-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Add secret scan for pull requests #30937
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,171 @@ | ||||||
| # Secret Scanning with Gitleaks | ||||||
|
|
||||||
| This repository uses [Gitleaks](https://github.com/gitleaks/gitleaks) to prevent secrets (API keys, passwords, private keys, tokens) from being committed to the codebase. | ||||||
|
|
||||||
| ## How It Works | ||||||
|
|
||||||
| ### Automated CI Scanning | ||||||
| - **Runs on:** All pull requests and pushes to `main` and `release-*` branches | ||||||
| - **What it scans:** Only new commits in your PR via `gitleaks-action@v2` with `GITLEAKS_ARGS: --log-opts="main..HEAD"` (not the entire git history despite `fetch-depth: 0`) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify trigger targets and gitleaks range args from workflow.
# Expected: pull_request includes main/release-*; gitleaks arg is hardcoded main..HEAD.
set -euo pipefail
echo "== Workflow trigger block =="
sed -n '1,40p' .github/workflows/secret-scan.yml
echo
echo "== Gitleaks step and args =="
rg -n -C3 'gitleaks-action@v2|GITLEAKS_ARGS|log-opts' .github/workflows/secret-scan.ymlRepository: openshift/origin Length of output: 1711 🏁 Script executed: cat -n .github/SECRET_SCANNING.md | head -20Repository: openshift/origin Length of output: 1069 🏁 Script executed: # Check for any conditional logic in the workflow that might adjust gitleaks args based on target branch
rg -n 'if:|env\.|GITLEAKS_ARGS' .github/workflows/secret-scan.ymlRepository: openshift/origin Length of output: 178 Gitleaks scan range is hardcoded to Line 9 claims "Only new commits in your PR," but 🤖 Prompt for AI Agents |
||||||
| - **Speed:** ~4 mins for full repository scan | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Speed line conflicts with stated scan mode. Line 10 references “full repository scan,” but Line 9 describes PR-commit scanning. Reword this to avoid mixing two different scan scopes. Suggested doc edit-- **Speed:** ~4 mins for full repository scan
+- **Speed:** Typically completes in a few minutes (depends on commit range and repository size)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| - **Action:** Blocks PR merge if secrets are detected | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid overstating merge-blocking behavior. Line 11 implies guaranteed merge blocking, but that depends on branch protection/required checks outside this file. Safer wording is that CI fails when findings are detected. Proposed doc fix-- **Action:** Blocks PR merge if secrets are detected
+- **Action:** Fails the secret-scan CI check if secrets are detected🤖 Prompt for AI Agents |
||||||
|
|
||||||
| ### What Gitleaks Detects | ||||||
| - API keys (AWS, GitHub, GitLab, Slack, etc.) | ||||||
| - Private keys (RSA, SSH, PGP, TLS) | ||||||
| - Database credentials and connection strings | ||||||
| - OAuth and JWT tokens | ||||||
| - Generic secrets (password=, api_key=, etc.) | ||||||
| - High entropy strings (randomized secrets) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor grammar: Use hyphenated compound modifier. "High entropy strings" should be hyphenated as "high-entropy strings" when used as a compound modifier before a noun. As per static analysis tools. 📝 Suggested fix - Generic secrets (password=, api_key=, etc.)
-- High entropy strings (randomized secrets)
+- High-entropy strings (randomized secrets)📝 Committable suggestion
Suggested change
🧰 Tools🪛 LanguageTool[grammar] ~19-~19: Use a hyphen to join words. (QB_NEW_EN_HYPHEN) 🤖 Prompt for AI Agents |
||||||
|
|
||||||
| ### What It Ignores | ||||||
| - Test fixtures in `test/` directories | ||||||
| - Vendor code in `vendor/` | ||||||
| - Example files in `examples/` | ||||||
| - Mock/placeholder credentials | ||||||
| - Variable names like `password` or `apiKey` | ||||||
|
|
||||||
| ## Running Locally | ||||||
|
|
||||||
| ### Installation | ||||||
|
|
||||||
| **macOS (Homebrew):** | ||||||
| ```bash | ||||||
| brew install gitleaks | ||||||
| ``` | ||||||
|
|
||||||
| **Linux:** | ||||||
| ```bash | ||||||
| # Docker/Podman | ||||||
| docker pull ghcr.io/gitleaks/gitleaks:latest | ||||||
|
|
||||||
| # Or download binary | ||||||
| wget https://github.com/gitleaks/gitleaks/releases/latest/download/gitleaks_linux_x64.tar.gz | ||||||
| tar -xzf gitleaks_linux_x64.tar.gz | ||||||
| sudo mv gitleaks /usr/local/bin/ | ||||||
| ``` | ||||||
|
|
||||||
| ### Scan Before Committing | ||||||
|
|
||||||
| **Scan staged changes (recommended):** | ||||||
| ```bash | ||||||
| gitleaks protect --staged --verbose | ||||||
| ``` | ||||||
|
|
||||||
| **Scan entire working directory:** | ||||||
| ```bash | ||||||
| gitleaks detect --source . --config .gitleaks.toml --verbose | ||||||
| ``` | ||||||
|
|
||||||
| **Scan specific file:** | ||||||
| ```bash | ||||||
| gitleaks detect --source path/to/file.go --no-git | ||||||
| ``` | ||||||
|
|
||||||
| ## Handling Detections | ||||||
|
|
||||||
| ### If Gitleaks Flags Your Commit | ||||||
|
|
||||||
| **1. Is it a real secret?** | ||||||
|
|
||||||
| If YES: | ||||||
| - **Remove the secret immediately** | ||||||
| - Use environment variables instead: `os.Getenv("API_KEY")` | ||||||
| - Store secrets in Kubernetes Secrets, Vault, or similar | ||||||
| - Rotate/revoke the exposed secret if it was already pushed | ||||||
|
|
||||||
| If NO (false positive): | ||||||
| - Continue to step 2 | ||||||
|
|
||||||
| **2. For legitimate test fixtures or examples:** | ||||||
|
|
||||||
| Add to `.gitleaks.toml` allowlist: | ||||||
|
|
||||||
| ```toml | ||||||
| [allowlist] | ||||||
| paths = [ | ||||||
| '''path/to/test/file\.go$''', | ||||||
| ] | ||||||
|
|
||||||
| # OR for specific values | ||||||
| regexes = [ | ||||||
| '''specific-test-value-to-ignore''', | ||||||
| ] | ||||||
| ``` | ||||||
|
|
||||||
| **3. For one-time overrides (use sparingly):** | ||||||
|
|
||||||
| Add inline comment in your code: | ||||||
| ```go | ||||||
| password := "test-password" // gitleaks:allow | ||||||
| ``` | ||||||
|
|
||||||
| ## Configuration | ||||||
|
|
||||||
| The `.gitleaks.toml` file controls what gets scanned and ignored: | ||||||
|
|
||||||
| - **Excluded paths:** `test/`, `vendor/`, `examples/`, `*.md` | ||||||
| - **Excluded patterns:** Test credentials, base64 test values, common examples | ||||||
| - **Rules:** Extends default gitleaks ruleset | ||||||
|
|
||||||
| To modify exclusions, edit `.gitleaks.toml` and test: | ||||||
| ```bash | ||||||
| gitleaks detect --source . --config .gitleaks.toml --verbose | ||||||
| ``` | ||||||
|
|
||||||
| ## Best Practices | ||||||
|
|
||||||
| ### DO: | ||||||
| - ✅ Use environment variables for secrets | ||||||
| - ✅ Use Kubernetes Secrets or external secret management | ||||||
| - ✅ Run `gitleaks protect --staged` before committing sensitive changes | ||||||
| - ✅ Use placeholder values in examples: `YOUR_API_KEY_HERE` | ||||||
|
|
||||||
| ### DON'T: | ||||||
| - ❌ Commit real credentials, even temporarily | ||||||
| - ❌ Use `--no-verify` to bypass the check | ||||||
| - ❌ Add broad exclusions to `.gitleaks.toml` without review | ||||||
| - ❌ Assume deleted secrets are safe (git history remembers) | ||||||
|
|
||||||
| ## Troubleshooting | ||||||
|
|
||||||
| ### CI fails but local scan passes | ||||||
| ```bash | ||||||
| # Ensure you're using the config file | ||||||
| gitleaks detect --source . --config .gitleaks.toml --no-git | ||||||
|
|
||||||
| # Check which gitleaks version CI uses | ||||||
| grep 'gitleaks-action@' .github/workflows/secret-scan.yml | ||||||
| ``` | ||||||
|
|
||||||
| ### Too many false positives | ||||||
| 1. Review the findings carefully | ||||||
| 2. Update `.gitleaks.toml` with specific exclusions | ||||||
| 3. Test the config change locally | ||||||
| 4. Submit the config update in your PR | ||||||
|
|
||||||
| ### Need to scan git history | ||||||
| ```bash | ||||||
| # Scan all commits (WARNING: can be slow on large repos) | ||||||
| gitleaks detect --source . --verbose | ||||||
|
|
||||||
| # Scan specific commit range | ||||||
| gitleaks detect --log-opts="main..HEAD" | ||||||
| ``` | ||||||
|
|
||||||
| ## Additional Resources | ||||||
|
|
||||||
| - [Gitleaks Documentation](https://github.com/gitleaks/gitleaks) | ||||||
| - [Gitleaks Configuration Reference](https://github.com/gitleaks/gitleaks#configuration) | ||||||
| - [GitHub Secret Scanning](https://docs.github.com/en/code-security/secret-scanning) | ||||||
|
|
||||||
| ## Questions? | ||||||
|
|
||||||
| For issues with secret scanning: | ||||||
| 1. Check this guide first | ||||||
| 2. Review `.gitleaks.toml` configuration | ||||||
| 3. Ask in your PR or open an issue | ||||||
|
|
||||||
| --- | ||||||
|
|
||||||
| **Remember:** It's easier to prevent secrets from being committed than to clean them up from git history! | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| name: Secret Scan | ||
|
|
||
| # Prevents secrets (API keys, passwords, tokens) from being committed. | ||
| # For setup and troubleshooting, see: .github/SECRET_SCANNING.md | ||
| # To run locally: gitleaks protect --staged --verbose | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| - 'release-*' | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| gitleaks: | ||
| name: Scan for secrets | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Full history for comprehensive scanning | ||
|
|
||
| - name: Run Gitleaks | ||
| uses: gitleaks/gitleaks-action@v2 | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} # Optional: for Gitleaks Pro features | ||
| GITLEAKS_ENABLE_COMMENTS: true | ||
| GITLEAKS_ARGS: --log-opts="main..HEAD" # Scan only PR commits, not full history | ||
|
|
||
| - name: Upload SARIF report | ||
| if: failure() | ||
| uses: github/codeql-action/upload-sarif@v3 | ||
| with: | ||
| sarif_file: results.sarif | ||
| category: gitleaks |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| # Gitleaks configuration for OpenShift Origin | ||
| # This config excludes common false positives while catching real secrets | ||
| # | ||
| # To test this config locally: | ||
| # gitleaks detect --source . --config .gitleaks.toml --verbose | ||
| # | ||
| # For full documentation, see: .github/SECRET_SCANNING.md | ||
|
|
||
| title = "gitleaks config for openshift/origin" | ||
|
|
||
| # Extend the default gitleaks config | ||
| [extend] | ||
| useDefault = true | ||
|
|
||
| [allowlist] | ||
| description = "Allowlist for test fixtures, examples, and vendor code" | ||
|
|
||
| # Paths to exclude from scanning | ||
| paths = [ | ||
| # Test directories and files | ||
| '''test/''', | ||
| '''.*_test\.go$''', | ||
| '''testdata/''', | ||
|
|
||
| # Vendor dependencies | ||
| '''vendor/''', | ||
|
|
||
| # Examples and demo files | ||
| '''examples/''', | ||
|
|
||
| # Generated binary data files | ||
| '''bindata\.go$''', | ||
|
|
||
| # Lock files and checksums | ||
| '''go\.sum$''', | ||
| '''package-lock\.json$''', | ||
| '''yarn\.lock$''', | ||
|
|
||
| # Documentation | ||
| '''\.md$''', | ||
| ] | ||
|
Comment on lines
+39
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider narrowing the markdown exclusion. Excluding all
🤖 Prompt for AI Agents |
||
|
|
||
| # Specific regexes to exclude (for base64 encoded test values, etc.) | ||
| regexes = [ | ||
| # Base64 encoded placeholder values commonly used in tests | ||
| '''c2VjcmV0dmFsdWU=''', # "secretvalue" in base64 | ||
| '''bXktc2VjcmV0LXZhbHVl''', # "my-secret-value" in base64 | ||
| '''cGFzc3dvcmQ=''', # "password" in base64 | ||
|
|
||
| # Common test/example credentials | ||
| '''admin:admin''', | ||
| '''system:admin''', | ||
| '''secretvalue1''', | ||
|
|
||
| # Grafana default example secret | ||
| '''SW2YcwTIb9zpOOhoPsMm''', | ||
| ] | ||
|
|
||
| # Stopwords - tokens that if found in the match will cause it to be ignored | ||
| stopwords = [ | ||
| # Common variable names and placeholders | ||
| '''YOUR_API_KEY''', | ||
| '''REPLACE_ME''', | ||
| '''CHANGEME''', | ||
| '''example\.com''', | ||
| '''localhost''', | ||
| ] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix trigger scope statement to match workflow config.
Line 8 says pushes to
mainandrelease-*, but.github/workflows/secret-scan.ymlcurrently triggerspushonly onmain. Please align the doc (or workflow) to avoid misleading contributors.Proposed doc fix
📝 Committable suggestion
🤖 Prompt for AI Agents