diff --git a/src/pentesting-ci-cd/github-security/README.md b/src/pentesting-ci-cd/github-security/README.md index 3f03027413..6d16a296cc 100644 --- a/src/pentesting-ci-cd/github-security/README.md +++ b/src/pentesting-ci-cd/github-security/README.md @@ -336,6 +336,31 @@ Hardening guidelines for services running external tools: - Execute tools in tightly isolated sandboxes with no sensitive environment variables mounted - Apply least‑privilege credentials and filesystem isolation, and restrict/deny outbound network egress for tools that don’t require internet access +## Git Push Infrastructure & GHES Security + +A Git server may treat `git push -o ` as harmless client metadata while internal backend services later parse it as **trusted security configuration**. If any service serializes user-controlled push options into a delimiter-based internal header, an attacker with **push access** may be able to **inject extra fields**, **override policy booleans**, reach **debug / enterprise-only code paths**, and even influence **hook execution**. + +### Delimiter injection into trusted internal metadata + +If user-controlled values are copied into an internal format such as `key=value;key=value` without escaping reserved delimiters, a push option can terminate its expected field and append new ones: + +```bash +git push -o 'x;security_flag=bool:false' origin HEAD +``` + +Common exploitation conditions: + +- The transport format uses a reserved delimiter such as `;` +- User-controlled values are copied verbatim into the internal header +- The receiver splits the header and inserts fields into a map/dictionary +- **Duplicate keys are accepted** and the last value silently wins +- Downstream services trust the parsed metadata as authenticated internal state + +This is especially dangerous when the injected fields control **sandboxing, feature flags, branch protections, hook configuration, or debug modes**. + +> [!NOTE] +> CVE-2026-3854 is a good public example of this pattern in GitHub/GHES: SSH `git push -o` input reached an internal `X-Stat` header, security-sensitive duplicate keys were accepted, sandbox selection depended on mutable metadata, and custom-hook path resolution allowed traversal to an existing executable. + ## Branch Protection Bypass - **Require a number of approvals**: If you compromised several accounts you might just accept your PRs from other accounts. If you just have the account from where you created the PR you cannot accept your own PR. However, if you have access to a **Github Action** environment inside the repo, using the **GITHUB_TOKEN** you might be able to **approve your PR** and get 1 approval this way. @@ -401,6 +426,8 @@ For more info check [https://www.chainguard.dev/unchained/what-the-fork-imposter ## References +- [Wiz Research: CVE-2026-3854: GitHub RCE Through X-Stat Push-Option Injection](https://www.wiz.io/blog/github-rce-vulnerability-cve-2026-3854) +- [GitHub: Securing the git push pipeline: Responding to a critical remote code execution vulnerability](https://github.blog/security/securing-the-git-push-pipeline-responding-to-a-critical-remote-code-execution-vulnerability/) - [How we exploited CodeRabbit: from a simple PR to RCE and write access on 1M repositories](https://research.kudelskisecurity.com/2025/08/19/how-we-exploited-coderabbit-from-a-simple-pr-to-rce-and-write-access-on-1m-repositories/) - [Rubocop extensions (require)](https://docs.rubocop.org/rubocop/latest/extensions.html) - [Authenticating with a GitHub App (JWT)](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app)