ci(security): enforce — block on new secrets, CRITICAL, and new SAST findings - #2022
Conversation
📝 WalkthroughWalkthroughThe security workflows now enforce selected findings. Semgrep blocks newly introduced findings, Trivy blocks critical findings, and TruffleHog blocks pull-request secret findings. Existing report-only scans remain available. ChangesSecurity workflow enforcement
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…findings
NOT FOR MERGE YET. Rebuilt on current main so the diff is only the enforcement
change: 30 lines across three files.
- `critical` (Trivy) — `--exit-code 1`
- `secrets (diff)` (TruffleHog) — summary exits non-zero on a finding
- `sast` (Semgrep) — second pass, `--error --baseline-commit`, so only findings
the pull request introduces fail. Plain `--error` fails on the 173-finding
baseline instead.
Image CVEs, the repository report pass and the history sweep stay report-only —
their baselines are not empty.
Preconditions in #2020.
Refs #2020
Signed-off-by: Grigoriy Gogin <Grigoriy.Gogin@constructor.tech>
d6da4da to
7bcafbf
Compare
…forcement Signed-off-by: Gregory Gogin <grigoriy.gogin@constructor.tech>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
.github/workflows/trivy.yml (3)
46-58: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winUse the same dependency inputs in the blocking job and report job.
The report job generates
uv.lockfiles, but the blockinggatejob does not download that dependency state. GitHub-hosted jobs use fresh runner instances, so generated lock files from the report job are not seen by the blocking scan. The report scan also sets--include-dev-deps, while the blocking scan omits it, and Trivy excludes Poetry/uv development dependencies by default. A CRITICAL dependency finding can appear in the report while the blocking job passes.Move the dependency-resolution step into
gateor upload the generated lock files as an artifact. Add--include-dev-depsto the blocking scan as well.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/trivy.yml around lines 46 - 58, Update the blocking gate workflow to use the same dependency inputs as the report job: make the gate job generate or download the required uv.lock files before the Trivy fs scan, and add --include-dev-deps to that scan. Preserve the existing CRITICAL-only, ignore-unfixed, and failure behavior while ensuring both jobs inspect equivalent dependency state.Source: MCP tools
53-58: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDo not combine secret scanning with
--severity CRITICAL.
--severityfilters secret findings too, and Trivy 0.72.0 categorizes asymmetric private keys as HIGH. An embedded private key can be skipped by this command and the gate can exit successfully. Scan secrets in a separate invocation without the CRITICAL-only filter; keep--severity CRITICALfor vulnerability and misconfiguration scans.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/trivy.yml around lines 53 - 58, Update the Trivy workflow command so secret scanning runs in a separate invocation without the --severity CRITICAL filter, while retaining --severity CRITICAL for vulnerability and misconfiguration scanning. Ensure both scans preserve the existing ignorefile and failure behavior, and that secret findings are not excluded by severity filtering.Source: MCP tools
54-58: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDo not suppress unfixed CRITICAL vulnerabilities in the blocking pass.
--ignore-unfixedfilters vulnerabilities with no available fix before--exit-code 1evaluates the results, and the workflow should fail on CRITICAL findings. An unfixed new CRITICAL vulnerability can therefore pass this gate. Remove the flag, or change the blocking policy to only fail on CRITICAL findings that have an available fix.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/trivy.yml around lines 54 - 58, Update the Trivy blocking invocation in the workflow to remove --ignore-unfixed so --exit-code 1 evaluates all CRITICAL vulnerabilities, including those without available fixes; preserve the existing scanners, severity, and exit-code settings.Source: MCP tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/trufflehog.yml:
- Line 116: Update the TruffleHog invocation to include --fail-on-scan-errors,
and adjust the summary step around sys.exit(1) to fail whenever the command
exits non-zero or its JSON output cannot be parsed, including scan errors even
when no findings are returned.
---
Outside diff comments:
In @.github/workflows/trivy.yml:
- Around line 46-58: Update the blocking gate workflow to use the same
dependency inputs as the report job: make the gate job generate or download the
required uv.lock files before the Trivy fs scan, and add --include-dev-deps to
that scan. Preserve the existing CRITICAL-only, ignore-unfixed, and failure
behavior while ensuring both jobs inspect equivalent dependency state.
- Around line 53-58: Update the Trivy workflow command so secret scanning runs
in a separate invocation without the --severity CRITICAL filter, while retaining
--severity CRITICAL for vulnerability and misconfiguration scanning. Ensure both
scans preserve the existing ignorefile and failure behavior, and that secret
findings are not excluded by severity filtering.
- Around line 54-58: Update the Trivy blocking invocation in the workflow to
remove --ignore-unfixed so --exit-code 1 evaluates all CRITICAL vulnerabilities,
including those without available fixes; preserve the existing scanners,
severity, and exit-code settings.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: be84b7b7-ce1e-4790-818f-959b7fcd4740
📒 Files selected for processing (3)
.github/workflows/semgrep.yml.github/workflows/trivy.yml.github/workflows/trufflehog.yml
| "is a detector false positive on synthetic data, say so in the PR and add a narrow, " | ||
| "reviewed exclusion rather than widening the filter.\n") | ||
| out.close() | ||
| sys.exit(1) |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow relevant section =="
if [ -f .github/workflows/trufflehog.yml ]; then
nl -ba .github/workflows/trufflehog.yml | sed -n '1,180p'
else
echo "missing .github/workflows/trufflehog.yml"
fi
echo
echo "== search for fail-on-scan-errors and unparsable usage =="
rg -n "fail-on-scan-errors|unparsable|sys\.exit\(1\)|results=verified" .github/workflows/trufflehog.yml || true
echo
echo "== git diff stat/name-status =="
git diff --stat HEAD~1 HEAD 2>/dev/null || true
git diff -- .github/workflows/trufflehog.yml 2>/dev/null | sed -n '1,220p' || trueRepository: constructorfabric/insight
Length of output: 235
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== available files =="
find .github -maxdepth 2 -type f 2>/dev/null | sort || true
echo
echo "== workflow trufflehog section =="
if [ -f .github/workflows/trufflehog.yml ]; then
awk '{printf "%6d %s\n", NR, $0}' .github/workflows/trufflehog.yml | sed -n '1,180p'
else
echo "missing .github/workflows/trufflehog.yml"
fi
echo
echo "== search relevant patterns =="
grep -nE "fail-on-scan-errors|unparsable|sys\.exit|results=verified|docker run" .github/workflows/trufflehog.yml || true
echo
echo "== git diff stat/name-status =="
git diff --stat HEAD~1 HEAD 2>/dev/null || true
git diff -- .github/workflows/trufflehog.yml 2>/dev/null | sed -n '1,260p' || trueRepository: constructorfabric/insight
Length of output: 44866
🌐 Web query:
TruffleHog v3.96.0 git file --json --fail-on-scan-errors behavior scan errors no findings
💡 Result:
In TruffleHog v3.96.0, the --fail-on-scan-errors flag is designed to ensure that the tool exits with a non-zero error code if any errors are encountered during the scan [1][2]. Behavior details: 1. Scan Errors vs. Findings: The --fail-on-scan-errors flag specifically monitors for errors that occur during the scanning process itself (e.g., repository cloning issues, unreachable commits, or other non-fatal scan failures) [1][2]. It is distinct from the --fail flag, which causes the tool to exit with code 183 specifically when secrets (results) are discovered [3][4]. 2. Interaction with Findings: If a scan completes successfully without any scan errors but finds no secrets, the tool will exit with a zero (success) code, provided the --fail flag was not also used. The --fail-on-scan-errors flag does not trigger a failure based on the presence or absence of security findings; it only triggers based on the internal health and success of the scan execution [1][2]. 3. Reporting: When errors are encountered during a scan, TruffleHog will log these errors to the console [1][2]. If --fail-on-scan-errors is enabled, the program will additionally terminate with a non-zero exit status [1]. In summary, if your scan reports "no findings" but encounters "scan errors," enabling --fail-on-scan-errors will cause the process to exit with a non-zero code to alert you that the scan did not complete perfectly, even if no secrets were identified [1][2].
Citations:
- 1: Return non-zero exit code if an error occurs during a scan. trufflesecurity/trufflehog#4476
- 2: https://github.com/trufflesecurity/trufflehog/blob/main/main.go
- 3: https://github.com/trufflesecurity/trufflehog/blob/9f0b97f1/docs/man/trufflehog.1
- 4: https://github.com/trufflesecurity/trufflehog?tab=readme-ov-file
🌐 Web query:
TruffleHog v3.96.0 main.go --json exits non-zero scan errors no findings
💡 Result:
In TruffleHog v3.96.0, if you are experiencing non-zero exit codes during scans despite having no findings, it is likely due to the --fail-on-scan-errors flag being enabled [1][2]. By default, TruffleHog utilizes the following exit codes: - 0: Successful execution with no errors and no findings [3]. - 1: An error occurred during scanning (e.g., repository access issues, invalid configuration) [2][3]. - 183: Credentials were found and the --fail flag was explicitly provided [2][3]. If your command includes --fail-on-scan-errors, TruffleHog will exit with a non-zero status (typically 1) if any errors are encountered during the scan process [1][2], even if no secrets are identified. This is designed to ensure that CI/CD pipelines fail if the scan itself is incomplete or encounters issues, rather than silently succeeding [4]. To troubleshoot the non-zero exit code: 1. Check the logs for error messages: Even with --json output, TruffleHog often writes error logs to stderr [1][4]. These errors (such as "encountered errors during scan") will cause the non-zero exit if --fail-on-scan-errors is set [1]. 2. Verify the --fail-on-scan-errors flag: If you do not want the scan to fail on technical errors (like a single unreadable file or transient network issue), remove this flag from your command. 3. Inspect for "invalid" inputs: Common causes for scan errors include invalid commit hashes (e.g., when using --since-commit), unreachable git remotes, or permission issues in the target directory [4]. If you are seeing "encountered errors during scan" in your output and your exit code is 1, it confirms that a non-fatal error occurred, triggering the fail condition you have configured [1][4].
Citations:
- 1: https://github.com/trufflesecurity/trufflehog/blob/main/main.go
- 2: https://github.com/trufflesecurity/trufflehog/blob/9f0b97f1/docs/man/trufflehog.1
- 3: https://github.com/trufflesecurity/trufflehog/blob/75972a6f81f01d4c034b8a57c8ef4a426482b280/README.md
- 4: trufflehog exits with 0 in case
--since-commithas invalid commit id trufflesecurity/trufflehog#4218
🌐 Web query:
TruffleHog v3.96.0 json output scan errors stdout stderr logs
💡 Result:
In TruffleHog v3.96.0, scan errors are primarily handled through standard error (stderr) logging and exit status codes, rather than being encapsulated within the structured JSON output stream [1][2]. Key points regarding scan errors and output: 1. JSON Output: When using the --json flag, the standard output (stdout) produces structured JSON objects representing detected secrets [1][2]. This output is intended for findings (verified and unverified secrets) and does not typically contain scan-level diagnostic errors [1][2]. 2. Logging and Errors: Diagnostic logs, warnings, and scan errors are sent to stderr [1][2]. Recent versions, including v3.96.0, have explicitly improved logging for analyzer-specific errors (e.g., Anthropic, Postgres, and HuggingFace analyzers) [3][4]. These are printed as human-readable logs to stderr during the execution [3][4]. 3. Exit Codes: TruffleHog uses specific exit codes to signal scan health [5][2]: - 0: Successful scan, no errors, no results found. - 1: An error occurred during the scan (sources may not have completed) [5][2]. - 183: Credentials found (only when the --fail flag is used) [5][2]. 4. Fail on Error: If you need to stop execution when an error occurs, you can use the --fail-on-scan-errors flag, which ensures the process exits with a non-zero code if an error is encountered during the scan [1]. If you are piping stdout to other tools like jq (e.g., trufflehog git... --json | jq...), it is recommended to keep stderr redirected to the terminal or a separate log file to monitor for errors without corrupting the JSON stream [1][6].
Citations:
- 1: https://github.com/trufflesecurity/trufflehog/blob/9f0b97f1/docs/man/trufflehog.1
- 2: https://github.com/trufflesecurity/trufflehog/blob/f3c2d5e6c77ed19caac817fa8091a47fb2102039/README.md
- 3: https://github.com/trufflesecurity/trufflehog/releases/tag/v3.96.0
- 4: https://newreleases.io/project/github/trufflesecurity/trufflehog/release/v3.96.0
- 5: https://github.com/trufflesecurity/trufflehog/blob/c8ac7c392edcf3009bf6da98a8eb680935a18d64/README.md
- 6: https://github.com/trufflesecurity/trufflehog/blob/main/manpage.go
🌐 Web query:
github.com/trufflesecurity/trufflehog main.go v3.96.0 PrintFindings scan errors stderr json
💡 Result:
In TruffleHog v3.96.0, the behavior regarding scan errors and JSON output is handled as follows: Scan errors are logged to stderr [1][2], while results are output to stdout [3][4]. When using the --json flag, TruffleHog outputs results as a stream of individual JSON objects (JSON Lines format), rather than a single encapsulated JSON array [4]. Regarding scan errors specifically: 1. Non-fatal errors encountered during a scan (such as those occurring within specific git refs or sources) are logged using the structured logger to stderr [1]. 2. The codebase specifically directs logging to os.Stderr when the --json flag is enabled [2]. 3. If the --fail-on-scan-errors flag is used, TruffleHog will exit with a non-zero error code if scan errors are encountered [5][6]. Because TruffleHog uses a structured logger (logrus) configured to write to stderr [1][2], these error messages appear in the standard error stream separate from the JSON result objects printed to stdout [4]. If you need to process these errors programmatically alongside your JSON results, you must capture stdout and stderr separately [4].
Citations:
- 1: https://github.com/trufflesecurity/trufflehog/blob/main/main.go
- 2: https://github.com/trufflesecurity/trufflehog/blob/d1a2d9e83264da0a75410cd1736576c47a8f87a4/main.go
- 3: https://github.com/trufflesecurity/trufflehog/blob/96bbe6b90a331d002cbaedf5a78cd3be54c8a952/main.go
- 4: --json flag still does not output as JSON standard trufflesecurity/trufflehog#2164
- 5: https://pkg.go.dev/github.com/trufflesecurity/trufflehog/v3@v3.96.0
- 6: https://github.com/trufflesecurity/trufflehog
🌐 Web query:
site:github.com/trufflesecurity/trufflehog/tags trufflesecurity/trufflehog v3.96.0
💡 Result:
TruffleHog version v3.96.0 was released by the Truffle Security team on July 24, 2026 [1]. This release follows version v3.95.9 and includes various contributions, including a first-time contribution from @mattbrady-1 [1]. As with other releases in this repository, binary assets for multiple platforms—including Darwin (amd64, arm64), Linux (amd64, arm64), and Windows (amd64, arm64)—were provided alongside checksum files [1].
Citations:
🌐 Web query:
github.com/trufflesecurity/trufflehog main.go 9f0b97f1 PrintFindings fail-on-scan-errors
💡 Result:
In TruffleHog, the --fail-on-scan-errors flag determines the behavior of the program when non-fatal errors occur during a scan [1][2][3]. When this flag is used, TruffleHog will exit with a non-zero exit code if any errors are encountered during the scanning process [4][5]. This functionality was introduced to prevent TruffleHog from failing silently in scenarios such as failing to clone a git repository correctly or referencing an invalid commit ID via the --since-commit flag [5]. The PrintFindings function (and related logic in main.go) is responsible for handling the reporting of results and errors at the conclusion of a scan [1][2][6]. Specifically, the engine logs any non-fatal errors gathered during the scan; if the --fail-on-scan-errors flag is set, the program ensures that a non-zero exit code is returned even if the overall scan process is considered complete [2]. Summary of Key Flags: --fail: Causes TruffleHog to exit with code 183 if any credentials are found [1][7]. --fail-on-scan-errors: Causes TruffleHog to exit with a non-zero error code if any errors occur during the scan, ensuring that such issues are not ignored [2][5].
Citations:
- 1: https://github.com/trufflesecurity/trufflehog/blob/9f0b97f1/main.go
- 2: https://github.com/trufflesecurity/trufflehog/blob/main/main.go
- 3: https://github.com/trufflesecurity/trufflehog?tab=readme-ov-file
- 4: https://github.com/trufflesecurity/trufflehog/blob/9f0b97f1/docs/man/trufflehog.1
- 5: Return non-zero exit code if an error occurs during a scan. trufflesecurity/trufflehog#4476
- 6: https://github.com/trufflesecurity/trufflehog/blob/8505d24d7d9b18f5543cc17194a2fcb1f8cae828/main.go
- 7: https://github.com/trufflesecurity/trufflehog/blob/9f0b97f1/manpage.go
Fail closed when the TruffleHog scan is incomplete.
The scan uses --json, which outputs findings to stdout while scan errors are reported on stderr. With this setup, a scan with zero parsed findings can still pass unless --fail-on-scan-errors is enabled. Add --fail-on-scan-errors and fail the summary step when the TruffleHog command exits non-zero or reports unparsable output.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/trufflehog.yml at line 116, Update the TruffleHog
invocation to include --fail-on-scan-errors, and adjust the summary step around
sys.exit(1) to fail whenever the command exits non-zero or its JSON output
cannot be parsed, including scan errors even when no findings are returned.
Turns the security scans from report-only into gates. Counterpart:
constructorfabric/insight-front#232.
What starts blocking
critical(Trivy)--exit-code 1secrets (diff)(TruffleHog)sast(Semgrep)--error --baseline-commitIt starts green
The whole point of gating now rather than earlier: the backlog it would have blocked on is gone.
maintodayVerified by running the blocking command itself against
main, same pinned image and flags asthe workflow:
Why Semgrep needs
--baseline-commitrather than plain--errorMeasured, not assumed. Plain
--errorexits 1 against the existing baseline, so every pullrequest would be red until the whole backlog is triaged. With
--baseline-commitpointed at thebase commit, the same run exits 0 and reports
Findings: 0 (0 blocking).The blocking pass uploads no SARIF: with
--baseline-committhe report holds only new findings,and uploading it would mark the existing baseline as fixed on the pull request's ref. The
full-tree pass keeps owning Code Scanning.
fetch-depth: 0is required because Semgrep builds aworktree at the base commit.
What deliberately stays report-only
insight-toolboximage (npm's bundledtar,minimatch,glob,cross-spawn,sigstore,brace-expansion, plus Go CVEs in thekubectland
yqbinaries) and 3KSV-0014recorded as accepted risk — keycloak'sstart-devrewritesits own installation directory, and the frontend chart the same way. Gating HIGH today would
fail every build.
upstream bases we do not control on the same cadence, so a new upstream CRITICAL would block
unrelated work.
Test plan
mainexits 0main: 0 CRITICAL from every tool and every categorymainshowscritical (blocking)greenSummary by CodeRabbit