Conversation
…-security-scan workflow
WalkthroughThis PR adds comprehensive documentation for GitHub Actions composites and reusable workflows covering configurability, reserved input/secret names, and step organization conventions. It introduces two new security actions (Docker Scout and PR Security Reporter), updates existing notification and workflow actions with enhanced logic and section comments, and migrates local action references to remote sources. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
.github/workflows/pr-security-scan.yml (1)
10-56:⚠️ Potential issue | 🟠 MajorMissing
workflow_dispatchtrigger anddry_runinput.Per repo convention, reusable workflows must expose both
workflow_callandworkflow_dispatchtriggers, plus adry_runinput (default:false) for manual testing and preview runs.Proposed fix
on: workflow_call: inputs: + dry_run: + description: 'Run in dry-run mode (preview only, no PR comments posted)' + type: boolean + default: false runner_type: description: 'GitHub runner type to use' type: string default: 'blacksmith-4vcpu-ubuntu-2404' # ... rest of inputs ... + + workflow_dispatch: + inputs: + dry_run: + description: 'Run in dry-run mode (preview only, no PR comments posted)' + type: boolean + default: false + runner_type: + description: 'GitHub runner type to use' + type: string + default: 'blacksmith-4vcpu-ubuntu-2404' + # Mirror remaining workflow_call inputs here for manual dispatchBased on learnings: "Enforce that every reusable GitHub Actions workflow in LerianStudio/github-actions-shared-workflows exposes both workflow_call and workflow_dispatch triggers, and includes a dry_run input (default: false)."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/pr-security-scan.yml around lines 10 - 56, Add a manual trigger and dry-run input to this reusable workflow: add a workflow_dispatch trigger alongside the existing workflow_call, and add an inputs.dry_run boolean (default: false) to the workflow_call inputs so consumers and manual runs can perform preview/testing; modify the top-level triggers to include workflow_dispatch and add the dry_run input entry (name it dry_run, type boolean, default false) to the inputs block that currently contains runner_type, filter_paths, etc., referencing the existing workflow_call and inputs sections.src/notify/discord-release/action.yml (1)
43-63:⚠️ Potential issue | 🟠 MajorHarden both Bash blocks: direct interpolation is injection-prone, and
contentis logged in plain text.Move values to
envvariables, quote$GITHUB_OUTPUT, useprintffor output, and redactcontentin dry-run logs. Per coding guidelines, never print potentially sensitive data viaechoor step output.Suggested hardening patch
- name: Detect beta release id: beta shell: bash + env: + RELEASE_TAG: ${{ inputs.release-tag }} run: | - if [[ "${{ inputs.release-tag }}" == *"-beta."* ]]; then - echo "is_beta=true" >> $GITHUB_OUTPUT + if [[ "$RELEASE_TAG" == *"-beta."* ]]; then + echo "is_beta=true" >> "$GITHUB_OUTPUT" else - echo "is_beta=false" >> $GITHUB_OUTPUT + echo "is_beta=false" >> "$GITHUB_OUTPUT" fi @@ - name: Dry run summary if: inputs.dry-run == 'true' shell: bash + env: + RELEASE_TAG: ${{ inputs.release-tag }} + COLOR: ${{ inputs.color }} + USERNAME: ${{ inputs.username }} + SKIP_BETA: ${{ inputs.skip-beta }} + IS_BETA: ${{ steps.beta.outputs.is_beta }} run: | echo "::notice::DRY RUN — Discord notification will not be sent" echo " webhook : (configured)" - echo " release-tag : ${{ inputs.release-tag }}" - echo " color : ${{ inputs.color }}" - echo " username : ${{ inputs.username }}" - echo " content : ${{ inputs.content }}" - echo " skip-beta : ${{ inputs.skip-beta }}" - echo " is_beta : ${{ steps.beta.outputs.is_beta }}" + printf ' release-tag : %s\n' "$RELEASE_TAG" + printf ' color : %s\n' "$COLOR" + printf ' username : %s\n' "$USERNAME" + echo " content : (redacted)" + printf ' skip-beta : %s\n' "$SKIP_BETA" + printf ' is_beta : %s\n' "$IS_BETA"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/notify/discord-release/action.yml` around lines 43 - 63, The Bash blocks are injection-prone and print potentially sensitive content; update the "if" block and the "Dry run summary" step to set inputs (like inputs.release-tag, inputs.color, inputs.username, inputs.skip-beta, inputs.content) into environment variables instead of direct interpolation, write to GITHUB_OUTPUT using a quoted redirect ("$GITHUB_OUTPUT") from a safe printf call in the beta check (e.g., produce is_beta via printf), and change the Dry run summary to use printf with the environment vars and redact or omit the actual inputs.content value (replace with "[REDACTED]" or similar) so no sensitive text is echoed or emitted via step outputs (refer to steps.beta.outputs.is_beta and the Dry run summary step name when locating the run blocks to modify).src/notify/slack-release/action.yml (1)
37-43:⚠️ Potential issue | 🟠 MajorHarden Bash input interpolation against command injection at lines 39–43.
Direct
${{ inputs.* }}interpolation within the bashrunscript at lines 39–43 is vulnerable to command injection. These user-provided inputs expand as literal shell code before execution; a caller providingchannel: "test'; rm -rf /"would inject commands.Move inputs to
envvariables and useprintf %sinstead ofecho:Hardening patch
- name: Dry run summary if: inputs.dry-run == 'true' shell: bash + env: + CHANNEL: ${{ inputs.channel }} + PRODUCT_NAME: ${{ inputs.product-name }} + RELEASE_TAG: ${{ inputs.release-tag }} + COLOR: ${{ inputs.color }} + ICON_EMOJI: ${{ inputs.icon-emoji }} run: | echo "::notice::DRY RUN — Slack notification will not be sent" - echo " channel : ${{ inputs.channel }}" - echo " product-name : ${{ inputs.product-name }}" - echo " release-tag : ${{ inputs.release-tag }}" - echo " color : ${{ inputs.color }}" - echo " icon-emoji : ${{ inputs.icon-emoji }}" + printf ' channel : %s\n' "$CHANNEL" + printf ' product-name : %s\n' "$PRODUCT_NAME" + printf ' release-tag : %s\n' "$RELEASE_TAG" + printf ' color : %s\n' "$COLOR" + printf ' icon-emoji : %s\n' "$ICON_EMOJI"Note: Lines 50–55 using
envare safe—GitHub Actions sets environment variables directly without shell evaluation.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/notify/slack-release/action.yml` around lines 37 - 43, The DRY RUN bash block interpolates GitHub Action inputs directly into the shell (channel, product-name, release-tag, color, icon-emoji) which allows command injection; change the step to export those inputs into environment variables (e.g., CHANNEL, PRODUCT_NAME, RELEASE_TAG, COLOR, ICON_EMOJI) via the step's env mapping and then replace the echo lines with safe printing using printf '%s\n' "$CHANNEL" etc. Ensure all references use the env var names (not `${{ inputs.* }}`) and quote the variable expansions to prevent word-splitting and globbing while keeping the same message format including the initial "::notice::DRY RUN — Slack notification will not be sent".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.claude/commands/composite.md:
- Around line 100-106: The fenced code block containing the three-layer flow
diagram is missing a language specifier; update the triple-backtick fence that
wraps the diagram to include a language tag (e.g., change ``` to ```text or
```plaintext) so linters accept it—look for the fenced block showing "Caller
repo Reusable workflow Composite" and add the language identifier immediately
after the opening backticks.
In @.claude/commands/gha.md:
- Around line 326-332: The fenced code block showing the ASCII table (starting
with "Caller repo Reusable workflow Composite" and ending
with "recommendations }}") is missing a language specifier; update the
triple-backtick fence around that block to include "text" (i.e., change ``` to
```text) so the block renders correctly and preserves spacing in the Markdown
(look for the exact fenced block containing "enable_docker_scout" /
"enable-recommendations" to modify).
In @.cursor/rules/composite-actions.mdc:
- Around line 140-146: The fenced code block showing the table lacks a language
specifier; update the block that begins with the triple backticks and the table
("Caller repo ... Composite") to use a plaintext/text fence (e.g., ```text) so
syntax highlighters render it consistently with other docs; locate the fenced
block in composite-actions.mdc and change the opening fence to include "text"
(or "plaintext") and keep the rest unchanged.
In @.cursor/rules/reusable-workflows.mdc:
- Around line 238-245: The fenced code block containing the three-column flow
diagram (the block starting with "Caller repo Reusable
workflow Composite" and the ASCII table) is missing a language
specifier; update that fenced block to include a language identifier (use "text"
as in the proposed fix) so it becomes ```text ... ``` to ensure proper
rendering, mirroring the same change made in composite.md; locate the diagram
block in the reusable-workflows.mdc file and add the "text" specifier to the
opening fence.
In `@docs/pr-security-scan-workflow.md`:
- Around line 180-181: The inputs documentation table is missing the
enable_docker_scout_recommendations input; add a new row for
enable_docker_scout_recommendations with type boolean, default true, and
description "Enable Docker Scout recommendations to surface Dockerfile issues
(non-root user, missing attestations, base image gaps)" so the table matches the
workflow's defined input (enable_docker_scout_recommendations) referenced
earlier in the file.
In `@src/security/docker-scout/action.yml`:
- Around line 111-119: The run step currently assigns QUICKVIEW_OUTPUT and
CVES_OUTPUT by interpolating '${{ steps.quickview.outputs.quickview }}' and '${{
steps.cves.outputs.cves }}' into single-quoted shell strings which can break on
quotes/newlines; instead export these outputs as environment variables or use a
here-doc to safely capture multi-line content before grepping: set
QUICKVIEW_OUTPUT and CVES_OUTPUT via the GitHub Actions env mechanism or use
printf '%s' with a here-doc so the grep line that checks for
'(critical|high|medium|low)\s+[1-9]' reads from those safe variables; update
references to QUICKVIEW_OUTPUT, CVES_OUTPUT, and HAS_VULNS accordingly so no
unquoted shell interpolation occurs.
---
Outside diff comments:
In @.github/workflows/pr-security-scan.yml:
- Around line 10-56: Add a manual trigger and dry-run input to this reusable
workflow: add a workflow_dispatch trigger alongside the existing workflow_call,
and add an inputs.dry_run boolean (default: false) to the workflow_call inputs
so consumers and manual runs can perform preview/testing; modify the top-level
triggers to include workflow_dispatch and add the dry_run input entry (name it
dry_run, type boolean, default false) to the inputs block that currently
contains runner_type, filter_paths, etc., referencing the existing workflow_call
and inputs sections.
In `@src/notify/discord-release/action.yml`:
- Around line 43-63: The Bash blocks are injection-prone and print potentially
sensitive content; update the "if" block and the "Dry run summary" step to set
inputs (like inputs.release-tag, inputs.color, inputs.username,
inputs.skip-beta, inputs.content) into environment variables instead of direct
interpolation, write to GITHUB_OUTPUT using a quoted redirect ("$GITHUB_OUTPUT")
from a safe printf call in the beta check (e.g., produce is_beta via printf),
and change the Dry run summary to use printf with the environment vars and
redact or omit the actual inputs.content value (replace with "[REDACTED]" or
similar) so no sensitive text is echoed or emitted via step outputs (refer to
steps.beta.outputs.is_beta and the Dry run summary step name when locating the
run blocks to modify).
In `@src/notify/slack-release/action.yml`:
- Around line 37-43: The DRY RUN bash block interpolates GitHub Action inputs
directly into the shell (channel, product-name, release-tag, color, icon-emoji)
which allows command injection; change the step to export those inputs into
environment variables (e.g., CHANNEL, PRODUCT_NAME, RELEASE_TAG, COLOR,
ICON_EMOJI) via the step's env mapping and then replace the echo lines with safe
printing using printf '%s\n' "$CHANNEL" etc. Ensure all references use the env
var names (not `${{ inputs.* }}`) and quote the variable expansions to prevent
word-splitting and globbing while keeping the same message format including the
initial "::notice::DRY RUN — Slack notification will not be sent".
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 87b0d7f6-7400-4cfe-b897-d1752874e2d4
📒 Files selected for processing (16)
.claude/commands/composite.md.claude/commands/gha.md.claude/commands/workflow.md.cursor/rules/composite-actions.mdc.cursor/rules/reusable-workflows.mdc.github/workflows/branch-cleanup.yml.github/workflows/labels-sync.yml.github/workflows/pr-security-scan.ymldocs/pr-security-scan-workflow.mdsrc/build/docker-build-ts/action.ymlsrc/config/branch-cleanup/action.ymlsrc/config/labels-sync/action.ymlsrc/notify/discord-release/action.ymlsrc/notify/slack-release/action.ymlsrc/security/docker-scout/README.mdsrc/security/docker-scout/action.yml
All comments addressed — valid suggestions applied in d988c56, out-of-scope suggestions (workflow_dispatch, discord/slack hardening) dismissed as not applicable to this PR.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/security/pr-security-reporter/action.yml`:
- Around line 188-217: The Docker Scout reporting is currently gated by
dockerScanEnabled so Scout data (scoutQuickview, scoutCves, scoutHasVulns) and
flags (hasFindings, hasScanErrors) are never processed when only
dockerScoutEnabled is true; change the conditional to run the Scout analysis
block when dockerScoutEnabled is true (ignore dockerScanEnabled for rendering
Scout output), ensure scoutHasVulns sets hasFindings regardless of
dockerScanEnabled, set hasScanErrors only when Scout output is missing
(scoutQuickview && scoutCves both empty) and dockerScoutEnabled is true, and
only render scoutRecommendations when scoutRecommendations is present (or when
the Scout analysis block was emitted) so recommendations don't appear without
the analysis; update references to dockerScoutEnabled, dockerScanEnabled,
scoutQuickview, scoutCves, scoutHasVulns, scoutRecommendations, hasFindings,
hasScanErrors and body accordingly.
In `@src/security/pr-security-reporter/README.md`:
- Around line 1-8: Add a real top-level Markdown H1 at the start of README.md to
satisfy MD041 by inserting "# pr-security-reporter" as the first line (or
replace the embedded <h1> tag in the HTML table with the same Markdown heading);
ensure the Markdown H1 appears before any HTML so the linter recognizes it as
the file's primary heading.
- Around line 12-20: The README inputs table is missing the
scout-recommendations input declared in action.yml; update the table to add a
row for `scout-recommendations` (match the exact name, default value `""`, and
required flag as in action.yml) so the README's inputs contract exactly mirrors
action.yml and callers can wire the recommendations section; ensure the column
values (Description, Required, Default) match the semantics from
`src/security/pr-security-reporter/action.yml`.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2bcb0d7c-bf30-4183-9fd9-caef4408d5fe
📒 Files selected for processing (2)
src/security/pr-security-reporter/README.mdsrc/security/pr-security-reporter/action.yml
GitHub Actions Shared Workflows
Description
Add a new
src/security/docker-scoutcomposite action that runs Docker Scout analysis (quickview, CVEs, recommendations) on locally built Docker images. Integrate it into thepr-security-scanreusable workflow as an opt-in feature via the newenable_docker_scoutinput (defaultfalse).Additionally:
uses: ./src/...refs in self-workflows (branch-cleanup,labels-sync) to use external refs for correct resolution by external callers.claude/commands/,.cursor/rules/)Type of Change
feat: New workflow or new input/output/step in an existing workflowfix: Bug fix in a workflow (incorrect behavior, broken step, wrong condition)refactor: Internal restructuring with no behavior changeBreaking Changes
None. The
enable_docker_scoutinput defaults tofalse, so existing callers are unaffected.Testing
@developor the beta tagCaller repo / workflow run: pending — will test via
workflow_dispatchafter merge todevelopRelated Issues
Closes #
Summary by CodeRabbit
Release Notes
New Features
Documentation