ci(security): SAST, secret and SCA gates - #225
Conversation
📝 WalkthroughWalkthroughAdds CI security scanning for source code, dependencies, secrets, repository configuration, and published container images, with blocking critical checks, report-only scans, Code Scanning uploads, job summaries, and ignored generated report files. ChangesSecurity scanning automation
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 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 |
|
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. |
Three scanning domains, none of them covered before: Semgrep for static
analysis, TruffleHog for secrets, Trivy for dependencies and the built image.
semgrep.yml mirrors constructorfabric/insight's so findings stay comparable
across repos, minus the p/rust and p/csharp packs.
Rollout state differs per gate, driven by the measured baseline:
- Semgrep: report-only (17 findings, 0 error level). Ratchets to blocking
with --error once triaged.
- Trivy fs: gate blocks on CRITICAL (baseline 0), report pass covers
HIGH/MEDIUM/LOW (baseline 10/16/3) without blocking.
- Trivy image: report-only, in docker.yml where the pushed manifest tag is
available. Base-image and OS-package CVEs are invisible to the fs pass.
- TruffleHog: blocking from the start. The baseline is provably empty over
all 62 refs, so there is nothing to triage.
TruffleHog runs with --results=verified,unknown,unverified,filtered_unverified.
The default set hides findings that fail live verification, so a revoked or
inactive credential in the history yields a green run — on a public repository
that is still a leak.
No raw secret value reaches a log, a job summary or an artifact: Actions logs
and Code Scanning alerts are world-readable here. The summary carries detector,
commit and path only. For the same reason the Trivy report pass drops the
secret scanner before uploading SARIF and keeps secrets in the blocking gate.
Scanner images are digest-pinned and actions are SHA-pinned, so these files add
no findings to the very rules they run.
Signed-off-by: Grigoriy Gogin <Grigoriy.Gogin@constructor.tech>
c7ddade to
71714fe
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (5)
.github/workflows/trivy.yml (3)
43-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
TRIVY_IMAGEdigest duplicated withdocker.yml.The exact same digest-pinned string is repeated in
docker.yml(Line 192). Two independent places to update on the next Trivy bump invites drift. See consolidated comment.🤖 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 43 - 45, Consolidate the duplicated TRIVY_IMAGE value by defining it in one shared configuration location and reference that value from both trivy.yml and docker.yml. Remove the independently hardcoded digest while preserving the existing digest-pinned Trivy image behavior.
1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDigest-pinned
TRIVY_IMAGEis duplicated verbatim across two workflow files. A future Trivy version/digest bump requires remembering to update both locations in lockstep, or the two workflows silently drift onto different scanner versions.
.github/workflows/trivy.yml#L43-45: keep as the canonical declaration, or move to a shared repo/org-level Actions variable..github/workflows/docker.yml#L191-192: reference the same shared variable (e.g.vars.TRIVY_IMAGE) instead of a second hard-coded copy.🤖 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 at line 1, Eliminate the duplicated hard-coded TRIVY_IMAGE declaration in the Docker workflow by referencing the canonical declaration from the Trivy workflow or an appropriate shared Actions variable such as vars.TRIVY_IMAGE. Keep one authoritative digest-pinned value and update the Docker workflow’s Trivy invocation to consume it.
73-109: 🧹 Nitpick | 🔵 TrivialNo cross-run caching of the Trivy vulnerability DB.
/tmp/trivy-cacheis only reused within the same job's twodocker runinvocations; it isn't persisted between separate workflow runs (noactions/cachestep). Given this workflow fires on every PR, push, and nightly cron, each run re-downloads the DB from the publicghcr.io/aquasecurity/trivy-dbmirror, adding latency and exposure to anonymous pull-rate limiting. Worth wiring anactions/cachestep keyed on a date/version to persist/tmp/trivy-cache(or the DB's own cache dir) across runs — applies equally to thegatejob (which currently has no cache mount at all) and todocker.yml'strivy-imagejob.🤖 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 73 - 109, Persist the Trivy cache across workflow runs by adding an actions/cache step keyed by an appropriate date or Trivy database version, targeting /tmp/trivy-cache before the report scans execute. Apply the same cache setup and mount usage to the gate job, and update the trivy-image job in docker.yml to reuse its persisted database cache..github/workflows/docker.yml (2)
191-192: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicated
TRIVY_IMAGEpin — see consolidated comment.🤖 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/docker.yml around lines 191 - 192, Remove the duplicated TRIVY_IMAGE definition from the workflow and retain a single pinned value for the Trivy image, consolidating references to use that existing definition.
169-231: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueMake the
.trivyignorecheckout comment match the Trivy invocation.The table scan has no repository mount, so the checkout step’s “waivers” note doesn’t apply to that invocation. The SARIF scan already mounts
${{ github.workspace }}:/work, so if waivers are intended here, run Trivy from/workor pass--ignorefile /work/.trivyignore; otherwise remove the waiver-related justification from the checkout permission comment.🤖 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/docker.yml around lines 169 - 231, Update the trivy-image workflow’s checkout permission comment and Trivy invocations so the `.trivyignore` justification matches actual usage: either make both scans access the checked-out ignore file by running from `/work` or passing `--ignorefile /work/.trivyignore`, or remove the “.trivyignore waivers” justification from the contents permission if waivers are not intended.
🤖 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/semgrep.yml:
- Around line 91-93: Update the summary-writing logic around the Semgrep SAST
report so the Code scanning link and “full details” claim are included only when
the SARIF upload runs for non-fork pull requests; for fork PRs, state that Code
Scanning details are unavailable. Keep the finding count and report-only wording
unchanged.
- Around line 60-63: Update the Semgrep invocation in the workflow so all
enabled generic.secrets.* rules are excluded from the SARIF, not just
generic.secrets.security.detected-generic-secret. Use a non-secret rule set or
explicitly exclude every selected secret rule, then validate semgrep.sarif
contains no secret-related rule IDs before it is uploaded.
In @.github/workflows/trivy.yml:
- Around line 57-71: Update the Trivy invocation in the “Trivy fs scan —
CRITICAL only (blocking)” workflow step to explicitly load the workspace-root
waiver file by passing /src/.trivyignore via Trivy’s ignorefile option,
preserving the existing scan behavior and options.
- Line 1: Update every Trivy docker invocation in the workflow to explicitly
access the mounted .trivyignore file, using the matching workspace path (/src or
/work) via --ignorefile or an equivalent working directory setting. Ensure the
table-format image scan invocation also mounts the workspace and applies the
ignore file, preserving the existing scan behavior and output formats.
In @.github/workflows/trufflehog.yml:
- Around line 105-106: Update the TruffleHog summary generation around the
`git.get("file")` and `git.get("line")` fields so repository paths and line
values are not emitted to `GITHUB_STEP_SUMMARY`; report only the detector and
commit fields, while retaining local inspection of the commit for the exact
finding location.
---
Nitpick comments:
In @.github/workflows/docker.yml:
- Around line 191-192: Remove the duplicated TRIVY_IMAGE definition from the
workflow and retain a single pinned value for the Trivy image, consolidating
references to use that existing definition.
- Around line 169-231: Update the trivy-image workflow’s checkout permission
comment and Trivy invocations so the `.trivyignore` justification matches actual
usage: either make both scans access the checked-out ignore file by running from
`/work` or passing `--ignorefile /work/.trivyignore`, or remove the
“.trivyignore waivers” justification from the contents permission if waivers are
not intended.
In @.github/workflows/trivy.yml:
- Around line 43-45: Consolidate the duplicated TRIVY_IMAGE value by defining it
in one shared configuration location and reference that value from both
trivy.yml and docker.yml. Remove the independently hardcoded digest while
preserving the existing digest-pinned Trivy image behavior.
- Line 1: Eliminate the duplicated hard-coded TRIVY_IMAGE declaration in the
Docker workflow by referencing the canonical declaration from the Trivy workflow
or an appropriate shared Actions variable such as vars.TRIVY_IMAGE. Keep one
authoritative digest-pinned value and update the Docker workflow’s Trivy
invocation to consume it.
- Around line 73-109: Persist the Trivy cache across workflow runs by adding an
actions/cache step keyed by an appropriate date or Trivy database version,
targeting /tmp/trivy-cache before the report scans execute. Apply the same cache
setup and mount usage to the gate job, and update the trivy-image job in
docker.yml to reuse its persisted database cache.
🪄 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: b300e0a4-cf5b-4500-a700-66f64d125ff6
📒 Files selected for processing (6)
.github/workflows/docker.yml.github/workflows/semgrep.yml.github/workflows/trivy.yml.github/workflows/trufflehog.yml.gitignore.semgrepignore
| semgrep scan \ | ||
| --config auto \ | ||
| --exclude-rule generic.secrets.security.detected-generic-secret \ | ||
| --sarif --output semgrep.sarif |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow excerpt =="
sed -n '1,120p' .github/workflows/semgrep.yml
echo
echo "== repo Semgrep references =="
rg -n "semgrep|generic\.secrets|detected-generic-secret|sarif|CodeQL|Code Scanning" .github . 2>/dev/null | head -200
echo
echo "== search for Semgrep config files if any =="
git ls-files | grep -E '(^|/)semgrep|^\.semgrep|semgrep\.yaml|\.semgrepignore|\.semgrep$' || true
python3 - <<'PY'
from pathlib import Path
p=Path('.github/workflows/semgrep.yml')
text=p.read_text() if p.exists() else ''
for i,line in enumerate(text.splitlines(),1):
if 'exclude-rule' in line or 'semgrep scan' in line or 'semgrep.sarif' in line:
print(f'{p}:{i}:{line}')
PYRepository: constructorfabric/insight-front
Length of output: 9846
🌐 Web query:
semgrep exclude rule rule ID short ID generic.secrets detected-generic-secret official documentation excludes
💡 Result:
To exclude a specific Semgrep rule—such as detected-generic-secret—from your scans, you can use several methods depending on whether you want to exclude it globally, via the command line, or for specific files [1][2][3]. The full rule ID for generic secret detection typically follows the format generic.secrets.security.detected-generic-secret (or a variation depending on your configuration source) [4][5]. You should verify the exact rule ID in your Semgrep dashboard or by inspecting the rule file [6][3]. Methods to exclude the rule: 1. Command-Line Interface (CLI): Use the --exclude-rule flag when running a scan [6][3]. This is the most direct way to ignore a rule globally for a specific execution [2]. semgrep scan --exclude-rule <rule_ID> 2. Inline Comments: To ignore the rule for specific lines of code, add a nosemgrep comment on the line preceding the finding [1][2][3]. // nosemgrep: <rule_ID> 3. Rule-Level Path Exclusion: If you want to keep the rule active but skip it for certain files or directories, you can modify the rule itself (or create a custom version) by adding a paths: exclude: section in the rule's YAML configuration [1][4][7]. rules: - id: <rule_ID>... paths: exclude: - "path/to/ignore/*" 4. Semgrep Platform: If you are using the Semgrep AppSec Platform, you can triage findings as false positives or ignored risks directly in the dashboard [2][8][3]. These decisions persist across future scans, preventing the finding from being reported again [3]. For maintaining consistent ignores across a project without using CLI flags, creating a custom rule that extends the original but adds a paths: exclude: filter is a common practice [4][2].
Citations:
- 1: https://docs.semgrep.dev/ignoring-files-folders-code
- 2: https://stackoverflow.com/questions/75862330/how-to-ignore-a-single-rule-globally-with-semgrep
- 3: https://dev.to/rahulxsingh/how-to-set-up-semgrep-in-2026-complete-installation-and-configuration-guide-5emm
- 4: https://docs.semgrep.dev/kb/rules/exclude_rule_for_certain_filetypes
- 5: https://context7.com/semgrep/semgrep-rules/llms.txt
- 6: https://docs.semgrep.dev/kb/semgrep-supply-chain/exclude-rule
- 7: https://docs.semgrep.dev/writing-rules/rule-syntax
- 8: https://semgrep.dev/docs/semgrep-secrets/finding-details
🌐 Web query:
Semgrep CLI 1.170.0 help --exclude-rule rule ID generic.secrets.security.detected-generic-secret
💡 Result:
To exclude a specific rule by its ID when running Semgrep CLI, use the --exclude-rule flag followed by the rule ID [1][2]. Based on your query, the correct command syntax is: semgrep --exclude-rule generic.secrets.security.detected-generic-secret This flag can be used multiple times in a single command to exclude more than one rule [1]. For other ways to manage rule exclusions: - Inline comments: To ignore a specific rule in your code, you can add a comment with the nosemgrep annotation immediately before the flagged code (e.g., // nosemgrep: rule-id) [3][2]. - Rule configuration: You can edit the rule definition itself to include paths filters if you only want to exclude the rule on specific files or directories [3][4]. - Semgrep AppSec Platform: For secrets scans specifically, you can also manage ignores through the Semgrep AppSec Platform if applicable to your configuration [3]. The --exclude-rule flag is available in Semgrep CLI versions that support rule filtering by ID [5]. Since you are using version 1.170.0, this functionality is fully supported [1][6].
Citations:
- 1: https://docs.semgrep.dev/cli-reference
- 2: https://aicodereview.cc/blog/semgrep-cli-tutorial/
- 3: https://docs.semgrep.dev/ignoring-files-folders-code
- 4: https://docs.semgrep.dev/writing-rules/rule-syntax
- 5: Feature: Exclude rules by id with CLI flag semgrep/semgrep#5974
- 6: https://github.com/semgrep/semgrep/blob/93b8e2c6/cli/src/semgrep/commands/scan.py
🌐 Web query:
Semgrep docs --exclude-rule --exclude-prefix
💡 Result:
Semgrep does not have a flag named --exclude-prefix. It is likely you are confusing the standard --exclude flag with other command-line options. Below is a summary of how to use the available exclusion flags and related features: --exclude-rule <rule_ID> This flag is used to skip a specific rule during a scan [1][2][3]. It is useful for silencing noisy rules without removing them from your configuration [1]. You can specify this flag multiple times to exclude multiple rules [2][3]. --exclude This flag is used to skip files or directories that match a specified glob-style pattern [4][2][5]. The pattern syntax follows gitignore and semgrepignore conventions [4][5]. Like --exclude-rule, this flag can be specified multiple times in a single command [4][2][3]. Other Ways to Exclude or Include If you are looking for more granular control than command-line flags provide, Semgrep offers several alternatives: 1. Rule-level path filtering: Within a rule's configuration file (YAML), you can use the paths: key with include: or exclude: sub-keys to limit which files a specific rule runs on [6][7]. 2. Ignore files: You can create a.semgrepignore file in your project to persistently ignore specific files or directories across multiple scans [5][8]. 3. Inline suppression: You can use the # nosemgrep comment within your code to suppress findings on a per-line or per-file basis [1][7]. There is no command-line flag --exclude-prefix in Semgrep. If your goal was to exclude rules or paths based on a common prefix, you must provide the full rule ID or glob pattern, or use appropriate wildcard patterns (e.g., --exclude 'dir/*') within the supported --exclude flag [4][5].
Citations:
- 1: https://aicodereview.cc/blog/semgrep-cli-tutorial/
- 2: https://trickest.com/tools/semgrep-scan
- 3: https://linuxcommandlibrary.com/man/semgrep
- 4: https://docs.semgrep.dev/cli-reference
- 5: https://docs.semgrep.dev/ignoring-files-folders-code
- 6: https://docs.semgrep.dev/writing-rules/rule-syntax
- 7: https://docs.semgrep.dev/kb/rules/exclude_rule_for_certain_filetypes
- 8: https://semgrep.dev/docs/semgrepignore-v2-reference
🌐 Web query:
Semgrep secrets rules generic.secrets auto config
💡 Result:
Semgrep’s generic secrets detection, often referred to as "Generic secrets AI" or "AI augmented rules," is a feature designed to detect potential credentials (such as API keys and passwords) by identifying common keywords and surrounding context rather than relying solely on specific, hardcoded patterns [1]. To configure and enable generic secrets, you do not use a local "auto config" file in the traditional sense; instead, the feature is enabled and managed directly through the Semgrep AppSec Platform [1]. How to enable Generic Secrets: 1. Sign in to the Semgrep AppSec Platform. 2. Navigate to Settings > General > Secrets [1]. 3. Locate the Generic secrets section and toggle the switch to "On" [1]. Once enabled, subsequent scans will automatically incorporate generic secrets rules [1]. You can verify that these rules are active by checking the CLI output during a scan, which will display a confirmation message stating: "AI augmented rules are active for secrets detection" [1]. Key aspects of Generic Secrets: - Analysis Method: Findings identified via this method are analyzed by "Semgrep Multimodal" to eliminate false positives and highlight high-signal, actionable results [1]. - Management: You can manage and filter these findings in the Semgrep AppSec Platform under the Findings page by selecting the "Generic" option in the "Secret type" filter [1]. - Policies: You can further control how your organization handles these secrets by navigating to Rules & policies > Policies > Secrets in the AppSec Platform, where you can filter by "Analysis method" to distinguish between Semantic and Generic analysis [2]. For standard secret detection, Semgrep also supports custom rules and validator configurations, which can be managed via the Semgrep Editor in the AppSec Platform [3][2][4].
Citations:
- 1: https://semgrep.dev/docs/semgrep-secrets/generic-secrets
- 2: https://semgrep.dev/docs/semgrep-secrets/policies
- 3: https://docs.semgrep.dev/semgrep-secrets/rules
- 4: https://semgrep.dev/docs/semgrep-secrets/conceptual-overview
Exclude all enabled secret rules from the Semgrep SARIF.
--exclude-rule only excludes the single specified full rule ID; --config auto can select additional generic.secrets.* rules, and their findings are written to semgrep.sarif and uploaded to Code Scanning. Split this into a non-secret Semgrep rule set, or exclude every selected secret rule explicitly, then assert the generated SARIF contains no secret-related rule IDs.
🤖 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/semgrep.yml around lines 60 - 63, Update the Semgrep
invocation in the workflow so all enabled generic.secrets.* rules are excluded
from the SARIF, not just generic.secrets.security.detected-generic-secret. Use a
non-secret rule set or explicitly exclude every selected secret rule, then
validate semgrep.sarif contains no secret-related rule IDs before it is
uploaded.
| w("## Semgrep SAST (report-only)\n\n") | ||
| w(f"**{total}** finding(s) from `auto` (secrets excluded — TruffleHog owns those). " | ||
| f"This check does **not** block; full details in [Security -> Code scanning]({cs_url}).\n\n") |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Files:"
git ls-files .github/workflows/semgrep.yml | sed -n '1,20p'
echo
echo "Relevant workflow section:"
if [ -f .github/workflows/semgrep.yml ]; then
nl -ba .github/workflows/semgrep.yml | sed -n '1,180p'
else
echo "missing .github/workflows/semgrep.yml"
fi
echo
echo "Search for Code scanning reference and fork SARIF behavior:"
rg -n "fork|pull_request|sarif|Code scanning|Code scanning|code scanning|secrets excluded|TruffleHog|check does" .github/workflows/semgrep.yml .github/workflows || trueRepository: constructorfabric/insight-front
Length of output: 275
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Relevant workflow section:"
if [ -f .github/workflows/semgrep.yml ]; then
awk '{printf "%5d\t%s\n", NR, $0}' .github/workflows/semgrep.yml | sed -n '1,180p'
else
echo "missing .github/workflows/semgrep.yml"
fi
echo
echo "Search for fork/SARIF/Code scanning references:"
grep -En "fork|pull_request|sarif|Code scanning|code scanning|secrets excluded|TruffleHog" .github/workflows/semgrep.yml .github/workflows || trueRepository: constructorfabric/insight-front
Length of output: 8271
Do not promise Code Scanning details for fork PRs.
The SARIF upload is skipped for fork pull requests, but the job summary always says full details are available in Security -> Code scanning. Make that wording and link conditional on the same upload condition, or state that details are unavailable for fork PRs.
🤖 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/semgrep.yml around lines 91 - 93, Update the
summary-writing logic around the Semgrep SAST report so the Code scanning link
and “full details” claim are included only when the SARIF upload runs for
non-fork pull requests; for fork PRs, state that Code Scanning details are
unavailable. Keep the finding count and report-only wording unchanged.
| @@ -0,0 +1,169 @@ | |||
| name: Trivy SCA | |||
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)(\.github/workflows/trivy\.yml|\.github/workflows/docker\.yml|\.trivyignore|README|.*\.md)$' || true
echo "== trivy workflow =="
if [ -f .github/workflows/trivy.yml ]; then
nl -ba .github/workflows/trivy.yml | sed -n '1,130p'
fi
echo "== docker workflow relevant =="
if [ -f .github/workflows/docker.yml ]; then
nl -ba .github/workflows/docker.yml | sed -n '130,250p'
fi
echo "== trivyignore =="
if [ -f .trivyignore ]; then
nl -ba .trivyignore | sed -n '1,120p'
fi
echo "== search trivy invocations =="
rg -n "docker run|trivy|ignorefile|-w\b|--ignorefile|checkout \(\.trivyignore waivers\)|contents: read" .github/workflows || trueRepository: constructorfabric/insight-front
Length of output: 6528
🌐 Web query:
Trivy .trivyignore default ignorefile location container working directory -w --ignorefile
💡 Result:
The default location for the Trivy ignore file is a file named.trivyignore located in the current working directory [1][2][3]. You can specify a different ignore file location using the --ignorefile flag [4][2][3]. When using this flag, you must provide the path to your custom ignore file [5]. Key considerations for using --ignorefile: - The path provided to --ignorefile should be reachable by the Trivy process [5]. - In containerized environments, if you are running Trivy as a container, ensure the ignore file is mounted into the container at the path you specify in the --ignorefile flag so that Trivy can access it [5]. - Trivy may not produce a warning or error if the file specified by --ignorefile does not exist or cannot be accessed, so ensure the path is correctly configured [6]. - Note that.trivyignore (and the --ignorefile mechanism) generally applies to scan results; for some scan types (like misconfigurations in specific file formats such as Terraform or Dockerfiles), Trivy also supports inline comments for ignoring specific issues [7].
Citations:
- 1: https://trivy.dev/docs/v0.54/references/configuration/config-file/
- 2: https://github.com/aquasecurity/trivy/blob/main/docs/guide/references/configuration/cli/trivy_image.md
- 3: https://trivy.dev/docs/v0.56/guide/references/configuration/cli/trivy_config/
- 4: https://github.com/aquasecurity/trivy/blob/main/docs/guide/references/configuration/config-file.md
- 5: --ignorefile has no effect on the image scan aquasecurity/trivy#3415
- 6: --ignorefile silently fails if the file in question does not exist aquasecurity/trivy#7089
- 7: https://github.com/aquasecurity/trivy/blob/main/docs/guide/scanner/misconfiguration/config/config.md
🌐 Web query:
Trivy CLI default ignorefile .trivyignore current directory --ignorefile
💡 Result:
In the Trivy CLI, the default behavior regarding ignore files is as follows: Default Ignore File By default, Trivy automatically looks for a file named.trivyignore in the current working directory [1][2]. This file is used to specify vulnerabilities, misconfigurations, or secrets to be ignored during a scan [3]. Using the --ignorefile Option You can specify a custom ignore file path using the --ignorefile flag [1][4]. 1. Usage: When you provide a path via --ignorefile, Trivy uses that specific file instead of the default.trivyignore [3][5]. 2. Strict Requirement: If you explicitly specify an ignore file using the --ignorefile flag, Trivy expects that file to exist [6]. If the specified file is missing, the scan will fail with a fatal error [6]. This differs from the default behavior, where the absence of a.trivyignore file in the current directory does not cause the scan to fail [6]. 3. Supported Formats: -.trivyignore: The legacy format (plain text) [3][5]. -.trivyignore.yaml (or.yml): A structured YAML format that allows for more granular control, such as ignoring findings based on file paths, PURLs, or expiration dates [3][5]. Note that if you are using the YAML format, you must explicitly provide the path using the --ignorefile flag [3][5].
Citations:
- 1: https://trivy.dev/docs/latest/references/configuration/cli/trivy_config/
- 2: https://trivy.dev/docs/v0.50/guide/references/configuration/config-file/
- 3: https://trivy.dev/docs/latest/configuration/filtering/
- 4: https://trivy.dev/docs/v0.53/guide/references/configuration/cli/trivy_repository/
- 5: feat: add support for .trivyignore.yaml aquasecurity/trivy#5070
- 6: Changes to the handling of missing Trivy ignore file is a breaking change aquasecurity/trivy#9487
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow file sizes =="
wc -l .github/workflows/trivy.yml .github/workflows/docker.yml 2>/dev/null || true
echo "== trivy workflow =="
sed -n '1L,180Lp' .github/workflows/trivy.yml 2>/dev/null | awk '{printf "%5d %s\n", NR, $0}'
echo "== docker workflow relevant =="
sed -n '130L,260Lp' .github/workflows/docker.yml 2>/dev/null | awk '{printf "%5d %s\n", NR, $0}'
echo "== trivyignore =="
if [ -f .trivyignore ]; then
sed -n '1L,160Lp' .trivyignore | awk '{printf "%5d %s\n", NR, $0}'
else
echo ".trivyignore not found"
fi
echo "== relevant searches =="
rg -n "docker run|--scan|trivy|pull|image|repository|fs|sbom|ignorefile|--ignorefile|-w\b|checkout \(\.trivyignore waivers\)|contents: read|# checkout" .github/workflows || trueRepository: constructorfabric/insight-front
Length of output: 297
🌐 Web query:
aquasecurity/trivy docker run example --ignorefile .trivyignore volume mount -w workdir
💡 Result:
To use a.trivyignore file when running Trivy in a Docker container, you must mount the file into the container and point Trivy to it using the --ignorefile flag [1]. Example Docker Command To scan an image while using a.trivyignore file located in your current directory, use the following command: docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $(pwd)/.trivyignore:/root/.trivyignore \ -v
Citations:
- 1: https://oneuptime.com/blog/post/2026-02-08-how-to-run-aqua-security-scanner-in-docker/view
- 2: https://github.com/aquasecurity/trivy/blob/main/docs/getting-started/installation.md
- 3: https://www.howtogeek.com/devops/how-to-use-trivy-to-find-vulnerabilities-in-docker-containers/
- 4: https://edu.chainguard.dev/chainguard/chainguard-images/staying-secure/working-with-scanners/trivy-tutorial/
- 5: https://github.com/aquasecurity/trivy/blob/main/docs/guide/references/configuration/cli/trivy_image.md
- 6: https://github.com/aquasecurity/trivy/blob/main/docs/guide/references/configuration/config-file.md
- 7: https://hub.docker.com/hardened-images/catalog/dhi/trivy/guides
- 8: https://trivy.dev/docs/v0.50/guide/references/configuration/config-file/
- 9: https://trivy.dev/docs/v0.55/references/configuration/config-file/
- 10: https://bckinfo.com/trivy-docker-security-how-to-scan-and-fix-container-vulnerabilities/
🌐 Web query:
site:trivy.dev "--ignorefile" "default" ".trivyignore"
💡 Result:
The --ignorefile flag in Trivy is used to specify a file that contains identifiers for vulnerabilities, misconfigurations, secrets, or licenses to be ignored during a scan [1][2]. By default, Trivy looks for a file named.trivyignore [3][4]. Key details regarding the --ignorefile option include: Supported Formats: Trivy supports both.trivyignore (plain text) and.trivyignore.yaml (YAML) files [1]. The YAML format allows for more granular control, such as specifying paths, package URLs (purls), and expiration dates for ignored findings [1]. Configuration File Usage: In addition to the command-line flag, you can set the ignore file path in your Trivy configuration file using the ignorefile setting [3][4]. Experimental Feature: While.trivyignore is standard, the use of.trivyignore.yaml is sometimes noted as requiring explicit specification via the --ignorefile flag, as it may be treated as an experimental feature depending on your specific version [1]. Distinction from Skipping: It is important to distinguish --ignorefile (which filters out specific findings/results) from flags like --skip-files or --skip-dirs (which control which files or directories Trivy traverses or scans entirely) [1][5].
Citations:
- 1: https://trivy.dev/docs/latest/configuration/filtering/
- 2: https://trivy.dev/docs/v0.56/guide/references/configuration/cli/trivy_config/
- 3: https://trivy.dev/docs/v0.57/references/configuration/config-file/
- 4: https://trivy.dev/docs/latest/guide/references/configuration/config-file/
- 5: https://trivy.dev/docs/latest/configuration/skipping/
🏁 Script executed:
#!/bin/bash
set +e
echo "== shell env =="
printf 'SHELL=%s\nPWD=%s\n' "$SHELL" "$PWD"
echo "== files =="
git ls-files .github/workflows/trivy.yml .github/workflows/docker.yml .trivyignore README.md SECURITY.md CLAUDE.md 2>/dev/null
echo "== trivy workflow =="
python3 - <<'PY'
from pathlib import Path
p = Path(".github/workflows/trivy.yml")
print(f"exists={p.exists()} size={p.stat().st_size if p.exists() else 0}")
for i,line in enumerate(p.read_text(errors="replace").splitlines(),1):
print(f"{i:5d} {line}")
PY
echo "== docker workflow =="
python3 - <<'PY'
from pathlib import Path
p = Path(".github/workflows/docker.yml")
print(f"exists={p.exists()} size={p.stat().st_size if p.exists() else 0}")
for i,line in enumerate(p.read_text(errors="replace").splitlines(),1):
if 130 <= i <= 260:
print(f"{i:5d} {line}")
PY
echo "== trivy workflow relevant search =="
python3 - <<'PY'
from pathlib import Path
txt = Path(".github/workflows/trivy.yml").read_text(errors="replace")
for needle in ["docker run", "trivy", "ignorefile", "contents: read", "checkout"]:
print(f"\n-- {needle} --")
for lineno, line in enumerate(txt.splitlines(), 1):
if needle in line:
start=max(1, lineno-3); end=min(len(txt.splitlines()), lineno+5)
for sn in range(start, end+1):
print(f"{sn:5d} {txt.splitlines()[sn-1]}")
PY
echo "== .trivyignore presence and lines =="
python3 - <<'PY'
from pathlib import Path
p = Path(".trivyignore")
print(f"exists={p.exists()} size={p.stat().st_size if p.exists() else 0}")
if p.exists():
for i,line in enumerate(p.read_text(errors="replace").splitlines(),1):
print(f"{i:5d} {line}")
PYRepository: constructorfabric/insight-front
Length of output: 26025
🌐 Web query:
Trivy 0.72.0 default ignorefile --ignorefile .trivyignore .trivyignore.yaml
💡 Result:
In Trivy 0.72.0, the --ignorefile flag is used to specify the file containing ignore rules [1]. The default value for this flag, when it is not explicitly provided, is.trivyignore [1][2][3]. Key points regarding the behavior of --ignorefile: 1. Automatic vs. Explicit Loading: While Trivy automatically looks for.trivyignore in the working directory by default, files with the.yaml or.yml extension (such as.trivyignore.yaml) must generally be explicitly specified using the --ignorefile flag [4][5]. 2. File Parsing: Trivy detects the format based on the file extension [6]. If the specified file ends in.yaml or.yml, Trivy attempts to parse it as a structured YAML configuration [6][4]. Otherwise, it is parsed as a legacy.trivyignore file [6][5]. 3. Missing Files: If you provide a specific path via --ignorefile and the file does not exist, Trivy will treat this as an error and stop execution [7]. This behavior changed in recent versions to prevent silent misconfigurations in CI/CD pipelines [7][8]. If you need to support environments where the file might not be present, ensure the file is created or adjust your pipeline logic to handle its absence [7]. In summary, you do not need to set the flag if you are using the default.trivyignore [1][3]. If you are using.trivyignore.yaml or any other custom filename, you must use --ignorefile to ensure it is loaded correctly [4][5].
Citations:
- 1: https://github.com/aquasecurity/trivy/blob/57c9cd36/pkg/flag/report_flags.go
- 2: https://github.com/aquasecurity/trivy/blob/main/docs/guide/references/configuration/config-file.md
- 3: https://trivy.dev/docs/latest/guide/references/configuration/config-file/
- 4: https://trivy.dev/docs/latest/configuration/filtering/
- 5: feat: add support for .trivyignore.yaml aquasecurity/trivy#5070
- 6: https://github.com/aquasecurity/trivy/blob/main/pkg/result/ignore.go
- 7: Non existing --ignorefile breaks pipelines aquasecurity/trivy#7856
- 8: feat(misconf): Improve logging experience when
--ignorefilenot found aquasecurity/trivy#7093
Make .trivyignore accessible to each Trivy container
Trivy reads .trivyignore from the container’s working directory by default, but these docker run commands never set that directory; they run inside the image’s root directory while the workspace is mounted under /src//work. Add --ignorefile /src/.trivyignore/--ignorefile /work/.trivyignore (or --workingdir /src/--workingdir /work) to each invocation so the documented waiver workflow is not skipped end-to-end. Also don’t omit the mount from the table-format image scan at docker.yml:196-211.
🤖 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 at line 1, Update every Trivy docker invocation
in the workflow to explicitly access the mounted .trivyignore file, using the
matching workspace path (/src or /work) via --ignorefile or an equivalent
working directory setting. Ensure the table-format image scan invocation also
mounts the workspace and applies the ignore file, preserving the existing scan
behavior and output formats.
| - name: Trivy fs scan — CRITICAL only (blocking) | ||
| # `--ignore-unfixed` keeps the gate actionable: a CRITICAL with no released fix cannot | ||
| # be resolved by the PR author, so it belongs in the report pass, not in a merge block. | ||
| # Waivers go in `.trivyignore` at the repo root, date-scoped: | ||
| # CVE-2026-12345 exp:2026-12-31 # tracked in <issue>, fix queued | ||
| run: | | ||
| docker run --rm \ | ||
| -v "${{ github.workspace }}:/src:ro" \ | ||
| "$TRIVY_IMAGE" fs \ | ||
| --scanners vuln,secret,misconfig \ | ||
| --severity CRITICAL \ | ||
| --ignore-unfixed \ | ||
| --exit-code 1 \ | ||
| --no-progress \ | ||
| /src |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate workflows =="
git ls-files '.github/workflows/*' | sed -n '1,120p'
echo
echo "== trivy workflow excerpt =="
if [ -f .github/workflows/trivy.yml ]; then
nl -ba .github/workflows/trivy.yml | sed -n '1,120p'
fi
echo
echo "== docker workflow trivy mentions =="
rg -n -C 4 'trivy|TRIVY|--ignorefile|-w /src|docker run' .github/workflows docker.yml . 2>/dev/null | sed -n '1,220p' || true
echo
echo "== trivyignore files =="
git ls-files | grep -E '(^|/)\.trivyignore$' || true
echo
echo "== changed/files context around .github/workflows/trivy.yml =="
git status --shortRepository: constructorfabric/insight-front
Length of output: 411
🌐 Web query:
Trivy ignorefile default path docker run --ignorefile .trivyignore ./ --ignorefile .trivyignore documentation
💡 Result:
The default path for the Trivy ignore file is.trivyignore [1][2][3]. When running Trivy in a Docker container, you must ensure the ignore file is accessible to the containerized Trivy process. You can use the --ignorefile flag to specify a custom path, but because Trivy runs inside a container, you must mount the local ignore file into the container using the -v (volume) flag [4]. If you have a file named.trivyignore in your current local directory and wish to use it when scanning, you can run: docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v
Citations:
- 1: https://trivy.dev/docs/v0.51/references/configuration/config-file/
- 2: https://github.com/aquasecurity/trivy/blob/main/docs/guide/references/configuration/cli/trivy_image.md
- 3: https://trivy.dev/docs/v0.53/guide/references/configuration/cli/trivy_image/
- 4: --ignorefile has no effect on the image scan aquasecurity/trivy#3415
🌐 Web query:
Trivy CLI ignore file default location --ignorefile current working directory target path
💡 Result:
Trivy automatically checks for a file named.trivyignore in your current working directory by default [1]. If this file exists, Trivy will load it without requiring any additional configuration [1]. Key points regarding the ignore file: 1. Default Behavior: Trivy is configured to look for.trivyignore in the directory where the command is executed [2][3][1]. 2. Using --ignorefile: You can explicitly specify a different file or path using the --ignorefile flag (e.g., trivy image --ignorefile path/to/custom-ignore-file my-image:latest) [3][4][1]. 3. Validation: If you use the --ignorefile flag to specify a path, Trivy will verify that the file exists [5]. If the file cannot be found, Trivy will return an error [5][6]. 4. Supported Formats: While the default.trivyignore file is standard, Trivy also supports experimental YAML-based ignore files (e.g.,.trivyignore.yaml), which must be explicitly specified via the --ignorefile flag [7]. You do not need to provide any arguments for Trivy to utilize the.trivyignore file located in your current working directory; it is the default location [2][8][1].
Citations:
- 1: https://oneuptime.com/blog/post/2026-01-27-trivy-container-scanning/view
- 2: https://trivy.dev/docs/latest/references/configuration/cli/trivy_config/
- 3: https://github.com/aquasecurity/trivy/blob/main/docs/guide/references/configuration/cli/trivy_image.md
- 4: Support passing CVEs to ignore directly in command aquasecurity/trivy#1542
- 5: https://github.com/aquasecurity/trivy/blob/57c9cd36/pkg/flag/report_flags.go
- 6: feat(misconf): Improve logging experience when
--ignorefilenot found aquasecurity/trivy#7093 - 7: https://trivy.dev/docs/latest/configuration/filtering/
- 8: https://trivy.dev/docs/v0.50/guide/references/configuration/config-file/
🌐 Web query:
site:trivy.dev docs ignorefile .trivyignore default path current working directory
💡 Result:
By default, Trivy looks for an.trivyignore file in the current working directory [1][2][3]. The --ignorefile flag is used to specify the path to an ignore file if it is located elsewhere or has a different name [1][4]. Additionally, you can configure the path to the ignore file within a Trivy configuration file (typically trivy.yaml) by setting the ignorefile parameter [1][5].
Citations:
- 1: https://trivy.dev/docs/v0.57/references/configuration/config-file/
- 2: http://trivy.dev/v0.39/docs/references/cli/trivy_image/
- 3: http://trivy.dev/v0.47/docs/references/configuration/cli/trivy_repository/
- 4: https://trivy.dev/docs/v0.57/guide/references/configuration/cli/trivy_config/
- 5: https://trivy.dev/docs/v0.66/guide/configuration/
Point the .trivyignore waiver file into the Trivy cwd.
By default Trivy loads .trivyignore from the container’s current working directory, so a workspace-root waiver remains outside the scan process unless the container cwd is set to /src or --ignorefile /src/.trivyignore is passed.
🔧 Proposed fix
- name: Trivy fs scan — CRITICAL only (blocking)
run: |
docker run --rm \
-v "${{ github.workspace }}:/src:ro" \
+ -w /src \
"$TRIVY_IMAGE" fs \
--scanners vuln,secret,misconfig \
--severity CRITICAL \
--ignore-unfixed \
+ --ignorefile /src/.trivyignore \
--exit-code 1 \
--no-progress \
/src📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Trivy fs scan — CRITICAL only (blocking) | |
| # `--ignore-unfixed` keeps the gate actionable: a CRITICAL with no released fix cannot | |
| # be resolved by the PR author, so it belongs in the report pass, not in a merge block. | |
| # Waivers go in `.trivyignore` at the repo root, date-scoped: | |
| # CVE-2026-12345 exp:2026-12-31 # tracked in <issue>, fix queued | |
| run: | | |
| docker run --rm \ | |
| -v "${{ github.workspace }}:/src:ro" \ | |
| "$TRIVY_IMAGE" fs \ | |
| --scanners vuln,secret,misconfig \ | |
| --severity CRITICAL \ | |
| --ignore-unfixed \ | |
| --exit-code 1 \ | |
| --no-progress \ | |
| /src | |
| - name: Trivy fs scan — CRITICAL only (blocking) | |
| # `--ignore-unfixed` keeps the gate actionable: a CRITICAL with no released fix cannot | |
| # be resolved by the PR author, so it belongs in the report pass, not in a merge block. | |
| # Waivers go in `.trivyignore` at the repo root, date-scoped: | |
| # CVE-2026-12345 exp:2026-12-31 # tracked in <issue>, fix queued | |
| run: | | |
| docker run --rm \ | |
| -v "${{ github.workspace }}:/src:ro" \ | |
| -w /src \ | |
| "$TRIVY_IMAGE" fs \ | |
| --scanners vuln,secret,misconfig \ | |
| --severity CRITICAL \ | |
| --ignore-unfixed \ | |
| --ignorefile /src/.trivyignore \ | |
| --exit-code 1 \ | |
| --no-progress \ | |
| /src |
🤖 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 57 - 71, Update the Trivy
invocation in the “Trivy fs scan — CRITICAL only (blocking)” workflow step to
explicitly load the workspace-root waiver file by passing /src/.trivyignore via
Trivy’s ignorefile option, preserving the existing scan behavior and options.
| "file": git.get("file") or "?", | ||
| "line": git.get("line") or "", |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not emit repository paths verbatim in the summary.
Line 119 writes an untrusted filename directly to GITHUB_STEP_SUMMARY. A finding in a path containing a credential can disclose that value despite the redaction policy; path characters can also alter the Markdown table. Report only detector and commit, and inspect the commit locally for the exact location.
Proposed fix
- "file": git.get("file") or "?",
- "line": git.get("line") or "",
...
- w("| Detector | Verified | Commit | Path |\n|---|---|---|---|\n")
+ w("| Detector | Verified | Commit |\n|---|---|---|\n")
for r in sorted(rows, key=lambda r: (not r["verified"], r["detector"])):
- w(f"| `{r['detector']}` | {'yes' if r['verified'] else 'no'} | `{r['commit']}` | `{r['file']}`{':' + str(r['line']) if r['line'] else ''} |\n")
+ w(f"| `{r['detector']}` | {'yes' if r['verified'] else 'no'} | `{r['commit']}` |\n")Also applies to: 117-119
🤖 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 around lines 105 - 106, Update the
TruffleHog summary generation around the `git.get("file")` and `git.get("line")`
fields so repository paths and line values are not emitted to
`GITHUB_STEP_SUMMARY`; report only the detector and commit fields, while
retaining local inspection of the commit for the exact finding location.
docker.yml conflicted: #227 (branch-tagged image builds) added a "Report pushed image" step at the end of the merge job, exactly where this branch appends the trivy-image job. Both kept — the step stays inside merge, trivy-image follows as a separate job. trivy-image's gating comment was stale after #227: it justified the main-only condition by metadata-action's enable={{is_default_branch}}, which #227 removed so branch dispatches now push a tagged image too. The condition is unchanged (main-only, matching the promotion path it guards); the comment now says why and how to widen it. needs.merge.outputs.build_tag still resolves — merge forwards prepare's branch-suffixed tag. Signed-off-by: Konstantin Tursunov <konstantin.tursunov@constructor.tech>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/docker.yml:
- Around line 215-217: Add a second vulnerability-scan pass for the published
image in the workflow, explicitly setting --platform linux/arm64 and retaining
the existing scan options. Upload the arm64 results to Code Scanning with a
distinct SARIF category from the amd64 scan, while preserving the current amd64
pass.
- Around line 231-249: Update both Trivy image scan commands in the Docker
workflow to include the --scanners vuln option, ensuring the terminal table and
trivy-image.sarif contain vulnerability findings only while preserving their
existing severity, output, 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: 750e3a3b-2edd-4cba-b81c-79ad77f61a43
📒 Files selected for processing (6)
.github/workflows/docker.yml.github/workflows/semgrep.yml.github/workflows/trivy.yml.github/workflows/trufflehog.yml.gitignore.semgrepignore
🚧 Files skipped from review as they are similar to previous changes (5)
- .semgrepignore
- .gitignore
- .github/workflows/trufflehog.yml
- .github/workflows/trivy.yml
- .github/workflows/semgrep.yml
| # `--ignore-unfixed` keeps the output to what a base-image bump can actually fix. | ||
| # A multi-arch manifest resolves to the runner's platform (linux/amd64); the arm64 | ||
| # leg shares the same base image and package set, so one pass is representative. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow context =="
if [ -f .github/workflows/docker.yml ]; then
nl -ba .github/workflows/docker.yml | sed -n '180,250p'
else
echo "missing .github/workflows/docker.yml"
fi
echo
echo "== trivy invocations in docker workflow =="
rg -n "trivy|sarif|platform|scan" .github/workflows/docker.yml || true
echo
echo "== workflow files =="
git ls-files '.github/workflows/*'Repository: constructorfabric/insight-front
Length of output: 232
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow context =="
if [ -f .github/workflows/docker.yml ]; then
awk '{printf "%6d %s\n", NR, $0}' .github/workflows/docker.yml | sed -n '180,250p'
else
echo "missing .github/workflows/docker.yml"
fi
echo
echo "== trivy invocations in docker workflow =="
grep -nE "trivy|sarif|platform|scan|multi-arch|manifest|docker manifest|linux/amd64|linux/arm64" .github/workflows/docker.yml || true
echo
echo "== workflow files =="
git ls-files '.github/workflows/*'Repository: constructorfabric/insight-front
Length of output: 6385
🌐 Web query:
Trivy container image scan multi-platform image default platform --platform documentation
💡 Result:
In Trivy, the --platform flag is used to specify the operating system and architecture (in the format os/architecture) for scanning multi-platform container images [1][2]. Regarding the default behavior and the --platform flag: - Default Behavior: When the --platform flag is not specified, Trivy attempts to load the image based on the platform of the host machine where Trivy is running [1][3]. For example, on a linux/amd64 host, Trivy defaults to scanning the linux/amd64 version of a multi-arch image [1][3]. - Using --platform: If you need to scan a specific architecture or OS variant, you can use the --platform argument to explicitly set the desired platform [1][3]. For example: trivy image --platform=linux/arm64 [YOUR_IMAGE_NAME] Additional Considerations: - Compatibility: The --platform flag is primarily intended for multi-platform images. If you specify a platform that does not exist within the image's manifest, the scan result may depend on how the underlying registry or container engine handles the request, as Trivy aims to mimic the behavior of standard container tools like Docker [4][5]. - Local vs. Remote: When scanning local images (e.g., from Docker Engine), Trivy relies on the container engine to provide the image content [3][6]. When scanning remote images, Trivy interacts directly with the registry, which can sometimes lead to differing behaviors compared to local scanning if platform auto-detection is not aligned [6]. - Configuration: You can also set this parameter in the Trivy configuration file using the image.platform key [7].
Citations:
- 1: https://trivy.dev/docs/latest/guide/target/container_image/
- 2: https://trivy.dev/docs/latest/references/configuration/cli/trivy_image/
- 3: https://github.com/aquasecurity/trivy/blob/main/docs/guide/target/container_image.md
- 4: fix(containerd): Use img platform in exporter instead of strict host platform aquasecurity/trivy#4477
- 5: Platform flag is being ignored when scanning an image aquasecurity/trivy#4310
- 6: Detect local platform when scanning image from remote source aquasecurity/trivy#9360
- 7: https://trivy.dev/docs/v0.57/references/configuration/config-file/
🌐 Web query:
GitHub Code Scanning SARIF upload max 5 results upload-sarif multiple SARIF files
💡 Result:
GitHub Code Scanning supports uploading multiple SARIF files for a single commit [1][2]. To upload multiple files, you must ensure each file represents a unique set of results by assigning each a unique "category" [1][3]. By default, code scanning expects one SARIF file per analysis; uploading a second file for the same category and tool will overwrite the previous results [1][4]. If you attempt to upload multiple files for the same tool and category within a single GitHub Actions workflow run, the configuration is considered invalid, and the run will fail [1][3]. Key details for managing multiple SARIF files: - The upload-sarif action's sarif_file input accepts both a single file path and a directory path [1][5]. When a directory is provided, the action recursively searches for and uploads all files ending in.sarif [6]. - Each SARIF file in a directory upload must be identified as a unique set, often by ensuring each file contains a unique runAutomationDetails.id if a category is not explicitly provided [4][3]. - While SARIF supports multiple files, GitHub imposes strict limits on the data contained within those files [7][8]. For example, a single run can contain a maximum of 25,000 results, with only the top 5,000 results displayed [7][8]. If a file exceeds these thresholds, it may be rejected or truncated [7][8]. The "5 results" limit mentioned in your query does not exist as a global hard limit for uploads, though specific data objects within the SARIF structure are subject to various hard and soft limits (e.g., maximum results per run, maximum locations per result) [7][9][8].
Citations:
- 1: https://docs.github.com/en/code-security/how-tos/find-and-fix-code-vulnerabilities/integrate-with-existing-tools/upload-sarif-file
- 2: https://docs.github.com/en/enterprise-server@3.16/code-security/how-tos/find-and-fix-code-vulnerabilities/integrate-with-existing-tools/upload-sarif-file
- 3: https://docs.github.com/en/enterprise-server@3.19/code-security/how-tos/find-and-fix-code-vulnerabilities/integrate-with-existing-tools/upload-sarif-file
- 4: https://help.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/uploading-a-sarif-file-to-github
- 5: https://github.com/github/docs/blob/main/content/code-security/how-tos/find-and-fix-code-vulnerabilities/integrate-with-existing-tools/uploading-a-sarif-file-to-github.md
- 6: Upload multiple sarif files github/codeql-action#1573
- 7: https://docs.github.com/en/enterprise-cloud@latest/code-security/reference/code-scanning/sarif-files/sarif-support
- 8: https://help.github.com/en/enterprise-server@3.10/code-security/code-scanning/troubleshooting-sarif-uploads/results-exceed-limit
- 9: https://github.com/github/docs/blob/main/content/code-security/reference/code-scanning/sarif-files/troubleshoot-sarif-uploads/results-exceed-limit.md
Scan the published arm64 image as well.
The workflow builds linux/amd64 and linux/arm64, but this check resolves the tag from the runner and scans only amd64. Add an explicit arm64 pass with --platform linux/arm64 and upload it under a distinct SARIF category so both image architectures are covered by Code Scanning.
🤖 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/docker.yml around lines 215 - 217, Add a second
vulnerability-scan pass for the published image in the workflow, explicitly
setting --platform linux/arm64 and retaining the existing scan options. Upload
the arm64 results to Code Scanning with a distinct SARIF category from the amd64
scan, while preserving the current amd64 pass.
There was a problem hiding this comment.
not required, publishing only amd64
There was a problem hiding this comment.
@ktursunov, the current workflow appears to publish both architectures: the build matrix pushes linux/amd64 and linux/arm64, and merge assembles them into one multi-arch manifest. As written, the scan covers only the amd64 variant.
If arm64 publication is no longer intended, removing the arm64 matrix leg would make this finding inapplicable; otherwise, the separate arm64 scan remains relevant.
| "$TRIVY_IMAGE" image \ | ||
| --severity CRITICAL,HIGH \ | ||
| --pkg-types os,library \ | ||
| --ignore-unfixed \ | ||
| --exit-code 0 \ | ||
| --no-progress \ | ||
| --format table \ | ||
| "$IMAGE_REF" | ||
| docker run --rm \ | ||
| -v "${{ github.workspace }}:/work" \ | ||
| -v /tmp/trivy-cache:/root/.cache \ | ||
| -e TRIVY_USERNAME -e TRIVY_PASSWORD \ | ||
| "$TRIVY_IMAGE" image \ | ||
| --severity CRITICAL,HIGH \ | ||
| --pkg-types os,library \ | ||
| --ignore-unfixed \ | ||
| --exit-code 0 \ | ||
| --no-progress \ | ||
| --format sarif --output /work/trivy-image.sarif \ |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow excerpt =="
if [ -f .github/workflows/docker.yml ]; then
sed -n '200,270p' .github/workflows/docker.yml | cat -n
else
echo ".github/workflows/docker.yml not found"
fi
echo
echo "== trivy references in workflow =="
rg -n "trivy|TRIVY|scanners|sarif|secret" .github/workflows/docker.yml || true
echo
echo "== related PR/workflow files =="
git ls-files '.github/workflows/*' . | sed -n '1,120p'Repository: constructorfabric/insight-front
Length of output: 9673
🌐 Web query:
Trivy v0.72 image --scanners default vuln secret SARIF output
💡 Result:
To generate a SARIF report for an image scan using Trivy v0.72, you can use the built-in --format sarif flag [1][2][3]. Since vulnerability (vuln) and secret (secret) scanning are enabled by default for container image scans [4][5][6], you do not need to explicitly specify them unless you wish to limit the scope of the scan [5][7]. The command syntax is as follows: trivy image --format sarif --output report.sarif [IMAGE_NAME] Explanation of flags: --format sarif: Sets the output format to SARIF (Static Analysis Results Interchange Format) [1][2][3]. --output report.sarif: Specifies the file path where the report should be saved [2][3][8]. --scanners [vuln,secret]: These are enabled by default, so omitting them defaults to running both [4][5]. If you want to explicitly ensure both are included, you can append --scanners vuln,secret to the command [4][1]. Note: Earlier versions of Trivy occasionally required the use of --template for SARIF generation, but modern versions (including v0.72) support --format sarif natively [1][2][3].
Citations:
- 1: https://github.com/aquasecurity/trivy/blob/main/docs/guide/references/configuration/cli/trivy_image.md
- 2: https://trivy.dev/docs/v0.53/guide/references/configuration/cli/trivy_image/
- 3: https://adhdecode.com/articles/trivy/trivy-output-formats-json-sarif-table/
- 4: https://trivy.dev/docs/latest/references/configuration/cli/trivy_image/
- 5: https://github.com/aquasecurity/trivy/blob/main/docs/guide/target/container_image.md
- 6: https://github.com/aquasecurity/trivy/blob/main/docs/guide/scanner/secret.md
- 7: https://github.com/aquasecurity/trivy/blob/main/docs/guide/configuration/others.md
- 8: https://www.commands.sh/trivy
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== trivy workflow excerpt =="
if [ -f .github/workflows/trivy.yml ]; then
sed -n '1,240p' .github/workflows/trivy.yml | cat -n
else
echo ".github/workflows/trivy.yml not found"
fi
echo
echo "== secret scanner references across workflows =="
rg -n "trivy|upload-sarif|secrets|secret|scanners|SARIF" .github/workflows/trivy.yml .github/workflows/docker.yml .github/workflows/semgrep.yml .github/workflows/trufflehog.yml || trueRepository: constructorfabric/insight-front
Length of output: 15552
Vulnerability-only image scans here.
Trivy image scans default to vuln,secret, so both the terminal table and the uploaded trivy-image.sarif can include secret findings even though secret detection is owned by the TruffleHog workflow. Add --scanners vuln to both image commands to keep this SARIF pass aligned with the vulnerability-only reporting contract.
Proposed fix
"$TRIVY_IMAGE" image \
+ --scanners vuln \
--severity CRITICAL,HIGH \
@@
"$TRIVY_IMAGE" image \
+ --scanners vuln \
--severity CRITICAL,HIGH \📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "$TRIVY_IMAGE" image \ | |
| --severity CRITICAL,HIGH \ | |
| --pkg-types os,library \ | |
| --ignore-unfixed \ | |
| --exit-code 0 \ | |
| --no-progress \ | |
| --format table \ | |
| "$IMAGE_REF" | |
| docker run --rm \ | |
| -v "${{ github.workspace }}:/work" \ | |
| -v /tmp/trivy-cache:/root/.cache \ | |
| -e TRIVY_USERNAME -e TRIVY_PASSWORD \ | |
| "$TRIVY_IMAGE" image \ | |
| --severity CRITICAL,HIGH \ | |
| --pkg-types os,library \ | |
| --ignore-unfixed \ | |
| --exit-code 0 \ | |
| --no-progress \ | |
| --format sarif --output /work/trivy-image.sarif \ | |
| "$TRIVY_IMAGE" image \ | |
| --scanners vuln \ | |
| --severity CRITICAL,HIGH \ | |
| --pkg-types os,library \ | |
| --ignore-unfixed \ | |
| --exit-code 0 \ | |
| --no-progress \ | |
| --format table \ | |
| "$IMAGE_REF" | |
| docker run --rm \ | |
| -v "${{ github.workspace }}:/work" \ | |
| -v /tmp/trivy-cache:/root/.cache \ | |
| -e TRIVY_USERNAME -e TRIVY_PASSWORD \ | |
| "$TRIVY_IMAGE" image \ | |
| --scanners vuln \ | |
| --severity CRITICAL,HIGH \ | |
| --pkg-types os,library \ | |
| --ignore-unfixed \ | |
| --exit-code 0 \ | |
| --no-progress \ | |
| --format sarif --output /work/trivy-image.sarif \ |
🤖 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/docker.yml around lines 231 - 249, Update both Trivy image
scan commands in the Docker workflow to include the --scanners vuln option,
ensuring the terminal table and trivy-image.sarif contain vulnerability findings
only while preserving their existing severity, output, and exit-code settings.
Adds the three scanning domains this repository had none of: static analysis, secret detection, and software-composition analysis over both the source tree and the built image.
semgrep.ymlis a port ofconstructorfabric/insight's workflow so findings stay comparable across the two repos, minus thep/rust/p/csharppacks (no Rust or C# here).Rollout state per gate
Driven by the measured baseline, not by a uniform policy:
sast(Semgrep)src/and that one is a false positivegate(Trivy fs, CRITICAL)report(Trivy fs, HIGH/MED/LOW)trivy-image(docker.yml)secrets(TruffleHog)TruffleHog blocks from the start because there is nothing to triage. Semgrep and the Trivy report pass ratchet to blocking later: add
--errorfor Semgrep,--exit-code 1plustrivy-imageindispatch-umbrella'sneedsto bar a vulnerable image from promotion.Two decisions worth reviewing
--results=verified,unknown,unverified,filtered_unverifiedon TruffleHog. The default (verified,unknown) suppresses findings whose live verification fails, so an already-revoked or inactive credential in the history produces a green run — on a public repository that is still a leak requiring rotation. Verified against a control repository with a planted key: with the default flags TruffleHog found it and reported nothing; with all four result kinds it reported detector, commit and path.No raw secret value reaches a log, a job summary or an artifact. Actions logs and Code Scanning alerts are world-readable on a public repo, so echoing a hit would publish the value the gate exists to protect. The summary carries detector, commit and path only. For the same reason the Trivy report pass drops the secret scanner before uploading SARIF (
--scanners vuln,misconfig) and secrets stay in the blocking gate.Scanner images are digest-pinned and every action is SHA-pinned, so these files add no findings to the rules they run — confirmed by diffing Semgrep output before and after.
Test plan
Everything below was run locally against this branch.
actionlint(with shellcheck overrun:blocks) — no findings in the new or changed code. Two pre-existing SC2046 warnings remain onCreate multi-arch manifest and push(docker.yml), untouchedpnpm-lock.yaml: 0 CRITICAL,Dockerfile: 0 CRITICAL).semgrepignore— 17 findings over 438 targets, down from 21 over 579trivy-imageagainst the published manifest — needs a pushed tag, so it first runs on merge tomainSemgrep OSS17 results andTrivy31 results (29 CVEs + 2 misconfigurations) recorded againstrefs/pull/225/mergeGitHub re-ranks Semgrep severity from rule metadata rather than the SARIF
level, so four alerts land at error severity:missing-userandmissing-user-entrypoint(Dockerfile:30-31),run-shell-injection(ci.yml:166) anduse-defused-xml-parse(scripts/ci/coverage-summary.py:58). The remaining 13 - all mutable action tags - are warnings.Note
Code Scanning upload is free while this repository is public. If it returns to private, the three
upload-sarifsteps will fail without GitHub Advanced Security; the job-summary reports would keep working.Summary by CodeRabbit
Refs constructorfabric/insight#2079