Skip to content

Commit 6c9c5be

Browse files
Merge commit from fork
* Fix regular term vulnerability * add test to prevent future regressions * Fix the other regular term vulnerability * Trigger Build --------- Co-authored-by: DayShift <[email protected]> Co-authored-by: DayShift <[email protected]>
1 parent e472e22 commit 6c9c5be

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

src/parse.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export function parse(options: EndpointDefaults): RequestOptions {
5959
if (url.endsWith("/graphql")) {
6060
if (options.mediaType.previews?.length) {
6161
const previewsFromAcceptHeader =
62-
headers.accept.match(/[\w-]+(?=-preview)/g) || ([] as string[]);
62+
headers.accept.match(/(?<![\w-])[\w-]+(?=-preview)/g) || ([] as string[]);
6363
headers.accept = previewsFromAcceptHeader
6464
.concat(options.mediaType.previews!)
6565
.map((preview) => {

src/util/extract-url-variable-names.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const urlVariableRegex = /\{[^}]+\}/g;
1+
const urlVariableRegex = /\{[^{}}]+\}/g;
22

33
function removeNonChars(variableName: string) {
4-
return variableName.replace(/^\W+|\W+$/g, "").split(/,/);
4+
return variableName.replace(/(?:^\W+)|(?:(?<!\W)\W+$)/g, "").split(/,/);
55
}
66

77
export function extractUrlVariableNames(url: string) {

test/parse.test.ts

+90
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,94 @@ describe("endpoint.parse()", () => {
5252

5353
expect(input.headers.accept).toEqual("application/vnd.github.v3+json");
5454
});
55+
56+
it("Test ReDoS - attack string #1", async () => {
57+
const startTime = performance.now();
58+
try {
59+
endpoint.parse({
60+
method: "POST",
61+
url: "/graphql", // Ensure that the URL ends with "/graphql"
62+
headers: {
63+
accept: "" + "A".repeat(100000) + "-", // Pass in the attack string
64+
"content-type": "text/plain",
65+
"user-agent": "Your User Agent String Here",
66+
},
67+
mediaType: {
68+
previews: ["test-preview"], // Ensure that mediaType.previews exists and has values
69+
format: "raw", // Optional media format
70+
},
71+
baseUrl: "https://api.github.com",
72+
});
73+
} catch (error) {
74+
// pass
75+
}
76+
const endTime = performance.now();
77+
const elapsedTime = endTime - startTime;
78+
const reDosThreshold = 2000;
79+
80+
expect(elapsedTime).toBeLessThanOrEqual(reDosThreshold);
81+
if (elapsedTime > reDosThreshold) {
82+
console.warn(`🚨 Potential ReDoS Attack! getDuration method took ${elapsedTime.toFixed(2)} ms, exceeding threshold of ${reDosThreshold} ms.`);
83+
}
84+
});
85+
86+
it("Test ReDoS - attack string #2", async () => {
87+
const startTime = performance.now();
88+
try {
89+
endpoint.parse({
90+
method: "POST",
91+
url: "{".repeat(100000) + "@", // Pass in the attack string
92+
headers: {
93+
accept: "application/vnd.github.v3+json",
94+
"content-type": "text/plain",
95+
"user-agent": "Your User Agent String Here",
96+
},
97+
mediaType: {
98+
previews: ["test-preview"], // Ensure that mediaType.previews exists and has values
99+
format: "raw", // Optional media format
100+
},
101+
baseUrl: "https://api.github.com",
102+
});
103+
} catch (error) {
104+
// pass
105+
}
106+
const endTime = performance.now();
107+
const elapsedTime = endTime - startTime;
108+
const reDosThreshold = 2000;
109+
110+
expect(elapsedTime).toBeLessThanOrEqual(reDosThreshold);
111+
if (elapsedTime > reDosThreshold) {
112+
console.warn(`🚨 Potential ReDoS Attack! getDuration method took ${elapsedTime.toFixed(2)} ms, exceeding threshold of ${reDosThreshold} ms.`);
113+
}
114+
});
115+
116+
it("Test ReDoS - attack string #3", async () => {
117+
const startTime = performance.now();
118+
try {
119+
endpoint.parse({
120+
method: "POST",
121+
url: "{"+"00"+"\u0000".repeat(100000)+"a!a"+"}", // Pass in the attack string
122+
headers: {
123+
accept: "application/vnd.github.v3+json",
124+
"content-type": "text/plain",
125+
"user-agent": "Your User Agent String Here",
126+
},
127+
mediaType: {
128+
previews: ["test-preview"],
129+
format: "raw",
130+
},
131+
baseUrl: "https://api.github.com",
132+
});
133+
} catch (error) {
134+
// pass
135+
}
136+
const endTime = performance.now();
137+
const elapsedTime = endTime - startTime;
138+
const reDosThreshold = 2000;
139+
140+
expect(elapsedTime).toBeLessThanOrEqual(reDosThreshold);
141+
if (elapsedTime > reDosThreshold) {
142+
console.warn(`🚨 Potential ReDoS Attack! getDuration method took ${elapsedTime.toFixed(2)} ms, exceeding threshold of ${reDosThreshold} ms.`);
143+
}
144+
});
55145
});

0 commit comments

Comments
 (0)