Project: Kortix-AI Suna (https://github.com/kortix-ai/suna)
Vulnerability Type: DOM-Based Cross-Site Scripting (XSS), Open Redirect
Severity: High (CVSS 3.1 Base Score: 8.8)
Report Date: April 10, 2026
A DOM-based Cross-Site Scripting (XSS) vulnerability has been discovered in Kortix AI Suna's /auth and /auth/password pages. The application improperly trusts a URL parameter (returnUrl), which is passed to router.replace and router.push. An attacker can craft a malicious link that, when opened by an authenticated user, performs a client-side redirect and executes arbitrary JavaScript in the context of their browser. This could lead to session hijacking, credential theft, internal network pivoting, and unauthorized actions performed on behalf of the victim.
- Affected Lines 1:
apps/frontend/src/app/auth/page.tsx, Line 199 - Affected Lines 2:
apps/frontend/src/app/auth/page.tsx, Line 833 - Affected Lines 3:
apps/frontend/src/app/auth/password/page.tsx, Line 29 - Affected Lines 4:
apps/frontend/src/app/auth/password/page.tsx, Line 55
Specific Lines:
// app/auth/page.tsx
function LoginContent() {
const router = useRouter();
const searchParams = useSearchParams();
// [...]
const rawReturnUrl = searchParams.get('returnUrl') || searchParams.get('redirect');
const returnUrl = rawReturnUrl?.match(/^\/instances\/[^/]+/) ? '/instances' : rawReturnUrl;
// [...]
useEffect(() => {
if (!isLoading && user) {
router.replace(returnUrl || '/instances'); // <-- sink (Line 199)
}
}, [user, isLoading, router, returnUrl]);(The other sinks and affected components are similar, and the other code snippets have been excluded for conciseness.)
As shown, the returnUrl parameter is taken from the browser's URL query and later passed to router.push or router.replace without validating against the javascript: protocol, leading to XSS. This happens because router.push and router.replace pass its parameter to window.location, which is known to parse and execute JavaScript in javascript: URIs. (Note: According to previous discussions, the stance from the NextJS maintainers is that library users are responsible for applying sanitisation for input passed to router.push and router.replace. See this NextJS GitHub issue.)
-
Attacker crafts a malicious URL:
https://HOST/auth/password?returnUrl=javascript:alert(window.origin) https://HOST/auth/password?returnUrl=javascript:alert(atob(document.cookie.split(%22;%22).find(r=%3Er.includes(%22kortix-auth%22))?.split(%22=%22)[1].substring(7)))A sophisticated payload could hide the JavaScript by inserting extra query parameters or using URL encoding to obfuscate the attack, making the URL appear less suspicious to victims.
-
Victim Action: An authenticated victim clicks the link and the XSS is triggered.
- Based on Affected Line #4,
app/auth/password/page.tsxLine 55, for unauthenticated users, the XSS may also trigger after a successful login.
- Based on Affected Line #4,
Impact - can exfiltrate access token:

PoC (app/auth/password/page.tsx):

Base Score: 8.8 (High)
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:L
- Attack Vector (AV): Network (N) – The vulnerability is exploitable remotely over the network via a crafted URL.
- Attack Complexity (AC): Low (L) – The attack does not require complex conditions.
- Privileges Required (PR): None (N) – No authentication or privileges are required by the attacker to trigger the vulnerability.
- User Interaction (UI): Required (R) – The victim must click on the attacker's malicious link and, if unauthenticated, perform a signup action.
- Scope (S): Changed (C) – The vulnerable component is the client-side code, but the impact (executing arbitrary script) affects the user's browser session and the data accessible within the application's security context.
- Confidentiality (C): High (H) – Successful exploitation could lead to complete loss of confidentiality. An attacker can call authenticated API endpoints and other information stored in the browser's context.
- Integrity (I): Low (L) – An attacker could modify data or perform actions on behalf of the user.
- Availability (A): Low (L) – In a reasonable worst case scenario, an administrator is compromised, leading to potential actions which affect the availability of the system.
Successful exploitation of this vulnerability has a High impact:
- Session Hijacking: An attacker could steal the victim's session token or authentication cookies, gaining complete access the account, files, and data.
- Arbitrary Actions: The script could use the victim's active session to make API requests, create, modify, or delete items, or perform any action the victim is authorized to do.
- Credential Theft: A script could present a fake login prompt within the context of the legitimate site to capture the user's credentials.
- Internal Network Pivoting: If the victim is within an internal network, the XSS could be used as a foothold to perform attacks against other internal systems from the victim's browser.
To fix this vulnerability, the application should validate and sanitise the returnUrl variable before using it for redirection. Here are a few approaches:
This approach only allows absolute URL paths such as /abc and protects against open redirects such as //example.com/path.
if (returnUrl && returnUrl.startsWith("/") && !returnUrl.startsWith("//")) {
redirectPath = returnUrl;
} else {
redirectPath = '/'; // Safe default
}This approach allows for http:// and https:// scheme in the redirect URL, but also protects against open redirect. Functionally, it is the same as Approach 1.
-
Validate the redirect path stays within the same origin and uses a safe scheme. Use the
URLconstructor to parse the path relative to the current origin and check both the origin and the protocol:function isValidRedirectPath(path) { try { // Parse relative paths correctly by providing the current origin as the base const url = new URL(path, window.location.origin); // Ensure the origin matches AND the scheme is either http: or https: return url.origin === window.location.origin && (url.protocol === 'http:' || url.protocol === 'https:'); } catch { return false; } }
This validation correctly handles:
- Relative paths like
/dashboard(resolves tohttps://example.com/dashboard) - Absolute paths within the same origin like
https://example.com/pipelines - Blocks cross-origin and open redirects like
//attacker.site/index.htmlandhttps://attacker.site/ - Blocks dangerous schemes like
javascript:,data:,vbscript:, etc.
- Relative paths like
-
Apply validation before any navigation. If
returnUrlpasses validation, it can be safely used; otherwise, fall back to a default safe path like/.if (returnUrl && isValidRedirectPath(returnUrl)) { redirectPath = returnUrl; } else { redirectPath = '/'; // Safe default }
Further, to mitigate the blast radius of future XSS risks, it is recommended that sensitive cookies related to session identification be marked as HttpOnly. This may require further adjuments to the client-side code. Currently, sb-kortix-auth-token has HttpOnly=False.
- 2026-04-10: Vulnerability discovered.
- 2026-04-10: Report sent to Suna security contact / maintainers.
- [Pending]: Maintainer acknowledges receipt of the report.
- [Pending]: Maintainer discloses security advisory, e.g. by publishing via GitHub's security advisory program.
A 45-day disclosure deadline is set for May 25, 2026, in accordance with standard coordinated disclosure practice. Details will be published on that date; or sooner if a fix is released or if the maintainer declines to address the issue. This approach is intended to inform users of potential risks in a timely manner. I understand that vendors may operate on their own timelines, and I am open to discussing adjustments to this deadline where warranted.
