fix(deps): patch brace-expansion and PostCSS advisories - #61
Conversation
|
🚅 Deployed to the protocol-visualizer-pr-61 environment in protocol-visualizer
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe pull request restricts workflow permissions and checkout credentials. It separates dependency audit execution from pull request reporting through an artifact. It updates dependency overrides, Docker runtime packages, and configuration tests. ChangesAudit workflow hardening
Estimated code review effort: 3 (Moderate) | ~30 minutes Possibly related PRs
Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant DependencyAudit
participant AuditArtifact
participant AuditComment
participant PullRequest
DependencyAudit->>DependencyAudit: Run pnpm audit
DependencyAudit->>AuditArtifact: Upload JSON result
AuditComment->>AuditArtifact: Download JSON result
AuditComment->>AuditComment: Validate and filter advisories
AuditComment->>PullRequest: Update or create audit comment
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/audit.yml:
- Around line 13-15: Update the audit workflow permissions to read-only by
removing pull-requests: write from the job that checks out and executes pull
request code, including .github/actions/bootstrap. Move comment creation into a
separate trusted job that does not execute the pull request revision, granting
that job the required pull request write permission.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8b383970-acfc-4969-878d-a9c3e3f750a1
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
.github/workflows/audit.yml.github/workflows/ci.yml.github/workflows/security-scan.ymlpnpm-workspace.yaml
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/config.test.mjs (1)
105-108: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winTest persisted checkout credentials.
The test does not assert
persist-credentials: false. A later change can restore persisted checkout credentials while this security-isolation test still passes.Proposed test update
assert(!auditWorkflow.includes("pull-requests: write")); assert(!auditWorkflow.includes("github_token:")); + assert(auditWorkflow.includes("persist-credentials: false")); assert(auditWorkflow.includes("pnpm audit --audit-level moderate --json"));🤖 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 `@tests/config.test.mjs` around lines 105 - 108, Update the auditWorkflow assertions in the configuration test to explicitly verify that the checkout configuration contains persist-credentials: false, while preserving the existing assertions covering permissions, tokens, audit execution, and artifact upload.
🤖 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/audit-comment.yml:
- Around line 21-27: Update the “Download audit result” workflow step to inspect
the artifact archive without extracting untrusted contents first, enforcing
limits on entry names and total uncompressed size, including the 1 MiB bound.
Extract only after validation, then validate audit.json against the expected
advisory schema and safely reject null or malformed advisory entries before
creating a comment.
---
Nitpick comments:
In `@tests/config.test.mjs`:
- Around line 105-108: Update the auditWorkflow assertions in the configuration
test to explicitly verify that the checkout configuration contains
persist-credentials: false, while preserving the existing assertions covering
permissions, tokens, audit execution, and artifact upload.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 40f7f3c1-d152-4107-bf09-a4dfeff907ca
📒 Files selected for processing (3)
.github/workflows/audit-comment.yml.github/workflows/audit.ymltests/config.test.mjs
| - name: Download audit result | ||
| uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 | ||
| with: | ||
| name: pnpm-audit-result | ||
| path: ${{ runner.temp }}/pnpm-audit-result | ||
| run-id: ${{ github.event.workflow_run.id }} | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 5 \
'actions/download-artifact|fs\.statSync|Object\.values\(result\.advisories|actions/upload-artifact|\.github/actions/bootstrap' \
.github/workflows/audit.yml .github/workflows/audit-comment.yml
: "${RUN_ID:?Set RUN_ID to a completed Dependency Audit run ID}"
gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${RUN_ID}/artifacts" \
--jq '.artifacts[] | select(.name == "pnpm-audit-result") | {id, size_in_bytes, expired}'Repository: OlympusDAO/protocol-visualizer
Length of output: 4237
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- audit.yml ---'
cat -n .github/workflows/audit.yml
printf '%s\n' '--- audit-comment.yml ---'
cat -n .github/workflows/audit-comment.yml
printf '%s\n' '--- bootstrap action files ---'
git ls-files '.github/actions/bootstrap*' '.github/actions/bootstrap/**' | while IFS= read -r f; do
printf '\n--- %s ---\n' "$f"
cat -n "$f"
done
printf '%s\n' '--- related workflow triggers and artifact references ---'
rg -n -C 4 'workflow_run|pull_request|pnpm-audit-result|audit\.json|pnpm audit|check:runtime-versions' .github package.jsonRepository: OlympusDAO/protocol-visualizer
Length of output: 19715
🌐 Web query:
GitHub Actions workflow_run untrusted code artifacts security warning download-artifact pull_request workflow
💡 Result:
Using the workflow_run trigger in GitHub Actions presents significant security risks, primarily due to the potential for privilege escalation and artifact poisoning [1][2][3]. Because workflows triggered by workflow_run operate with the base repository's privileged context—including access to repository secrets and write-scoped GITHUB_TOKEN—they must never implicitly trust artifacts or code originating from an untrusted source, such as a pull request from a fork [1][4][5]. Security Risks 1. Privilege Escalation: A common, vulnerable pattern involves using a pull_request trigger for untrusted, low-privilege tasks, followed by a workflow_run trigger for privileged tasks [6][7]. If the second workflow assumes the triggering build's output is safe, an attacker can compromise the privileged environment by injecting malicious code or configurations into the preceding, unprivileged workflow [1][3][5]. 2. Artifact Poisoning: When a workflow_run workflow downloads artifacts created by an untrusted upstream run, those artifacts can be poisoned [2][4][8]. If the privileged workflow executes, extracts, or uses these files without strict validation, it can lead to arbitrary code execution, secret exfiltration, or unauthorized repository modifications [1][3][8][5]. Best Practices for Secure Implementation - Treat All Artifacts as Untrusted: Never assume artifacts are safe [2][4][8]. Always validate their contents and shape before use [4][5][9]. - Isolate Extraction: When using actions/download-artifact, extract files to a temporary directory (e.g., ${{ runner.temp }}/artifacts/) to prevent them from overwriting critical workspace files [2][8][9]. - Avoid Executing Artifacts: Do not execute binaries, scripts, or configurations directly from downloaded artifacts [4][8][5]. - Verify Origin: If possible, verify the origin of the workflow run within your job. For example, you can check if the triggering workflow originated from a fork and exit the job if it did [7]. - Minimize Permissions: Explicitly limit the permissions of the workflow_run job to only what is strictly necessary, rather than relying on default elevated scopes [1][7]. - Keep Dependencies Updated: Ensure you are using the latest versions of actions/download-artifact (version 4.1.3 or higher is required to mitigate specific path traversal vulnerabilities) [10][11]. In summary, the most secure approach is to decouple privileged operations from untrusted code entirely. If a workflow must consume output from a workflow that might have processed fork code, implement strict isolation and validation of all inputs [6][4][7].
Citations:
- 1: https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/GitHub_Actions_Security_Cheat_Sheet.md
- 2: https://github.blog/security/application-security/how-to-secure-your-github-actions-workflows-with-codeql/
- 3: https://sisaku-security.github.io/lint/docs/ghsl/ghsl-2025-084/
- 4: https://actsense.dev/vulnerabilities/artifact_poisoning/
- 5: https://pipefort.mintlify.app/rules/cicd-sec-1-workflow-run-artifact-poisoning
- 6: https://codeql.github.com/codeql-query-help/actions/actions-untrusted-checkout-high/
- 7: https://www.wardenscan.tech/docs/rules/triggers.html
- 8: https://codeql.github.com/codeql-query-help/actions/actions-artifact-poisoning-critical/
- 9: https://github.com/github/codeql/blob/main/actions/ql/src/Security/CWE-829/ArtifactPoisoningMedium.md
- 10: https://github.com/actions/download-artifact
- 11: GHSA-cxww-7g56-2vh6
🌐 Web query:
actions/download-artifact v5 extraction archive size limit artifact download behavior
💡 Result:
The actions/download-artifact@v5 action does not explicitly document a specific "archive size limit" for extraction, though it operates under the general limitations of the GitHub Actions artifact service [1][2]. Users have reported failures during artifact downloads, particularly when dealing with a high number of files or complex directory structures, which can trigger errors such as "Artifact download failed after 5 retries" [1]. Regarding download behavior in v5: 1. Path Consistency: The primary change in v5 is a breaking fix that standardizes path behavior for single artifact downloads [3][4]. Previously, downloading a single artifact by name extracted directly to the specified path/, while downloading by ID created a nested directory (path/artifact-name/) [3][5]. In v5, both methods now extract directly to the specified path/ [3][6]. 2. Migration: If your workflow relied on the previous nested structure when downloading by ID, you must now explicitly include the artifact name in your path input (e.g., path: dist/my-artifact) to maintain that structure [3][4]. 3. General Behavior: When merge-multiple is set to false (the default), multiple artifacts are extracted into individual named directories within the specified path [6][7]. If merge-multiple is true, they are extracted directly into the same directory [6][7]. If you encounter persistent download errors, it is often recommended to verify your environment, as some users have resolved these issues by managing dependencies (e.g., removing node_modules before upload) or updating related actions [1]. Additionally, note that file permissions are not natively preserved during upload/download (files default to 644, directories to 755) unless you use a workaround like tar [8][2].
Citations:
- 1: [bug] Error: Unable to download artifact(s): Unable to download and extract artifact: Artifact download failed after 5 retries. actions/download-artifact#433
- 2: https://github.com/actions/download-artifact/blob/3f40cd641f8c4a2b41aaba3d9fc97a3cbae1992d/README.md
- 3: https://github.com/actions/download-artifact/releases/tag/v5.0.0
- 4: https://newreleases.io/project/github/actions/download-artifact/release/v5.0.0
- 5: Update README for download-artifact v5 changes actions/download-artifact#417
- 6: https://github.com/actions/download-artifact/blob/974686ed5098c7f9c9289ec946b9058e496a2561/README.md
- 7: https://github.com/actions/download-artifact
- 8: https://github.com/marketplace/actions/download-a-build-artifact
🏁 Script executed:
#!/bin/bash
set -euo pipefail
node - <<'JS'
const cases = [
{ name: "null advisory", result: { advisories: { x: null } } },
{ name: "primitive advisory", result: { advisories: { x: "bad" } } },
{ name: "missing advisories", result: {} },
{ name: "valid advisory", result: { advisories: { x: { severity: "high" } } } },
];
for (const { name, result } of cases) {
try {
const advisories = Object.values(result.advisories ?? {});
const reportable = advisories
.filter((advisory) =>
["moderate", "high", "critical"].includes(advisory.severity)
)
.slice(0, 50);
console.log(name, "=>", reportable.length);
} catch (error) {
console.log(name, "=>", error.name + ": " + error.message);
}
}
JS
printf '%s\n' '--- tracked runtime declarations ---'
git ls-files | while IFS= read -r f; do
case "$f" in
package.json|.nvmrc|.node-version|.github/workflows/*|Dockerfile*)
printf '\n--- %s ---\n' "$f"
rg -n 'engines|node-version|node-version-file|FROM node|NODE_VERSION|\.nvmrc|\.node-version' "$f" || true
;;
esac
doneRepository: OlympusDAO/protocol-visualizer
Length of output: 1619
Validate the audit artifact before extraction.
The PR workflow can upload untrusted audit.json content. actions/download-artifact extracts it before the 1 MiB check, so a large or highly compressed artifact can consume runner storage. The accepted JSON {"advisories":{"x":null}} also causes advisory.severity to throw. Download and inspect the archive with bounds on entry names and uncompressed size, then validate the JSON schema before creating a 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/audit-comment.yml around lines 21 - 27, Update the
“Download audit result” workflow step to inspect the artifact archive without
extracting untrusted contents first, enforcing limits on entry names and total
uncompressed size, including the 1 MiB bound. Extract only after validation,
then validate audit.json against the expected advisory schema and safely reject
null or malformed advisory entries before creating a comment.
Summary
Patch the three high-severity pnpm advisories by resolving
brace-expansionto 5.0.8 and PostCSS to 8.5.18. GitHub Actions checkouts no longer persist credentials, and workflow permissions are limited to the access each job requires.Validation
pnpm audit --audit-level moderate: zero moderate, high, or critical findings; one existing lowbody-parseradvisory remainsmasterAdditional Hasura/Trivy verification was blocked by a Docker BuildKit metadata input/output error; no vulnerability ignore was added.
Summary by CodeRabbit
brace-expansionandpostcss.