Skip to main content
sus.botdocs
  • SEO
  • AI
  • QA
  • Privacy
  • Accessibility
  • Security
  1. Docs
  2. Security
  3. Session tokens readable in the browser
  4. A JSON Web Token in the browser is unsigned, never expires, lives long, or sits in web storage

Security finding

A JSON Web Token in the browser is unsigned, never expires, lives long, or sits in web storage

Security Warning Severity: Medium

Part of the audit Session tokens readable in the browser. Finding id: security.jwtInBrowser.

What it costs you

Whoever holds a session token is logged in as that visitor.

What to do

Sign tokens, give them a short lifetime, and keep them where scripts cannot read them.

What it checks

  • Login token has no signature
  • Login token never expires
  • Login token lasts too long
  • Login token kept in browser storage

How to fix it

Sign the token and check the algorithm

  1. Find the code or service that issues the token held in [container] and have it sign tokens with a key, for example with HS256 or RS256.
  2. In the code that checks tokens, accept only the algorithm you sign with and reject alg none. Most JWT libraries take the allowed algorithms as a setting.

How to check: Decode the header of a new token in your browser's developer tools: alg is not none.

Give the token a short lifetime

  1. Set an exp claim on every token the browser holds, a short time after it is issued.
  2. If visitors must stay logged in longer, issue a new short token from a refresh token kept in an HttpOnly cookie.
  3. Have the server reject tokens without exp or past it.

How to check: Decode a new token: exp is present and close to iat.

Move the token out of web storage

  1. Have the server set the token, or the session it stands for, as a cookie marked HttpOnly, Secure and SameSite=Lax, instead of handing it to a script that writes [where found].
  2. If a script must hold the token, keep it in a variable in memory only and get a new one after a reload.
  3. Remove the code that writes [container] to [where found], and delete the key on the next visit.

How to check: Open the developer tools on [example url], Application tab: [where found] has no key [container].

Thresholds

Thresholds for A JSON Web Token in the browser is unsigned, never expires, lives long, or sits in web storage
NameDefaultMeaning
max_lifetime_hours24Longest acceptable lifetime of a token the browser holds, in hours. Starting value, not taken from a standard.
  • All audits
  • About sus.bot
  • Open the app
  • Contact support