Update checkmarx-ast-cli binaries with 2.3.58 #3
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security | |
| on: | |
| pull_request: | |
| branches: [main, master] | |
| # One run per PR; a new push cancels the in-progress scan (no duplicate | |
| # comments, no wasted runner minutes). | |
| concurrency: | |
| group: secret-scan-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| permissions: {} # no broad grants at workflow level | |
| jobs: | |
| secret-scan: | |
| name: TruffleHog Secret Scan | |
| runs-on: cx-public-ubuntu-x64 | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: read # required to check out the PR head | |
| pull-requests: write # required to upsert the findings comment | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| persist-credentials: false | |
| - name: Run TruffleHog | |
| id: trufflehog | |
| shell: bash | |
| env: | |
| # Pinned by immutable digest (tag 3.96.0). Bump digest + comment on upgrade. | |
| TRUFFLEHOG_IMAGE: "ghcr.io/trufflesecurity/trufflehog@sha256:aa821cf4ace8861c7d096d83818cdf7bb9719028a52d37a52eaad44086a52577" # 3.96.0 | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| run: | | |
| set -euo pipefail | |
| # --no-fail: findings exit 0, so TruffleHog only exits nonzero on real | |
| # breakage (image pull, daemon, bad flags). With `set -e` and no `|| true`, | |
| # that breakage fails the step (and, with no continue-on-error, the job) — | |
| # instead of silently producing empty results. We block on VERIFIED secrets | |
| # ourselves in a later step. | |
| ARGS=(git "file:///repo" --json --no-update --no-fail) | |
| if [[ -n "${BASE_SHA}" && ! "${BASE_SHA}" =~ ^0+$ ]]; then | |
| ARGS+=(--since-commit "${BASE_SHA}") | |
| fi | |
| echo "Running: trufflehog ${ARGS[*]}" | |
| docker run --rm -v "${GITHUB_WORKSPACE}:/repo:ro" -w /repo \ | |
| "${TRUFFLEHOG_IMAGE}" "${ARGS[@]}" > trufflehog-results.json | |
| echo "--- raw results ---"; cat trufflehog-results.json | |
| - name: Parse results | |
| id: parse | |
| if: always() | |
| shell: bash | |
| run: | | |
| set -uo pipefail | |
| grep -E '"DetectorName"' trufflehog-results.json > findings.ndjson || true | |
| # Count non-empty lines. grep -c prints "0" AND exits 1 on no match, so | |
| # capture once and only reset on failure (avoids a duplicate "0"). | |
| COUNT=$(grep -c . findings.ndjson 2>/dev/null) || COUNT=0 | |
| # Verified = confirmed-live by the provider (compact JSON -> "Verified":true). | |
| # These are what we BLOCK on; everything else is a warning. | |
| VERIFIED=$(grep -c '"Verified":true' findings.ndjson 2>/dev/null) || VERIFIED=0 | |
| echo "count=${COUNT}" >> "$GITHUB_OUTPUT" | |
| echo "verified=${VERIFIED}" >> "$GITHUB_OUTPUT" | |
| echo "Total=${COUNT} verified(blocking)=${VERIFIED} unverified(warn)=$((COUNT - VERIFIED))" | |
| - name: Upsert single PR comment | |
| if: always() | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const MARKER = '<!-- trufflehog-secret-scan -->'; | |
| const server = process.env.GITHUB_SERVER_URL; | |
| const { owner, repo } = context.repo; | |
| const issue_number = context.payload.pull_request.number; | |
| const findings = fs.existsSync('findings.ndjson') | |
| ? fs.readFileSync('findings.ndjson', 'utf8').split('\n').filter(Boolean).map(l => JSON.parse(l)) | |
| : []; | |
| const n = findings.length; | |
| const verifiedCount = findings.filter(f => f.Verified === true).length; | |
| const unverifiedCount = n - verifiedCount; | |
| let body; | |
| if (n > 0) { | |
| const seen = new Set(); | |
| const rows = []; | |
| for (const f of findings) { | |
| const g = f.SourceMetadata?.Data?.Git || {}; | |
| const type = f.DetectorName || 'Unknown'; | |
| const status = f.Verified ? '✅ verified' : '⚠️ unverified'; | |
| const commit = g.commit || ''; | |
| const file = g.file || '(unknown)'; | |
| const line = g.line || 0; | |
| let view = '—'; | |
| if (commit && file !== '(unknown)') { | |
| const anchor = line > 0 ? `#L${line}` : ''; | |
| view = `[🔎 View secret](${server}/${owner}/${repo}/blob/${commit}/${file}${anchor})`; | |
| } | |
| const key = `${type}|${file}|${line}|${commit}`; | |
| if (seen.has(key)) continue; | |
| seen.add(key); | |
| rows.push(`| ${type} | ${status} | \`${commit.slice(0,10)}\` | \`${file}\` | ${view} |`); | |
| } | |
| const author = context.payload.pull_request.user.login; | |
| // Tiered: VERIFIED secrets block the merge; unverified are warnings. | |
| const header = verifiedCount > 0 | |
| ? '## 🚨 Verified secret(s) detected — merge blocked' | |
| : '## ⚠️ Potential secret(s) detected (unverified)'; | |
| const footer = verifiedCount > 0 | |
| ? '> ⛔ This PR is **blocked**: a verified, live secret was found. Remove it and re-scan to merge.' | |
| : '> ⚠️ These are **unverified** matches and do **not** block the merge — please review and confirm they are not real secrets.'; | |
| body = [ | |
| MARKER, | |
| header, | |
| '', | |
| `@${author} — TruffleHog found **${n}** potential secret(s) in this PR ` + | |
| `(**${verifiedCount} verified**, ${unverifiedCount} unverified).`, | |
| '', | |
| '| Secret Type | Status | Commit | File Path | View |', | |
| '| --- | --- | --- | --- | --- |', | |
| ...rows, | |
| '', | |
| '### 🛠 Guidelines to remediate hardcoded secrets', | |
| '- Understand the implications of revoking this secret by investigating where it is used in your code.', | |
| '- **Immediately rotate/revoke** the exposed secret. (https://howtorotate.com/docs/introduction/getting-started/)', | |
| '- Remove it from git history ( **a new "remove secret" commit is NOT enough** e.g. with [`git-filter-repo`](https://github.com/newren/git-filter-repo)).', | |
| '', | |
| 'To avoid such incidents in the future consider:', | |
| '- Following the best practices for managing and storing secrets, including API keys and other credentials.', | |
| '- Re-scan after cleanup before merging.', | |
| '', | |
| footer, | |
| ].join('\n'); | |
| } else { | |
| body = [ | |
| MARKER, | |
| '## ✅ No secrets detected', | |
| '', | |
| 'TruffleHog found no secrets in the current commits of this PR.', | |
| ].join('\n'); | |
| } | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| owner, repo, issue_number, per_page: 100, | |
| }); | |
| const existing = comments.find(c => c.body && c.body.includes(MARKER)); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body }); | |
| } else if (n > 0) { | |
| await github.rest.issues.createComment({ owner, repo, issue_number, body }); | |
| } | |
| # Block the merge ONLY on verified (confirmed-live) secrets. Unverified | |
| # findings are surfaced in the PR comment but do not fail the check. | |
| - name: Fail if verified secrets were found | |
| if: steps.parse.outputs.verified != '0' | |
| env: | |
| VERIFIED: ${{ steps.parse.outputs.verified }} # <-- add | |
| run: | | |
| echo "::error::TruffleHog found ${VERIFIED} VERIFIED secret(s). Merge is blocked." | |
| exit 1 |