# RCE via github import

Malicious GitHub import server returns a crafted Sawyer resource whose id hash injects Redis commands, escalating to RCE via a Sidekiq gadget.

- Payout: hidden
- Severity: critical
- Program: GitLab
- Found by: yvvdwf
- Disclosed: 2022-11-16
- Write-up quality: 9/10
- Original: https://hackerone.com/reports/1672388
- Library page: https://bugbountylibrary.com/r/h1%3A1672388
- Tags: area:web3 domain:web impact:rce kind:bounty platform:hackerone sev:critical tech:redis tech:ruby technique:chained technique:source-review vuln:command-injection vuln:deserialization

**Target:** GitLab GitHub import API (api/v4/import/github) and Redis cache
**Root cause:** Octokit/Sawyer converts attacker-controlled JSON keys into Ruby method calls; GitLab passes the resulting object's id into Redis cache keys, and redis-rb builds commands from to_s/bytesize, letting a nested hash inject raw Redis protocol bytes.
**Steps:**
1. Host a dummy GitHub API server returning a repo object whose id is `{"to_s": {"bytesize": 2, "to_s": "1234REDIS_COMMANDS"}}`.
2. POST to `/api/v4/import/github` with `github_hostname` pointing at the dummy server and a valid PRIVATE-TOKEN.
3. GitLab's already_imported? builds a Redis key from the Sawyer id; bytesize=2 truncates the prior command and the remaining bytes are parsed as new Redis commands.
4. Inject `lpush resque:gitlab:queue:system_hook_push` with a GitlabShellWorker/PagesWorker class_eval gadget to run shell commands.
5. Verify RCE via out-of-band callback (nc/curl) or file write.
**How found:** Continued mining the prior GitHub import report; noticed Sawyer::Resource maps hash keys to methods and that GitLab passes the raw id object into Redis caching, then reasoned about redis-rb's bytesize-based command construction to inject protocol bytes.
**Exploitation:** Attacker controls the GitHub hostname during import; the crafted id hash injects Redis commands into GitLab's Redis. A Sidekiq queue gadget (class_eval with IO.read pipe) executes arbitrary shell commands. Confirmed on gitlab.com via REPLICAOF ping callback, proving full Redis control.
**Escalation:** Redis command injection escalated to OS command execution by pushing a malicious job onto the resque:gitlab:queue:system_hook_push Sidekiq queue using a class_eval gadget.
**Insight:** When a library turns untrusted JSON keys into method calls (Sawyer/Octokit), trace where those objects flow into serializers like redis-rb that trust to_s/bytesize; a nested hash can smuggle raw protocol bytes past length framing.
