@@ -9,6 +9,44 @@ const ORG2 = { id: 2 };
99
1010const TestOctokit = Octokit . plugin ( paginateRest , restEndpointMethods ) ;
1111describe ( "pagination" , ( ) => {
12+ it ( "Test ReDoS - attack string" , async ( ) => {
13+ const ReDosOctokit = Octokit . plugin ( paginateRest ) ;
14+ const octokit = new ReDosOctokit ( {
15+ auth : "your-github-token" ,
16+ } ) ;
17+ octokit . hook . wrap ( "request" , async ( ) => {
18+ const maliciousLinkHeader = "" + "<" . repeat ( 100000 ) + ">" ;
19+ return {
20+ data : [ ] ,
21+ headers : {
22+ link : maliciousLinkHeader ,
23+ } ,
24+ status : 200 ,
25+ url : "" ,
26+ } ;
27+ } ) ;
28+ const startTime = performance . now ( ) ;
29+ try {
30+ for await ( const normalizedResponse of octokit . paginate . iterator (
31+ "GET /repos/{owner}/{repo}/issues" ,
32+ { owner : "DayShift" , repo : "ReDos" , per_page : 100 } ,
33+ ) ) {
34+ normalizedResponse ;
35+ }
36+ } catch ( error ) {
37+ // pass
38+ }
39+ const endTime = performance . now ( ) ;
40+ const elapsedTime = endTime - startTime ;
41+ const reDosThreshold = 2000 ;
42+
43+ expect ( elapsedTime ) . toBeLessThanOrEqual ( reDosThreshold ) ;
44+ if ( elapsedTime > reDosThreshold ) {
45+ console . warn (
46+ `🚨 Potential ReDoS Attack! getDuration method took ${ elapsedTime . toFixed ( 2 ) } ms, exceeding threshold of ${ reDosThreshold } ms.` ,
47+ ) ;
48+ }
49+ } ) ;
1250 it ( ".paginate()" , async ( ) => {
1351 const mock = fetchMock
1452 . sandbox ( )
0 commit comments