TC-012 - I3 Sensitive client-side storage access

Reading from sessionStorage and writing to a DOM sink

positive / contextual I1 supporting SQ1SQ2SQ3

Context profile

A restrictive Content Security Policy is present. Session-like cookies use HttpOnly, Secure and SameSite.

Content Security Policy

default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; font-src 'self'; object-src 'none'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'

Cookies

CookieTypeHttpOnlySecureSameSite
tc_sessionsession-likeyesyesStrict

Cookie values are placeholders and are never collected. Of these attributes only HttpOnly decides whether JavaScript can read the cookie.

Test case

The script reads a value from sessionStorage and assigns it to innerHTML. A stored value is parsed as HTML - so storage access (I3) feeds a DOM sink (I1). The value is seeded by the code, not the URL, so its origin is internal: there is no proof of exploitability without knowing how it got there.

The same stored value is shown twice below: as the raw string read from sessionStorage (the source), and as the result of assigning it to innerHTML (the sink).

Value in sessionStorage (raw)

Rendered via innerHTML

What to observe

  • The raw panel shows the exact string in sessionStorage, including the literal <img> markup - this is the source.
  • Under C0 the rendered panel reads Stored value: [onerror executed]: innerHTML parsed the string and the onerror handler ran.
  • Under C1 the markup is still parsed (the image element is created) but the CSP blocks the inline handler, so it does not run - the image's alt text [image parsed, handler blocked] is shown instead.
  • The value survives in sessionStorage for the tab; reload to see it read again (clear it in DevTools → Application → Session Storage to reset).

Two findings are expected - the sessionStorage read and the innerHTML write - and they support each other: a stored value reaching an HTML-parsing sink is a stronger signal than either alone. It is still not proof of exploitability, because the value's origin is unknown.

Expected outcome

Purpose
Check whether storage access and DOM injection can support each other as combined signals.
Expected finding
Finding on sessionStorage and finding on innerHTML.
Expected interpretation
Possible stored or client-side DOM XSS indicator; no proof of exploitability without knowing how the storage value was created.
Expected priority
Medium (C1)
Notes
Deliberately combined because I3 can have both a storage role and a source role.

Expected priority is shown for the active context profile. Other profiles for this case: C0, C1.