Skip to content

ci(security): enforce — block on new secrets, CRITICAL, and new SAST findings - #2022

Merged
Gregory91G merged 2 commits into
mainfrom
ci/security-enable-enforcement
Aug 4, 2026
Merged

ci(security): enforce — block on new secrets, CRITICAL, and new SAST findings#2022
Gregory91G merged 2 commits into
mainfrom
ci/security-enable-enforcement

Conversation

@Gregory91G

@Gregory91G Gregory91G commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Turns the security scans from report-only into gates. Counterpart:
constructorfabric/insight-front#232.

What starts blocking

Check Mechanism Scope of failure
critical (Trivy) --exit-code 1 a CRITICAL vulnerability, an embedded secret, or a CRITICAL misconfiguration anywhere in the tree
secrets (diff) (TruffleHog) the summary step exits non-zero only the commits the pull request adds
sast (Semgrep) a second pass with --error --baseline-commit only findings the pull request introduces

It starts green

The whole point of gating now rather than earlier: the backlog it would have blocked on is gone.

before the hardening branch on main today
CRITICAL, repository scan 9 0
CRITICAL, image scans 73 0
HIGH, repository scan 131 25

Verified by running the blocking command itself against main, same pinned image and flags as
the workflow:

trivy fs --ignorefile /src/.trivyignore.yaml --scanners vuln,secret,misconfig \
         --severity CRITICAL --ignore-unfixed --exit-code 1 --no-progress /src
-> exit 0

Why Semgrep needs --baseline-commit rather than plain --error

Measured, not assumed. Plain --error exits 1 against the existing baseline, so every pull
request would be red until the whole backlog is triaged. With --baseline-commit pointed at the
base commit, the same run exits 0 and reports Findings: 0 (0 blocking).

The blocking pass uploads no SARIF: with --baseline-commit the 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: 0 is required because Semgrep builds a
worktree at the base commit.

What deliberately stays report-only

  • HIGH. 25 remain: 22 inside the built insight-toolbox image (npm's bundled tar,
    minimatch, glob, cross-spawn, sigstore, brace-expansion, plus Go CVEs in the kubectl
    and yq binaries) and 3 KSV-0014 recorded as accepted risk — keycloak's start-dev rewrites
    its own installation directory, and the frontend chart the same way. Gating HIGH today would
    fail every build.
  • Image CVEs. Now at 0 CRITICAL across all 13 scanned images, but they are built from
    upstream bases we do not control on the same cadence, so a new upstream CRITICAL would block
    unrelated work.

Test plan

  • The blocking Trivy command run against main exits 0
  • Code Scanning on main: 0 CRITICAL from every tool and every category
  • After merge: the first pull request into main shows critical (blocking) green
  • After merge: a pull request that adds a CRITICAL is refused

Summary by CodeRabbit

  • Bug Fixes
    • Security checks now reliably block pull requests when new code introduces critical vulnerabilities, suspicious secrets, or policy violations.
    • Scan results now distinguish between report-only checks and blocking checks for clearer review outcomes.
    • Baseline comparisons identify only newly introduced findings, reducing noise from previously known issues.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The 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.

Changes

Security workflow enforcement

Layer / File(s) Summary
Semgrep baseline gate
.github/workflows/semgrep.yml
The workflow performs a full-history SARIF scan and adds a pull-request scan that fails on findings introduced since the base commit.
Trivy critical gate
.github/workflows/trivy.yml
The critical Trivy job now blocks when configured findings are detected.
TruffleHog secrets gate
.github/workflows/trufflehog.yml
The secrets-diff scan now fails after reporting pull-request findings, while the no-findings path remains successful.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: ktursunov

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: security CI now blocks new secrets, CRITICAL findings, and new SAST findings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/security-enable-enforcement

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…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>
@Gregory91G
Gregory91G force-pushed the ci/security-enable-enforcement branch from d6da4da to 7bcafbf Compare July 29, 2026 15:31
…forcement

Signed-off-by: Gregory Gogin <grigoriy.gogin@constructor.tech>
@Gregory91G
Gregory91G marked this pull request as ready for review August 4, 2026 00:27
@Gregory91G
Gregory91G requested a review from a team as a code owner August 4, 2026 00:27

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 win

Use the same dependency inputs in the blocking job and report job.

The report job generates uv.lock files, but the blocking gate job 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 gate or upload the generated lock files as an artifact. Add --include-dev-deps to 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 win

Do not combine secret scanning with --severity CRITICAL.

--severity filters 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 CRITICAL for 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 win

Do not suppress unfixed CRITICAL vulnerabilities in the blocking pass.

--ignore-unfixed filters vulnerabilities with no available fix before --exit-code 1 evaluates 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

📥 Commits

Reviewing files that changed from the base of the PR and between 75c0da1 and 8bb9ad1.

📒 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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 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' || true

Repository: 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' || true

Repository: 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:


🌐 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:


🌐 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:


🌐 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:


🌐 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:


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.

@Gregory91G
Gregory91G requested a review from cyberantonz August 4, 2026 08:00
@Gregory91G
Gregory91G added this pull request to the merge queue Aug 4, 2026
Merged via the queue into main with commit 59f0634 Aug 4, 2026
24 of 25 checks passed
@Gregory91G
Gregory91G deleted the ci/security-enable-enforcement branch August 4, 2026 09:26
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.

2 participants