# DoS through cache poisoning using invalid HTTP parameters

Array-style `for[]` params poisoned Greenhouse's cached embed JS, corrupting iframe URIs and breaking customer job boards for ~20-30 minutes.

- Payout: hidden
- Severity: medium
- Program: Greenhouse.io
- Found by: irvinlim
- Disclosed: 2018-05-02
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/326639
- Library page: https://bugbountylibrary.com/r/h1%3A326639
- Tags: area:web domain:web impact:dos kind:bounty platform:hackerone sev:medium tech:cdn technique:param-pollution vuln:cache-poisoning vuln:dos

**Target:** boards.greenhouse.io embed job_board JS endpoint (CloudFront + app-layer cache)
**Root cause:** The embed JS endpoint reflects the raw query string into Grnhse.Settings URIs without normalizing array-style `for[]` params, and the response is cached keyed on the canonical `for=` URL, so the mutated body is served to legitimate requests.
**Steps:**
1. Request `https://boards.greenhouse.io/embed/job_board/js?for[]=twitter&for[]=&for[]=&...` (many empty `for[]` entries).
2. Observe the returned JS has `boardURI`/`applicationURI` containing the escaped array query string instead of `for=twitter`.
3. Fetch the canonical `https://boards.greenhouse.io/embed/job_board/js?for=twitter` and confirm it now returns the same corrupted JS from cache.
4. Load a customer site (e.g. Airbnb) embedding the SDK; the job_app/job_board iframes fail and show a Greenhouse error page.
**How found:** Reading a related report (HackerOne #298265), then testing array-style `for[]` params on the embed JS endpoint and noticing the reflected URIs; confirmed caching by re-fetching the canonical URL and via CloudFront IP identification.
**Exploitation:** Attacker sends a single crafted array-param request to poison the shared cache; subsequent legitimate embed loads for that board receive corrupted URIs, breaking the iframe for all visitors until cache expiry (~5-30 min observed).
**Escalation:** Repeated poisoning across many board IDs could extend the DoS window if cache TTLs and architecture were known.
**Insight:** When an endpoint reflects query params into a cached JS/config body, try array/duplicate param forms (`for[]=`, repeated keys) that the cache key normalizes away — the cache key and the reflected value can diverge, letting one request poison the canonical URL.

