@@ -57,6 +57,45 @@ function generateAttackEvent(): Event {
5757 } ;
5858}
5959
60+ function generateAttackWaveEvent ( ) : Event {
61+ return {
62+ type : "detected_attack_wave" ,
63+ time : Date . now ( ) ,
64+ request : {
65+ ipAddress : undefined ,
66+ userAgent : undefined ,
67+ source : "express" ,
68+ } ,
69+ attack : {
70+ metadata : { } ,
71+ user : undefined ,
72+ } ,
73+ agent : {
74+ version : "1.0.0" ,
75+ library : "firewall-node" ,
76+ dryMode : false ,
77+ hostname : "hostname" ,
78+ packages : { } ,
79+ ipAddress : "ipAddress" ,
80+ preventedPrototypePollution : false ,
81+ nodeEnv : "" ,
82+ os : {
83+ name : "os" ,
84+ version : "version" ,
85+ } ,
86+ serverless : false ,
87+ incompatiblePackages : {
88+ prototypePollution : { } ,
89+ } ,
90+ stack : [ ] ,
91+ platform : {
92+ version : "version" ,
93+ arch : "arch" ,
94+ } ,
95+ } ,
96+ } ;
97+ }
98+
6099t . test ( "it throttles attack events" , async ( ) => {
61100 const api = new ReportingAPIForTesting ( ) ;
62101 const token = new Token ( "123" ) ;
@@ -250,3 +289,59 @@ t.test("it does not blow memory", async () => {
250289 // @ts -expect-error Private field but we need to check the length
251290 t . same ( throttled . events . length , 10 ) ;
252291} ) ;
292+
293+ t . test ( "it throttles attack wave events" , async ( ) => {
294+ const api = new ReportingAPIForTesting ( ) ;
295+ const token = new Token ( "123" ) ;
296+
297+ const throttled = new ReportingAPIRateLimitedClientSide ( api , {
298+ maxEventsPerInterval : 5 ,
299+ intervalInMs : 1000 ,
300+ } ) ;
301+
302+ t . same ( api . getEvents ( ) . length , 0 ) ;
303+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
304+ t . same ( api . getEvents ( ) . length , 1 ) ;
305+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
306+ t . same ( api . getEvents ( ) . length , 2 ) ;
307+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
308+ t . same ( api . getEvents ( ) . length , 3 ) ;
309+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
310+ t . same ( api . getEvents ( ) . length , 4 ) ;
311+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
312+ t . same ( api . getEvents ( ) . length , 5 ) ;
313+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
314+ t . same ( api . getEvents ( ) . length , 5 ) ;
315+
316+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
317+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
318+ t . same ( api . getEvents ( ) . length , 6 ) ;
319+ } ) ;
320+
321+ t . test ( "it throttles both event types at the same time" , async ( ) => {
322+ const api = new ReportingAPIForTesting ( ) ;
323+ const token = new Token ( "123" ) ;
324+
325+ const throttled = new ReportingAPIRateLimitedClientSide ( api , {
326+ maxEventsPerInterval : 5 ,
327+ intervalInMs : 1000 ,
328+ } ) ;
329+
330+ t . same ( api . getEvents ( ) . length , 0 ) ;
331+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
332+ t . same ( api . getEvents ( ) . length , 1 ) ;
333+ await throttled . report ( token , generateAttackEvent ( ) , 5000 ) ;
334+ t . same ( api . getEvents ( ) . length , 2 ) ;
335+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
336+ t . same ( api . getEvents ( ) . length , 3 ) ;
337+ await throttled . report ( token , generateAttackEvent ( ) , 5000 ) ;
338+ t . same ( api . getEvents ( ) . length , 4 ) ;
339+ await throttled . report ( token , generateAttackWaveEvent ( ) , 5000 ) ;
340+ t . same ( api . getEvents ( ) . length , 5 ) ;
341+ await throttled . report ( token , generateAttackEvent ( ) , 5000 ) ;
342+ t . same ( api . getEvents ( ) . length , 5 ) ;
343+
344+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
345+ await throttled . report ( token , generateAttackEvent ( ) , 5000 ) ;
346+ t . same ( api . getEvents ( ) . length , 6 ) ;
347+ } ) ;
0 commit comments