# Synthetics Recorder: Code injection when recording website with malicious content

Synthetics Recorder's quote() escaping failed inside a multi-line comment, letting a malicious site's URL break out and inject arbitrary code executed when the recording is replayed.

- Payout: hidden
- Severity: high
- Program: Elastic
- Found by: dee-see
- Disclosed: 2023-04-08
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/1636382
- Library page: https://bugbountylibrary.com/r/h1%3A1636382
- Tags: area:os domain:desktop impact:privesc impact:rce kind:bounty platform:hackerone sev:high tech:electron tech:nodejs technique:source-review vuln:command-injection

**Target:** Synthetics Recorder Electron app / syntheticsGenerator.ts
**Root cause:** waitForNavigation embeds the URL inside a /* ... */ comment and only escapes single quotes; a URL containing */ closes the comment and injects executable JS.
**Steps:**
1. Start Synthetics Recorder, enter `http://deesee.xyz:4567` as starting URL, click Start Recording
2. On the malicious page click a link to `https://gitlab.com/dee-see?query=*/require(`child_process`).exec(`touch$IFS/tmp/dee-see`)/*`
3. Close browser, click Export: generated code contains `page.waitForNavigation(/*{ url: '...*/require(`child_process`).exec(`touch$IFS/tmp/dee-see`)/*' }*/)`
4. Save export, run `npm init -y; npm install @elastic/synthetics; npx @elastic/synthetics .`
5. Observe `/tmp/dee-see` created, confirming command execution
**How found:** Noticed quote() escaping is applied but the URL is placed inside a multi-line comment; realized */ can terminate the comment without needing escaped single quotes, then crafted a URL payload using $IFS to avoid space encoding.
**Exploitation:** Attacker controls a site the victim records; a crafted navigation URL breaks out of the comment in the generated test script. When the victim runs the exported suite via the synthetics runner (dev machine or CI), the injected require('child_process').exec runs arbitrary commands.
**Escalation:** In-recorder 'test' feature limits impact (no require); saving and replaying via @elastic/synthetics runner yields full RCE on developer/CI hosts, enabling privilege escalation inside a company.
**Insight:** When a value is escaped for string context but embedded in a comment, the comment terminator (*/ or -->) is an unescaped breakout primitive; test comment-wrapped interpolations with terminator sequences rather than quote characters.
