Skip to content

feat(CI Pipeline secrets): Secret Scanning CI for PRs#31

Closed
ebichman-1 wants to merge 1 commit into
dcm-project:mainfrom
ebichman-1:FLPATH-3360-add-sensitive-info-check-to-ci
Closed

feat(CI Pipeline secrets): Secret Scanning CI for PRs#31
ebichman-1 wants to merge 1 commit into
dcm-project:mainfrom
ebichman-1:FLPATH-3360-add-sensitive-info-check-to-ci

Conversation

@ebichman-1
Copy link
Copy Markdown

@ebichman-1 ebichman-1 commented May 4, 2026

Secret Scanning CI for PRs

FLPATH-3360

Context

The project currently has no security scanning in CI. The existing .github/workflows/ci.yaml only validates Traefik config and
runs a smoke test. The goal is to add automated secret/credential detection so that PRs introducing sensitive data (passwords,
API keys, tokens) are blocked before merge, and historical secrets in the git history are periodically audited.


Tool: gitleaks

Recommended over truffleHog (overkill — its verified-secret detection contacts external APIs, which adds no value here since the
repo has only placeholder credentials) and detect-secrets (Python-based, heavier operational overhead with its baseline file
approach).

Why gitleaks: Fast Go binary, 150+ built-in rules, excellent .gitleaks.toml config for allowlisting false positives, works
natively with git commit ranges for PR-scoped scanning. MIT-licensed CLI (no license key needed — we install the binary directly
instead of using the official GitHub Action wrapper which requires a license for org repos).


Plan

  1. Create .gitleaks.toml (repo root)

Gitleaks configuration that extends default rules and allowlists known false positives:

  • Path allowlist: .env.example, *.md docs — these contain placeholder credentials like adminpass that are not real secrets
  • Regex allowlist: adminpass literal and ${POSTGRES_PASSWORD:-adminpass} substitution patterns in compose.yaml
  1. Create .github/workflows/secret-scan.yaml

A separate workflow (not added to ci.yaml) with three jobs:

 ┌───────────────────────┬────────────────────────────────────────────┬──────────────────────────────────────────────────┐
 │          Job          │                  Trigger                   │                  What it scans                   │
 ├───────────────────────┼────────────────────────────────────────────┼──────────────────────────────────────────────────┤
 │ gitleaks-diff         │ pull_request                               │ Only the PR's new commits (base..head SHA range) │
 ├───────────────────────┼────────────────────────────────────────────┼──────────────────────────────────────────────────┤
 │ gitleaks-push         │ push to main                               │ Only the newly pushed commits                    │
 ├───────────────────────┼────────────────────────────────────────────┼──────────────────────────────────────────────────┤
 │ gitleaks-full-history │ Weekly schedule + manual workflow_dispatch │ Entire git history from first commit             │
 └───────────────────────┴────────────────────────────────────────────┴──────────────────────────────────────────────────┘

Key details:

  • Uses actions/checkout@v6 with fetch-depth: 0 (full clone needed for commit range scanning)
  • Installs gitleaks CLI directly (version pinned via GITLEAKS_VERSION env var) — avoids the official Action wrapper's license
    requirement
  • --redact flag masks actual secret values in logs
  • PR/push jobs upload SARIF to GitHub Code Scanning (with continue-on-error: true in case GHAS isn't enabled)
  • Full-history job uploads report as a build artifact instead
  1. (Optional) Create .pre-commit-config.yaml

Local pre-commit hook using the same gitleaks engine and .gitleaks.toml config, so developers catch secrets before pushing. This
is a convenience — the CI workflow is the mandatory gate.

  1. Update CONTRIBUTING.md

Add a section on pre-commit hook setup (pip install pre-commit && pre-commit install).

  1. Configure branch protection

After merging, add Scan PR for secrets as a required status check on the main branch protection rule.


Files to create/modify

 ┌────────────────────────────────────┬────────────────────────────────────────────┐
 │                File                │                   Action                   │
 ├────────────────────────────────────┼────────────────────────────────────────────┤
 │ .gitleaks.toml                     │ Create — gitleaks config with allowlists   │
 ├────────────────────────────────────┼────────────────────────────────────────────┤
 │ .github/workflows/secret-scan.yaml │ Create — the scanning workflow             │
 ├────────────────────────────────────┼────────────────────────────────────────────┤
 │ .pre-commit-config.yaml            │ Create (optional) — local pre-commit hook  │
 ├────────────────────────────────────┼────────────────────────────────────────────┤
 │ CONTRIBUTING.md                    │ Modify — add pre-commit setup instructions │
 └────────────────────────────────────┴────────────────────────────────────────────┘

Known false positives to allowlist

 ┌───────────────────────┬───────────────────────────────────────────────┬────────────────────────────────────────────┐
 │        Source         │                    Pattern                    │                  Why safe                  │
 ├───────────────────────┼───────────────────────────────────────────────┼────────────────────────────────────────────┤
 │ compose.yaml:15-16,39 │ ${POSTGRES_PASSWORD:-adminpass}               │ Local-dev default; real .env is gitignored │
 ├───────────────────────┼───────────────────────────────────────────────┼────────────────────────────────────────────┤
 │ .env.example:4        │ # POSTGRES_PASSWORD=adminpass                 │ Commented placeholder                      │
 ├───────────────────────┼───────────────────────────────────────────────┼────────────────────────────────────────────┤
 │ README.md, RUN.md     │ adminpass in docs                             │ Documentation only                         │
 ├───────────────────────┼───────────────────────────────────────────────┼────────────────────────────────────────────┤
 │ .env.example:21       │ <base64-encoded-dockerconfigjson> placeholder │ Literal placeholder text                   │
 └───────────────────────┴───────────────────────────────────────────────┴────────────────────────────────────────────┘

Verification

  1. After creating the files, open a test PR that includes a dummy secret (e.g., DB_HOST, DB_PASSWORD, POSTGRES_PASSWORD) and confirm the gitleaks-diff job fails
  2. Confirm a clean PR (no secrets) passes the check
  3. Run the full-history scan via workflow_dispatch and review the artifact for any unexpected findings — add fingerprints to .gitleaksignore if needed
  4. Test the pre-commit hook locally: stage a file with a fake secret, run git commit, confirm it's blocked

Summary by Sourcery

Add automated secret scanning to the repository using gitleaks in CI and developer workflows.

New Features:

  • Introduce a GitHub Actions workflow that runs gitleaks-based secret scanning on PRs, pushes to main, and on a scheduled full-history scan.
  • Add a shared gitleaks configuration file with allowlists for known placeholder credentials.
  • Provide an optional pre-commit hook configuration so contributors can run gitleaks locally before committing.
  • Document contributor workflow requirements and guidance for tests, code generation, and secret scanning in CONTRIBUTING.md.

The project currently has no security scanning in CI. The existing .github/workflows/ci.yaml only validates Traefik config and runs a smoke test. The goal is to add automated secret/credential detection so that PRs introducing sensitive data (passwords, API keys, tokens) are blocked before merge, and historical secrets in the git history are periodically audited.

Assisted-by: Claude Opus 4.6 (Anthropic)
Signed-off-by: ebichman-1 <ebichman@redhat.com>
@github-advanced-security
Copy link
Copy Markdown

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:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The gitleaks install logic is duplicated across all three jobs; consider extracting this into a reusable workflow or composite action (or at least a YAML anchor) so future version bumps or installation changes only need to be updated in one place.
  • To harden the gitleaks installation step, consider verifying the downloaded tarball with a published checksum or signature rather than piping curl directly into tar.
  • In the push job, --log-opts="${{ github.event.before }}..${{ github.event.after }}" can be problematic when before is all zeros (e.g., first push or force push); you may want to guard against this and fall back to a sensible default range (like HEAD~1..HEAD).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The gitleaks install logic is duplicated across all three jobs; consider extracting this into a reusable workflow or composite action (or at least a YAML anchor) so future version bumps or installation changes only need to be updated in one place.
- To harden the gitleaks installation step, consider verifying the downloaded tarball with a published checksum or signature rather than piping curl directly into tar.
- In the push job, `--log-opts="${{ github.event.before }}..${{ github.event.after }}"` can be problematic when `before` is all zeros (e.g., first push or force push); you may want to guard against this and fall back to a sensible default range (like `HEAD~1..HEAD`).

## Individual Comments

### Comment 1
<location path=".github/workflows/secret-scan.yaml" line_range="26-30" />
<code_context>
+        with:
+          fetch-depth: 0
+
+      - name: Install gitleaks
+        run: |
+          curl -sSfL \
+            "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
+            | tar -xz -C /usr/local/bin gitleaks
</code_context>
<issue_to_address>
**🚨 suggestion (security):** Consider adding checksum verification for the downloaded gitleaks binary

The tarball is downloaded and extracted without any integrity check. Please verify it (e.g., via the official checksum or signature) before extraction to reduce supply-chain or MITM risk when installing gitleaks on the runner.

```suggestion
      - name: Install gitleaks
        run: |
          set -euo pipefail

          GITLEAKS_BASE_URL="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}"
          TARBALL="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
          CHECKSUMS_FILE="gitleaks_${GITLEAKS_VERSION}_checksums.txt"

          # Download tarball and checksums
          curl -sSfL "${GITLEAKS_BASE_URL}/${TARBALL}" -o "${TARBALL}"
          curl -sSfL "${GITLEAKS_BASE_URL}/${CHECKSUMS_FILE}" -o "${CHECKSUMS_FILE}"

          # Verify checksum for the linux_x64 tarball
          grep "linux_x64.tar.gz" "${CHECKSUMS_FILE}" > "${CHECKSUMS_FILE}.linux_x64"
          sha256sum -c "${CHECKSUMS_FILE}.linux_x64"

          # Extract gitleaks only after successful verification
          tar -xz -C /usr/local/bin -f "${TARBALL}" gitleaks
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +26 to +30
- name: Install gitleaks
run: |
curl -sSfL \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz -C /usr/local/bin gitleaks
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 suggestion (security): Consider adding checksum verification for the downloaded gitleaks binary

The tarball is downloaded and extracted without any integrity check. Please verify it (e.g., via the official checksum or signature) before extraction to reduce supply-chain or MITM risk when installing gitleaks on the runner.

Suggested change
- name: Install gitleaks
run: |
curl -sSfL \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz -C /usr/local/bin gitleaks
- name: Install gitleaks
run: |
set -euo pipefail
GITLEAKS_BASE_URL="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}"
TARBALL="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
CHECKSUMS_FILE="gitleaks_${GITLEAKS_VERSION}_checksums.txt"
# Download tarball and checksums
curl -sSfL "${GITLEAKS_BASE_URL}/${TARBALL}" -o "${TARBALL}"
curl -sSfL "${GITLEAKS_BASE_URL}/${CHECKSUMS_FILE}" -o "${CHECKSUMS_FILE}"
# Verify checksum for the linux_x64 tarball
grep "linux_x64.tar.gz" "${CHECKSUMS_FILE}" > "${CHECKSUMS_FILE}.linux_x64"
sha256sum -c "${CHECKSUMS_FILE}.linux_x64"
# Extract gitleaks only after successful verification
tar -xz -C /usr/local/bin -f "${TARBALL}" gitleaks

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the goal is correct, implementing this locally in the placement-manager creates a maintenance silo.

Since we have the dcm-project/shared-workflows repository, the standard approach for our organization should be to centralize this as a Reusable Workflow. This ensures a homogeneous security posture across all DCM repos and eliminates the need to maintain manual installation scripts in individual repositories.

IMO, you should move the gitleaks logic to a reusable workflow in the shared-workflows repo and simply call the check in the dcm repos, keeping this repo's CI clean and aligned.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll look into a solution for implementing the Gitleaks workflow globally across the dcm-project/shared-workflows repository.


- name: Install gitleaks
run: |
curl -sSfL \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use go install instead

GITLEAKS_VERSION: "8.22.1"

jobs:
gitleaks-diff:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the advantage of running all of this manually over using the gitleaks action: https://github.com/marketplace/actions/gitleaks?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. Following @gciavarrini comment, I've moved this logic to the gitleaks.yaml file, like in the PR #19 so we can utilize the gitleaks.yaml file located in /shared-workflows/.github/workflows/

@ygalblum
Copy link
Copy Markdown
Contributor

ygalblum commented May 4, 2026

Closing this PR as the workflow will be added in the shared repo

@ygalblum ygalblum closed this May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants