You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[SECURITY] Dear Next Maintainers, what is up with PR#88185?
#95505
I would like to ask what is the project's current stance on the useRouter XSS issue? Where is the security boundary and who bears the responsibility?
I understand that the purpose and end result is to protect users. But at the same time, the lack of a security advisory creates a conundrum for security analysts.
Let me share my thoughts on why this is an issue. (There are actually many small issues which make this issue very complicated. But let's walk through them.)
In 2023, the XSS was reported as a security issue (#50093). The Next.js maintainer (now member?) responded to the issue with:
Hi, this isn't a bug in Next.js itself as this is equivalent to doing window.location.href = 'javascript:alert(1)'. You shouldn't pass untrusted input to router.push/replace the same as you wouldn't to window.location.href.
The key point is that this sets a clear precedent that the XSS issue is an application-level issue. The fix (and thus advisory) all happens on the software using Next.js, and not on Next.js itself.
Security researchers have understood this clearly. If you search for combinations of the words "Next", "router", "XSS", "cve" along with relevant other Google dorking tricks, you'll notice that such vulnerabilities have been reported at the application-level over the past three years.
PR#88185 dismantles this precedent!
Previously, a security researcher discovers a bug, reports it to the application maintainers, and they fix it by applying sanitisation.
Now, the sanitisation has already been applied by Next.
All's fine and dandy, right?
Well, not really.
Many applications use this pattern of passing attacker-controllable data to router.push or replace. What happens to those vulnerable applications which are unaware of the specific patch?
Even if the application updates, users may be self-hosting. What happens to the users using the application in its vulnerable version? Can you expect the application to be liable if there was no notification provided?
Who is responsible for applying sanitisation now? Where does the security boundary lie?
Will documentation be updated? If not, why? If so, when?
Perhaps the issue still isn't clear. Let me provide a different perspective.
Angle 2: A Black Box, User Perspective
Let's suppose we ignore the changes, the contents of PR#88185. Let's treat it as a black box, which made some unknown (but intentional) modification to the project.
Let's suppose Bob the in-house security analyst is reviewing two versions of an app. In the first version, the app uses Next.js v15 and is vulnerable to DOM-XSS via router.push. In the second version, it uses Next.js v16.2.0 but is not vulnerable.
No other changes were made to the app's source code besides updating the Next.js version from v15 to v16.2.0. However! The first version is insecure, it had the DOM-XSS vulnerability. The second version is secure, no DOM-XSS.
Bob is now in a conundrum. Previous versions of the app were vulnerable. Per their security policy, their team should release an advisory notifying users to patch and upgrade. But the fix wasn't in their app's code. It was a package-level fix where a version bump was all the app needed! So why should Bob's team release an advisory?
There was no NPM advisory, which would report the vulnerability downstream across the ecosystem!
Fine, Bob thought. Sometimes the ecosystem is fragmented and downstream libraries/applications publish their own advisory.
But here's the thing: this is usually done with or after the initial advisory from the affected package!
And another thing: Bob's colleague Carla who's auditing a different app just received notice that their application got hacked and some blackhat made unauthorised API calls with administrator privileges.
Carla did not get notified about the Next.js vulnerability! Their team had accepted the risk of other vulns (for various reasons), but they were completely blind-sided by this silent fix!
In a similar scenario, Daniel's team— responsible for yet another app— received word that their app was hacked. But that's crazy, Daniel thought, because they regularly keep their app up-to-date. It turns out the client disabled auto-updates and were not aware there were security issues with the app! I need to highlight the difference between Carla and Daniel's situation: Carla's client got pwned because the app team was unaware of the security issue and did not update. Daniel's client got pwned because Daniel's team was unaware and hence the client was unaware, and ultimately did not update.
However, the typical security signals of ownership and responsibility are not there: no advisory, no backporting, no CVE assignment.
Due to lack of advisory, applications (in general: Next.js users) don't receive notification of the bug.
Due to Next.js users not receiving notification, end-users don't receive notification and potentially put themselves (and their data) at risk.
If responsibility is still application-level and this is simply a defense-in-depth, how do we explain the black-box perspective, where in a previous version an app is insecure, but in a later version the app is secure, all due to a version bump?
Where to go from here?
My burning questions:
What is Next's current stance?
Will an advisory be published?
Other Tangents:
Documentation gaps. If Next fully embraces responsibility, then it is no longer an application issue. Will it be updated? If so, when?
What about Open Redirect? Should the security model be shared? How should it be defined? Package-level (Next.js) protection against XSS, but application-level protection against open redirects? Have package-level protection against open redirects but allow a configurable opt-in?
I think you would also find HackerOne Report #3687674 relevant. I want to make it clear that it is a completely separate, but relevant, finding which partially bypasses PR#88185. I believe the report was wrongly closed yet still deserves attention by Next maintainers. I have provided multiple justifications as to why the report is in-scope and valid, but it appears triage does not want to hear about it.
Timeline
2023.01.20 - Documented evidence shows that the first disclosure to Next.js regarding the XSS issue was made on this day.
2023.05.20 - A GitHub issue was posted by hamid-bhz sharing the XSS. A maintainer replied with a won't fix. This is the first publicly documented report which sets a precedent. The implications are that fixes (and therefore advisories) need to be handled on the application-level rather than the package-level.
2024.04.12 - A blog post was published by Mobin Yardim on Medium sharing the XSS. The post documents the author's exchange with Next.js and how the vulnerability was first reported in Jan 20, 2023.
2026.01.08 - PR#88185 was merged to canary, Next.js' development branch.
2026.02 - I discovered an XSS issue during a penetration test. After tracing the root cause, I determined it was due to unsanitised data passed to Next router. This was my first encounter of the pattern.
2026.03.07 - I discovered the same pattern in other Next.js applications and was able to reproduce XSS. Due to the precedent from 2023 and without knowledge of PR#88185, I privately reported the issue to the app maintainers.
2026.03.12 - I discovered the existence of PR#88185, which at this moment has been merged but yet to be released. I attempted to reach out privately to Next maintainers. No response. I also attempted going through Vercel’s security disclosure program, but was blocked by triage as their system was not designed to handle candid discussions about silent patches.
2026.03.19 - The commit from PR#88185 was released in Next.js 16.2.0. But it was not backported to 16.1.7 even though other security fixes were. No advisory or CVE was issued.
2026.04.21 - I opened HackerOne report 3687674. This is a completely new finding which partially bypasses PR#88185.
2026.07.05 - This "request for comment" was posted on GitHub discussions.
Reporting
Posting on GitHub for visibility. I have previously reported this through multiple channels to no avail.
Multiple CVD reports through responsible.disclosure@vercel.com (i.e. "Vercel Open Source" program at HackerOne)
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Dear Next maintainers,
I would like to ask what is the project's current stance on the useRouter XSS issue? Where is the security boundary and who bears the responsibility?
I understand that the purpose and end result is to protect users. But at the same time, the lack of a security advisory creates a conundrum for security analysts.
Let me share my thoughts on why this is an issue. (There are actually many small issues which make this issue very complicated. But let's walk through them.)
Refs
First, some references to past issues:
Angle 1: A Historical Perspective
In 2023, the XSS was reported as a security issue (#50093). The Next.js maintainer (now member?) responded to the issue with:
The key point is that this sets a clear precedent that the XSS issue is an application-level issue. The fix (and thus advisory) all happens on the software using Next.js, and not on Next.js itself.
Security researchers have understood this clearly. If you search for combinations of the words "Next", "router", "XSS", "cve" along with relevant other Google dorking tricks, you'll notice that such vulnerabilities have been reported at the application-level over the past three years.
PR#88185 dismantles this precedent!
Previously, a security researcher discovers a bug, reports it to the application maintainers, and they fix it by applying sanitisation.
Now, the sanitisation has already been applied by Next.
All's fine and dandy, right?
Well, not really.
Many applications use this pattern of passing attacker-controllable data to router.push or replace. What happens to those vulnerable applications which are unaware of the specific patch?
Even if the application updates, users may be self-hosting. What happens to the users using the application in its vulnerable version? Can you expect the application to be liable if there was no notification provided?
Who is responsible for applying sanitisation now? Where does the security boundary lie?
Will documentation be updated? If not, why? If so, when?
Perhaps the issue still isn't clear. Let me provide a different perspective.
Angle 2: A Black Box, User Perspective
Let's suppose we ignore the changes, the contents of PR#88185. Let's treat it as a black box, which made some unknown (but intentional) modification to the project.
Let's suppose Bob the in-house security analyst is reviewing two versions of an app. In the first version, the app uses Next.js v15 and is vulnerable to DOM-XSS via
router.push. In the second version, it uses Next.js v16.2.0 but is not vulnerable.No other changes were made to the app's source code besides updating the Next.js version from v15 to v16.2.0. However! The first version is insecure, it had the DOM-XSS vulnerability. The second version is secure, no DOM-XSS.
Bob is now in a conundrum. Previous versions of the app were vulnerable. Per their security policy, their team should release an advisory notifying users to patch and upgrade. But the fix wasn't in their app's code. It was a package-level fix where a version bump was all the app needed! So why should Bob's team release an advisory?
There was no NPM advisory, which would report the vulnerability downstream across the ecosystem!
Fine, Bob thought. Sometimes the ecosystem is fragmented and downstream libraries/applications publish their own advisory.
But here's the thing: this is usually done with or after the initial advisory from the affected package!
And another thing: Bob's colleague Carla who's auditing a different app just received notice that their application got hacked and some blackhat made unauthorised API calls with administrator privileges.
Carla did not get notified about the Next.js vulnerability! Their team had accepted the risk of other vulns (for various reasons), but they were completely blind-sided by this silent fix!
In a similar scenario, Daniel's team— responsible for yet another app— received word that their app was hacked. But that's crazy, Daniel thought, because they regularly keep their app up-to-date. It turns out the client disabled auto-updates and were not aware there were security issues with the app! I need to highlight the difference between Carla and Daniel's situation: Carla's client got pwned because the app team was unaware of the security issue and did not update. Daniel's client got pwned because Daniel's team was unaware and hence the client was unaware, and ultimately did not update.
Do you see the conundrum?
To summarise the conundrum...
Where to go from here?
My burning questions:
Other Tangents:
Documentation gaps. If Next fully embraces responsibility, then it is no longer an application issue. Will it be updated? If so, when?
What about Open Redirect? Should the security model be shared? How should it be defined? Package-level (Next.js) protection against XSS, but application-level protection against open redirects? Have package-level protection against open redirects but allow a configurable opt-in?
I think you would also find HackerOne Report #3687674 relevant. I want to make it clear that it is a completely separate, but relevant, finding which partially bypasses PR#88185. I believe the report was wrongly closed yet still deserves attention by Next maintainers. I have provided multiple justifications as to why the report is in-scope and valid, but it appears triage does not want to hear about it.
Timeline
Reporting
Posting on GitHub for visibility. I have previously reported this through multiple channels to no avail.
responsible.disclosure@vercel.com(i.e. "Vercel Open Source" program at HackerOne)All reactions