From 206afd733844bb10d065cece9799f31aa67434bb Mon Sep 17 00:00:00 2001 From: Arcuru Bot Date: Wed, 19 Aug 2026 00:41:45 -0700 Subject: [PATCH] fix(security-audit): pass the advisory report through a file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When cargo-deny reports an advisory the issue-reporting step died before it started, with: An error occurred trying to start process '/usr/bin/bash' ... Argument list too long The report was captured into a step output and re-exported as the AUDIT_OUTPUT environment variable of the reporting step. Because the audit step redirected stderr as well, that capture also swallowed the whole Nix dev-shell build log — 242 KB on a cold cache, against roughly 8 KB of actual cargo-deny report. A single environment string over 128 KiB exceeds the per-string execve limit, so the runner could not exec bash at all, and the step that exists to file the advisory failed in exactly the case it exists for. A clean audit never reached it. Two changes: - Build the dev shell in its own step, so the Nix build log is no longer part of what gets captured. - Write the report to a file under RUNNER_TEMP and hand it to `gh issue edit`/`gh issue create` with --body-file, so no copy of it passes through argv or the environment. A GitHub issue body is still capped at 65536 characters, so an unexpectedly large report keeps its tail — where cargo-deny prints the advisories and its verdict — and links the run log for the rest, rather than failing the API call. --- .github/workflows/security-audit.yml | 86 ++++++++++++++++++---------- 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 1278aa4..eaf0f65 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -63,20 +63,28 @@ jobs: extra-substituters: ${{ inputs.extra-substituters }} extra-trusted-public-keys: ${{ inputs.extra-trusted-public-keys }} + # Build the dev shell in its own step so that the Nix build log — hundreds + # of kilobytes of downloads and `building ...` lines on a cold cache — + # stays out of the report captured below. + - name: Warm the dev shell + run: nix develop --command true + - name: Check advisories id: audit run: | set +e - OUTPUT=$(nix develop --command cargo deny check --config .config/deny.toml advisories 2>&1) + nix develop --command cargo deny check --config .config/deny.toml advisories \ + > "$REPORT" 2>&1 EXIT_CODE=$? - echo "$OUTPUT" - { - echo "output<> "$GITHUB_OUTPUT" + cat "$REPORT" echo "exit_code=$EXIT_CODE" >> "$GITHUB_OUTPUT" exit 0 + env: + # The report goes to a file, not a step output: it is passed to the + # reporting step below, where an inlined copy would land in the + # environment block and fail the step with E2BIG once it exceeds the + # 128 KiB per-string execve limit. + REPORT: ${{ runner.temp }}/cargo-deny-advisories.txt - name: Find existing issue id: find_issue @@ -89,38 +97,56 @@ jobs: - name: Create or update issue on failure if: steps.audit.outputs.exit_code != '0' run: | + set -eo pipefail TITLE="Security Advisory Alert" - TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ) - BODY=$(cat <<'ISSUE_EOF' - ## Security Advisory Found - - `cargo deny check advisories` found active advisories in dependencies. - -
- Full output + BODY_FILE="${RUNNER_TEMP}/security-advisory-issue.md" - ``` - __AUDIT_OUTPUT__ - ``` - -
- - **Action required:** Review the advisories above and update affected dependencies or add ignore entries to `.config/deny.toml` if appropriate. + # A GitHub issue body is capped at 65536 characters, so a very large + # report cannot be posted whole. Keep the tail, which is where + # cargo-deny prints the advisories and its verdict, and link the run + # log for the rest. `tail -n +2` drops the partial first line left by + # the byte-wise cut, which could otherwise split a UTF-8 sequence. + MAX_REPORT_BYTES=50000 + TRUNCATED="" + if [ "$(wc -c < "$REPORT")" -gt "$MAX_REPORT_BYTES" ]; then + TRUNCATED=yes + tail -c "$MAX_REPORT_BYTES" "$REPORT" | tail -n +2 > "${REPORT}.tail" + mv "${REPORT}.tail" "$REPORT" + fi - _Last checked: __TIMESTAMP___ - ISSUE_EOF - ) - BODY="${BODY//__TIMESTAMP__/$TIMESTAMP}" - BODY="${BODY//__AUDIT_OUTPUT__/$AUDIT_OUTPUT}" + { + echo "## Security Advisory Found" + echo + echo "\`cargo deny check advisories\` found active advisories in dependencies." + echo + if [ -n "$TRUNCATED" ]; then + echo "> Output truncated to the last ${MAX_REPORT_BYTES} bytes. The full report is in the [workflow run log](${RUN_URL})." + echo + fi + echo "
" + echo "Full output" + echo + echo '```' + cat "$REPORT" + echo + echo '```' + echo + echo "
" + echo + echo "**Action required:** Review the advisories above and update affected dependencies or add ignore entries to \`.config/deny.toml\` if appropriate." + echo + echo "_Last checked: $(date -u +%Y-%m-%dT%H:%M:%SZ)_" + } > "$BODY_FILE" if [ -n "$ISSUE_NUMBER" ]; then - gh issue edit "$ISSUE_NUMBER" --body "$BODY" + gh issue edit "$ISSUE_NUMBER" --body-file "$BODY_FILE" else - gh issue create --title "$TITLE" --body "$BODY" --label security + gh issue create --title "$TITLE" --body-file "$BODY_FILE" --label security fi env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - AUDIT_OUTPUT: ${{ steps.audit.outputs.output }} + REPORT: ${{ runner.temp }}/cargo-deny-advisories.txt + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} ISSUE_NUMBER: ${{ steps.find_issue.outputs.number }} - name: Close issue on success