Koa Open Redirect via Referrer Header (User-Controlled)
Published 29 Jul 2025 · Updated 30 Jul 2025
Affected packages
- Affected
- >=2.0.0 <2.16.2
- Fixed in
- 2.16.2
npm install koa@2.16.2- Affected
- >=3.0.0-alpha.0 <3.0.1
- Fixed in
- 3.0.1
npm install koa@3.0.1Details
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/
Is GHSA-jgmv-j7ww-jx2x in any of your client repos?
Checking one package by hand is fine. Checking it across forty client projects is not. NPMscan reads the lockfiles in every GitHub repo you pick, finds each project with an affected koa, and gives you the command that fixes it.
References
- Linkgithub.com/koajs/koa/security/advisories/GHSA-jgmv-j7ww-jx2x
- Advisorynvd.nist.gov/vuln/detail/CVE-2025-54420
- Linkgithub.com/koajs/koa/issues/1892
- Linkgithub.com/koajs/koa/issues/1892#issue-3213028583
- Linkgithub.com/koajs/koa/commit/422c551c63d00f24e2bbbdf492f262a5935bb1f0
- Packagegithub.com/koajs/koa
- Linkvuldb.com/?ctiid.317514
- Linkvuldb.com/?id.317514
- Linkvuldb.com/?submit.619741
Advisory data from OSV.dev (opens OSV.dev in a new tab), refreshed daily.