feat: add secret and exposure scanning for PRs#418
Conversation
Signed-off-by: Rayhan Hossain <hossain.rayhan@outlook.com>
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
|
|
||
| # ---- Fixtures that MUST be flagged (fake but pattern-valid) ----------------- | ||
| cat > "${WORK}/leaks.txt" <<'EOF' | ||
| password = "sup3rSecretValue" |
| # ---- Fixtures that MUST be flagged (fake but pattern-valid) ----------------- | ||
| cat > "${WORK}/leaks.txt" <<'EOF' | ||
| password = "sup3rSecretValue" | ||
| mongodb://admin:hunter2@db.internal:27017/app |
| -----BEGIN RSA PRIVATE KEY----- | ||
| MIIEvfakekeymaterialdoesnotmatterforregexmatching | ||
| -----END RSA PRIVATE KEY----- |
| cat > "${WORK}/leaks.txt" <<'EOF' | ||
| password = "sup3rSecretValue" | ||
| mongodb://admin:hunter2@db.internal:27017/app | ||
| -----BEGIN RSA PRIVATE KEY----- |
| -----BEGIN RSA PRIVATE KEY----- | ||
| MIIEvfakekeymaterialdoesnotmatterforregexmatching | ||
| -----END RSA PRIVATE KEY----- | ||
| InstrumentationKey=11111111-2222-3333-4444-555555555555 |
| -----END RSA PRIVATE KEY----- | ||
| InstrumentationKey=11111111-2222-3333-4444-555555555555 | ||
| APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=https://eastus.in.applicationinsights.azure.com/ | ||
| subscriptionId: 99999999-8888-7777-6666-555555555555 |
| InstrumentationKey=11111111-2222-3333-4444-555555555555 | ||
| APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=https://eastus.in.applicationinsights.azure.com/ | ||
| subscriptionId: 99999999-8888-7777-6666-555555555555 | ||
| /subscriptions/12345678-90ab-cdef-1234-567890abcdef/resourceGroups/rg |
| APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=https://eastus.in.applicationinsights.azure.com/ | ||
| subscriptionId: 99999999-8888-7777-6666-555555555555 | ||
| /subscriptions/12345678-90ab-cdef-1234-567890abcdef/resourceGroups/rg | ||
| mongodb://docdbadmin:R3alSecret!@10.0.0.5:10260/?tls=true |
| APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=https://eastus.in.applicationinsights.azure.com/ | ||
| subscriptionId: 99999999-8888-7777-6666-555555555555 | ||
| /subscriptions/12345678-90ab-cdef-1234-567890abcdef/resourceGroups/rg | ||
| mongodb://docdbadmin:R3alSecret!@10.0.0.5:10260/?tls=true |
| subscriptionId: 99999999-8888-7777-6666-555555555555 | ||
| /subscriptions/12345678-90ab-cdef-1234-567890abcdef/resourceGroups/rg | ||
| mongodb://docdbadmin:R3alSecret!@10.0.0.5:10260/?tls=true | ||
| mongodb+srv://docdbadmin:R3alSecret!@my-cluster.mongocluster.cosmos.azure.com/ |
There was a problem hiding this comment.
Pull request overview
Adds a defense-in-depth secret and exposure scanning setup for this repository, combining a required CI workflow (gitleaks + SARIF + LoadBalancer exposure check), a local pre-commit hook, and updated Copilot review guidance to reduce the chance of secret leaks or unintended public exposure reaching main.
Changes:
- Adds a
secret-scanGitHub Actions workflow to run gitleaks diff-scoped scanning (with SARIF upload) and detect potentially-publicService type: LoadBalancermanifests. - Introduces a custom
.gitleaks.tomlruleset plus a bash self-test script to validate the rules fire and placeholders are ignored. - Adds an opt-in
.pre-commit-config.yamland extends Copilot review instructions with secret/exposure review criteria.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/secret-scan.yml |
Adds CI jobs for gitleaks scanning + SARIF upload and a YAML-based LoadBalancer exposure check. |
.gitleaks.toml |
Defines custom gitleaks rules and allowlisting for placeholders and selected paths. |
.pre-commit-config.yaml |
Adds local pre-commit hooks for gitleaks and credential/key detectors. |
scripts/security/test-secret-scan.sh |
Implements a config self-test harness that generates fixtures and asserts expected gitleaks RuleIDs. |
.github/copilot-review-instructions.md |
Adds Copilot review guidance for secret-leak and exposure findings. |
| assert_no_finding_in() { | ||
| # Assert no finding references the placeholder file. | ||
| local file="$1" | ||
| if grep -q "placeholders.txt" "${REPORT}"; then |
| InstrumentationKey=11111111-2222-3333-4444-555555555555 | ||
| APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=https://eastus.in.applicationinsights.azure.com/ | ||
| subscriptionId: 99999999-8888-7777-6666-555555555555 |
| assert_rule_present "azure-appinsights-instrumentation-key" | ||
| assert_rule_present "azure-appinsights-connection-string" | ||
| assert_rule_present "azure-subscription-id" |
| set +e | ||
| LOGOPTS="" | ||
| if [ "${{ github.event_name }}" = "pull_request" ]; then | ||
| git fetch --no-tags --depth=1 origin "${{ github.base_ref }}" || git fetch --no-tags origin "${{ github.base_ref }}" | ||
| LOGOPTS="--log-opts=origin/${{ github.base_ref }}..HEAD" | ||
| elif [ -n "${{ github.event.before }}" ] && [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]; then | ||
| LOGOPTS="--log-opts=${{ github.event.before }}..${{ github.sha }}" | ||
| fi | ||
| echo "Scanning range: ${LOGOPTS:-<full history>}" | ||
| gitleaks detect \ | ||
| --source . \ | ||
| --config .gitleaks.toml \ | ||
| --redact \ | ||
| --report-format sarif \ | ||
| --report-path gitleaks.sarif \ | ||
| --exit-code 1 \ | ||
| --verbose \ | ||
| $LOGOPTS | ||
| echo "exit_code=$?" >> "$GITHUB_OUTPUT" |
| echo "exit_code=$?" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Upload SARIF to code scanning | ||
| if: always() && hashFiles('gitleaks.sarif') != '' |
| GL_VER=8.21.2 | ||
| curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GL_VER}/gitleaks_${GL_VER}_linux_x64.tar.gz" \ | ||
| | tar xz gitleaks | ||
| sudo mv gitleaks /usr/local/bin/gitleaks |
| GL_VER=8.21.2 | ||
| curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GL_VER}/gitleaks_${GL_VER}_linux_x64.tar.gz" \ | ||
| | tar xz gitleaks | ||
| sudo mv gitleaks /usr/local/bin/gitleaks |
| '''(^|/)documentdb-playground/''', | ||
| '''\.md$''', | ||
| ] |
|
🤖 Auto-triaged by documentdb-triage-tool. Applied: Reasoningcomponent from path globs (docs, ci); P0 keyword "security" in body; effort from diff stats (364+0 LOC, 5 files) If a label is wrong, remove it manually and ping |
Add secret & exposure scanning for PRs
What & why
This PR adds a defense-in-depth secret-scanning setup so accidental leaks (passwords, private keys/certs, cloud keys, DocumentDB connection strings) and accidental public exposure never make it into
main. There was previously no secret scanning in the repo — onlygovulncheck(Go CVEs).Coverage spans three layers:
Changes
.github/workflows/secret-scan.yml.gitleaks.toml.pre-commit-config.yamldetect-private-key+detect-aws-credentials)scripts/security/test-secret-scan.sh.github/copilot-review-instructions.mdDetection coverage
-----BEGIN … PRIVATE KEY-----,.pem/.key/.pfx/.p12)mongodb://,postgres://,redis://, …):10260,mongodb+srv://,*.mongocluster.cosmos.azure.com(the+srvform is missed by the generic rule)subscriptionId,AZURE_/ARM_SUBSCRIPTION_ID,/subscriptions/<guid>/…)Service type: LoadBalancerwithout an internal-LB annotationDesign notes
gitleaks/gitleaks-action, which requires a paidGITLEAKS_LICENSEsecret for GitHub organizations (this repo is under thedocumentdborg).changeme,${VAR},user:pass, all-zeros GUID) from false-flagging. The self-test asserts this.How to test locally
Enable the local pre-commit hook (optional, per clone)
The hook is opt-in and local (
.git/hooks/isn't committed), so it's a convenience — the CI gate is the real enforcement.How it blocks a PR
The
secret-scanworkflow runs on everypull_request. If gitleaks finds a new secret, or a public LoadBalancer without an internal annotation, the job fails. Findings also appear in Security → Code scanning via SARIF upload. Once the checks are marked required (see next steps), a failing scan blocks merge.AI reviewer
Copilot code review reads the new Security & secret-leak review section in
.github/copilot-review-instructions.mdand leaves 🔴 Critical comments / requests changes for the same categories. This is advisory (its comments aren't a required status check) — it complements, but does not replace, the deterministic gitleaks gate.Next steps / repo settings required after merge
These are repo-admin actions, not code:
Make the checks required — Settings → Branches → branch protection for
main→ add as required status checks:secret-scan / gitleaks config self-testsecret-scan / gitleaks (secrets, keys, certs)secret-scan / public LoadBalancer / external exposure checkThis is what actually blocks merges.
(Optional) Enable GitHub Secret Scanning + Push Protection (Settings → Code security) as a native complement for known provider token formats.
Known follow-ups (not blockers)
internal/utils/constants.go, sidecar-injectorconfig.go). These need separate triage — the diff-scoped gate means they won't block new PRs in the meantime. A gitleaks baseline can grandfather them if a scheduled full scan is added later.make secret-scanconvenience target.Testing done
scripts/security/test-secret-scan.sh— 8/8 pass (7 rules fire, placeholders ignored)