CVE-2025-25290
Description
@octokit/request sends parameterized requests to GitHub’s APIs with sensible defaults in browsers and Node. Starting in version 1.0.0 and prior to versions 9.2.1 and 8.4.1, the regular expression /<([^>]+)>; rel="deprecation"/ used to match the link header in HTTP responses is vulnerable to a ReDoS (Regular Expression Denial of Service) attack. This vulnerability arises due to the unbounded nature of the regex's matching behavior, which can lead to catastrophic backtracking when processing specially crafted input. An attacker could exploit this flaw by sending a malicious link header, resulting in excessive CPU usage and potentially causing the server to become unresponsive, impacting service availability. Versions 9.2.1 and 8.4.1 fix the issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@octokit/requestnpm | >= 9.0.0-beta.1, < 9.2.1 | 9.2.1 |
@octokit/requestnpm | >= 1.0.0, < 8.4.1 | 8.4.1 |
Patches
3356411e32170fix: ReDos regex vulnerability, reported by @DayShift (#741)
4 files changed · +40 −11
package.json+2 −2 modified@@ -23,8 +23,8 @@ "author": "Gregor Martynus (https://github.com/gr2m)", "license": "MIT", "dependencies": { - "@octokit/endpoint": "^9.0.1", - "@octokit/request-error": "^5.1.0", + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" },
package-lock.json+10 −8 modified@@ -9,8 +9,8 @@ "version": "0.0.0-development", "license": "MIT", "dependencies": { - "@octokit/endpoint": "^9.0.1", - "@octokit/request-error": "^5.1.0", + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" }, @@ -1572,9 +1572,10 @@ } }, "node_modules/@octokit/endpoint": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", - "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "license": "MIT", "dependencies": { "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" @@ -1640,9 +1641,10 @@ } }, "node_modules/@octokit/request-error": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", - "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "license": "MIT", "dependencies": { "@octokit/types": "^13.1.0", "deprecation": "^2.0.0",
src/fetch-wrapper.ts+1 −1 modified@@ -56,7 +56,7 @@ export default function fetchWrapper( if ("deprecation" in headers) { const matches = - headers.link && headers.link.match(/<([^>]+)>; rel="deprecation"/); + headers.link && headers.link.match(/<([^<>]+)>; rel="deprecation"/); const deprecationLink = matches && matches.pop(); log.warn( `[@octokit/request] "${requestOptions.method} ${
test/request.test.ts+27 −0 modified@@ -18,6 +18,33 @@ const userAgent = `octokit-request.js/0.0.0-development ${getUserAgent()}`; const stringToArrayBuffer = require("string-to-arraybuffer"); describe("request()", () => { + it("Test ReDoS - attack string", () => { + const fakeFetch = async (url: string, options?: RequestInit) => { + const response = await fetch(url, options); + const fakeHeaders = new Headers(response.headers); + fakeHeaders.set("link", "<".repeat(100000) + ">"); + fakeHeaders.set("deprecation", "true"); + return new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers: fakeHeaders, + }); + }; + const startTime = performance.now(); + request("GET /repos/octocat/hello-world", { + request: { fetch: fakeFetch }, + }); + const endTime = performance.now(); + const elapsedTime = endTime - startTime; + const reDosThreshold = 2000; + expect(elapsedTime).toBeLessThanOrEqual(reDosThreshold); + if (elapsedTime > reDosThreshold) { + console.warn( + `🚨 Potential ReDoS Attack! getDuration method took ${elapsedTime.toFixed(2)} ms, exceeding threshold of ${reDosThreshold} ms.`, + ); + } + }); + it("is a function", () => { expect(request).toBeInstanceOf(Function); });
6bb29ba92a52fix: mitigate ReDos vulnerabilities & lint (#738)
3 files changed · +22 −26
package.json+2 −2 modified@@ -25,8 +25,8 @@ "author": "Gregor Martynus (https://github.com/gr2m)", "license": "MIT", "dependencies": { - "@octokit/endpoint": "^10.0.0", - "@octokit/request-error": "^6.0.1", + "@octokit/endpoint": "^10.1.3", + "@octokit/request-error": "^6.1.6", "@octokit/types": "^13.6.2", "fast-content-type-parse": "^2.0.0", "universal-user-agent": "^7.0.2"
package-lock.json+10 −17 modified@@ -9,8 +9,8 @@ "version": "0.0.0-development", "license": "MIT", "dependencies": { - "@octokit/endpoint": "^10.0.0", - "@octokit/request-error": "^6.0.1", + "@octokit/endpoint": "^10.1.3", + "@octokit/request-error": "^6.1.6", "@octokit/types": "^13.6.2", "fast-content-type-parse": "^2.0.0", "universal-user-agent": "^7.0.2" @@ -751,27 +751,18 @@ } }, "node_modules/@octokit/endpoint": { - "version": "10.0.0", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", + "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", "license": "MIT", "dependencies": { - "@octokit/types": "^12.0.0", + "@octokit/types": "^13.6.2", "universal-user-agent": "^7.0.2" }, "engines": { "node": ">= 18" } }, - "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { - "version": "20.0.0", - "license": "MIT" - }, - "node_modules/@octokit/endpoint/node_modules/@octokit/types": { - "version": "12.6.0", - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^20.0.0" - } - }, "node_modules/@octokit/oauth-authorization-url": { "version": "7.1.1", "dev": true, @@ -813,10 +804,12 @@ } }, "node_modules/@octokit/request-error": { - "version": "6.1.1", + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.6.tgz", + "integrity": "sha512-pqnVKYo/at0NuOjinrgcQYpEbv4snvP3bKMRqHaD9kIsk9u1LCpb2smHZi8/qJfgeNqLo5hNW4Z7FezNdEo0xg==", "license": "MIT", "dependencies": { - "@octokit/types": "^13.0.0" + "@octokit/types": "^13.6.2" }, "engines": { "node": ">= 18"
test/request.test.ts+10 −7 modified@@ -23,26 +23,29 @@ function stringToArrayBuffer(str: string) { describe("request()", () => { it("Test ReDoS - attack string", () => { - const originalFetch = globalThis.fetch; - globalThis.fetch = async (url, options) => { - const response = await originalFetch(url, options); + const fakeFetch = async (url, options) => { + const response = await fetch(url, options); const fakeHeaders = new Headers(response.headers); fakeHeaders.set("link", "<".repeat(100000) + ">"); fakeHeaders.set("deprecation", "true"); return new Response(response.body, { status: response.status, statusText: response.statusText, - headers: fakeHeaders + headers: fakeHeaders, }); }; const startTime = performance.now(); - request("GET /repos/octocat/hello-world"); + request("GET /repos/octocat/hello-world", { + request: { fetch: fakeFetch }, + }); const endTime = performance.now(); const elapsedTime = endTime - startTime; - const reDosThreshold = 2000; + const reDosThreshold = 2000; expect(elapsedTime).toBeLessThanOrEqual(reDosThreshold); if (elapsedTime > reDosThreshold) { - console.warn(`🚨 Potential ReDoS Attack! getDuration method took ${elapsedTime.toFixed(2)} ms, exceeding threshold of ${reDosThreshold} ms.`); + console.warn( + `🚨 Potential ReDoS Attack! getDuration method took ${elapsedTime.toFixed(2)} ms, exceeding threshold of ${reDosThreshold} ms.`, + ); } });
2 files changed · +25 −1
src/fetch-wrapper.ts+1 −1 modified@@ -96,7 +96,7 @@ export default async function fetchWrapper( if ("deprecation" in responseHeaders) { const matches = responseHeaders.link && - responseHeaders.link.match(/<([^>]+)>; rel="deprecation"/); + responseHeaders.link.match(/<([^<>]+)>; rel="deprecation"/); const deprecationLink = matches && matches.pop(); log.warn( `[@octokit/request] "${requestOptions.method} ${
test/request.test.ts+24 −0 modified@@ -22,6 +22,30 @@ function stringToArrayBuffer(str: string) { } describe("request()", () => { + it("Test ReDoS - attack string", () => { + const originalFetch = globalThis.fetch; + globalThis.fetch = async (url, options) => { + const response = await originalFetch(url, options); + const fakeHeaders = new Headers(response.headers); + fakeHeaders.set("link", "<".repeat(100000) + ">"); + fakeHeaders.set("deprecation", "true"); + return new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers: fakeHeaders + }); + }; + const startTime = performance.now(); + request("GET /repos/octocat/hello-world"); + const endTime = performance.now(); + const elapsedTime = endTime - startTime; + const reDosThreshold = 2000; + expect(elapsedTime).toBeLessThanOrEqual(reDosThreshold); + if (elapsedTime > reDosThreshold) { + console.warn(`🚨 Potential ReDoS Attack! getDuration method took ${elapsedTime.toFixed(2)} ms, exceeding threshold of ${reDosThreshold} ms.`); + } + }); + it("is a function", () => { expect(request).toBeInstanceOf(Function); });
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-rmvr-2pp2-xj38ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-25290ghsaADVISORY
- github.com/octokit/request.js/commit/34ff07ee86fc5c20865982d77391bc910ef19c68nvdWEB
- github.com/octokit/request.js/commit/356411e3217019aa9fc8a68f4236af82490873c2nvdWEB
- github.com/octokit/request.js/commit/6bb29ba92a52f7bf94469c3433707c682c17126cnvdWEB
- github.com/octokit/request.js/releases/tag/v8.4.1nvdWEB
- github.com/octokit/request.js/releases/tag/v9.2.1nvdWEB
- github.com/octokit/request.js/security/advisories/GHSA-rmvr-2pp2-xj38nvdWEB
News mentions
0No linked articles in our index yet.