ghsa-jgmv-j7ww-jx2x
Vulnerability from github
Summary
In the latest version of Koa, the back method used for redirect operations adopts an insecure implementation, which uses the user-controllable referrer header as the redirect target.
Details
on the API document https://www.koajs.net/api/response#responseredirecturl-alt, we can see:
response.redirect(url, [alt]) ``` Performs a [302] redirect to url. The string "back" is specially provided for Referrer support, using alt or "/" when Referrer does not exist.
ctx.redirect('back'); ctx.redirect('back', '/index.html'); ctx.redirect('/login'); ctx.redirect('http://google.com');
``` however, the "back" method is insecure:
- https://github.com/koajs/koa/blob/master/lib/response.js#L322
back (alt) { const url = this.ctx.get('Referrer') || alt || '/' this.redirect(url) },
Referrer Header is User-Controlled.
PoC
there is a demo for POC: ``` const Koa = require('koa') const serve = require('koa-static') const Router = require('@koa/router') const path = require('path')
const app = new Koa() const router = new Router()
// Serve static files from the public directory app.use(serve(path.join(__dirname, 'public')))
// Define routes router.get('/test', ctx => { ctx.redirect('back', '/index1.html') })
router.get('/test2', ctx => { ctx.redirect('back') })
router.get('/', ctx => { ctx.body = 'Welcome to the home page! Try accessing /test, /test2' })
app.use(router.routes()) app.use(router.allowedMethods())
const port = 3000
app.listen(port, () => {
console.log(Server running at http://localhost:${port}
)
})
**Proof Of Concept**
GET /test HTTP/1.1
Host: 127.0.0.1:3000
Referer: http://www.baidu.com
Connection: close
GET /test2 HTTP/1.1
Host: 127.0.0.1:3000
Referer: http://www.baidu.com
Connection: close
```
Impact
https://learn.snyk.io/lesson/open-redirect/
{ "affected": [ { "package": { "ecosystem": "npm", "name": "koa" }, "ranges": [ { "events": [ { "introduced": "2.0.0" }, { "fixed": "2.16.2" } ], "type": "ECOSYSTEM" } ] }, { "package": { "ecosystem": "npm", "name": "koa" }, "ranges": [ { "events": [ { "introduced": "3.0.0-alpha.0" }, { "fixed": "3.0.1" } ], "type": "ECOSYSTEM" } ] } ], "aliases": [ "CVE-2025-8129" ], "database_specific": { "cwe_ids": [ "CWE-601" ], "github_reviewed": true, "github_reviewed_at": "2025-07-29T19:11:25Z", "nvd_published_at": "2025-07-29T17:15:33Z", "severity": "LOW" }, "details": "## Summary\nIn the latest version of Koa, the back method used for redirect operations adopts an insecure implementation, which uses the user-controllable referrer header as the redirect target.\n\n## Details\non the API document https://www.koajs.net/api/response#responseredirecturl-alt, we can see:\n\n**response.redirect(url, [alt])**\n```\nPerforms a [302] redirect to url.\nThe string \"back\" is specially provided for Referrer support, using alt or \"/\" when Referrer does not exist.\n\nctx.redirect(\u0027back\u0027);\nctx.redirect(\u0027back\u0027, \u0027/index.html\u0027);\nctx.redirect(\u0027/login\u0027);\nctx.redirect(\u0027http://google.com\u0027);\n\n```\nhowever, the \"back\" method is insecure:\n\n- https://github.com/koajs/koa/blob/master/lib/response.js#L322\n```\n back (alt) {\n const url = this.ctx.get(\u0027Referrer\u0027) || alt || \u0027/\u0027\n this.redirect(url)\n },\n```\nReferrer Header is User-Controlled.\n\n\n## PoC\n\n**there is a demo for POC:**\n```\nconst Koa = require(\u0027koa\u0027)\nconst serve = require(\u0027koa-static\u0027)\nconst Router = require(\u0027@koa/router\u0027)\nconst path = require(\u0027path\u0027)\n\nconst app = new Koa()\nconst router = new Router()\n\n// Serve static files from the public directory\napp.use(serve(path.join(__dirname, \u0027public\u0027)))\n\n// Define routes\nrouter.get(\u0027/test\u0027, ctx =\u003e {\n ctx.redirect(\u0027back\u0027, \u0027/index1.html\u0027)\n})\n\nrouter.get(\u0027/test2\u0027, ctx =\u003e {\n ctx.redirect(\u0027back\u0027)\n})\n\nrouter.get(\u0027/\u0027, ctx =\u003e {\n ctx.body = \u0027Welcome to the home page! Try accessing /test, /test2\u0027\n})\n\napp.use(router.routes())\napp.use(router.allowedMethods())\n\nconst port = 3000\napp.listen(port, () =\u003e {\n console.log(`Server running at http://localhost:${port}`)\n}) \n```\n**Proof Of Concept**\n```\nGET /test HTTP/1.1\nHost: 127.0.0.1:3000\nReferer: http://www.baidu.com\nConnection: close\n\n\nGET /test2 HTTP/1.1\nHost: 127.0.0.1:3000\nReferer: http://www.baidu.com\nConnection: close\n```\n\n\n\n\n\n## Impact\nhttps://learn.snyk.io/lesson/open-redirect/", "id": "GHSA-jgmv-j7ww-jx2x", "modified": "2025-07-30T14:14:46Z", "published": "2025-07-29T19:11:25Z", "references": [ { "type": "WEB", "url": "https://github.com/koajs/koa/security/advisories/GHSA-jgmv-j7ww-jx2x" }, { "type": "ADVISORY", "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-54420" }, { "type": "WEB", "url": "https://github.com/koajs/koa/issues/1892" }, { "type": "WEB", "url": "https://github.com/koajs/koa/issues/1892#issue-3213028583" }, { "type": "WEB", "url": "https://github.com/koajs/koa/commit/422c551c63d00f24e2bbbdf492f262a5935bb1f0" }, { "type": "PACKAGE", "url": "https://github.com/koajs/koa" }, { "type": "WEB", "url": "https://vuldb.com/?ctiid.317514" }, { "type": "WEB", "url": "https://vuldb.com/?id.317514" }, { "type": "WEB", "url": "https://vuldb.com/?submit.619741" } ], "schema_version": "1.4.0", "severity": [ { "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:N/I:L/A:N", "type": "CVSS_V3" }, { "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:P", "type": "CVSS_V4" } ], "summary": "Koa Open Redirect via Referrer Header (User-Controlled)" }
Sightings
Author | Source | Type | Date |
---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.