# OS Command Injection in 'rdoc' documentation generator

rdoc's remove_unparseable opens files matching /tags$/i via Kernel#open, so a filename starting with '|' executes arbitrary shell commands during rdoc --all.

- Payout: hidden
- Severity: medium
- Program: Ruby
- Found by: sighook
- Disclosed: 2021-07-13
- CVE: CVE-2021-31799
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/1161691
- Library page: https://bugbountylibrary.com/r/h1%3A1161691
- Tags: area:oss domain:oss impact:rce kind:bounty platform:hackerone sev:medium tech:ruby technique:source-review vuln:command-injection

**Target:** rdoc documentation generator (remove_unparseable file handling)
**Root cause:** Kernel#open treats a filename beginning with '|' as a command to execute; remove_unparseable passes attacker-controlled filenames matching /tags$/i to open(file, 'rb').
**Steps:**
1. Create a file whose name matches the tags pattern and begins with a pipe: `touch '| touch evil.txt && echo tags'`
2. Run `rdoc --all` in that directory
3. remove_unparseable rejects files matching /tags$/i by calling open(file,'rb'), which executes `touch evil.txt && echo tags`
4. Confirm `evil.txt` created, proving command execution
**How found:** Code reading of remove_unparseable: noticed open(file,'rb') on a filename matching /tags$/i, and that Kernel#open interprets a leading '|' as a shell command.
**Exploitation:** Attacker plants a maliciously named file (e.g. `| cmd && echo tags`) deep in a project tree; when a victim runs rdoc --all, Kernel#open executes the embedded command with the victim's privileges.
**Insight:** In Ruby, any call to Kernel#open (not File.open) on a user-influenced path is a command-injection sink when the path can start with '|'; grep for bare `open(` in file-processing code, especially where filenames are attacker-controllable via repo contents.

