Menu ▾ ▴

#533 fix(ci): resolve npm audit root advisories and document braces exception

v2.0.0
closed
nobody
5 days ago
6 days ago
Anonymous
No

Originally created by: Redo-San
Originally owned by: Redo-San

Problem

Weekly Security Audit run 37294123943 (2026-10-05) failed with 10 unexcepted high findings — all rooted at braces GHSA-vfj7-8cjw-p6xm (CVE-2026-93687), for which no patched release exists (npm dist-tags.latest is still 3.0.3, upstream [micromatch/braces#70](https://github.com/micromatch/braces/issues/70) open).

Root cause, verified against the run's own audit-report.json artifact: npm audit exposes the advisory URL only on via leaf objects, while the gate read vuln.url at the top level of each vulnerability entry — always undefined — so every finding resolved to n/a and could never match an exception row. The matcher had never been exercised before: the 2026-09-28 run passed only because npm's advisory DB returned no high findings at the time.

Changes

  1. .github/workflows/security-audit.yml — walk via links (string refs and leaf objects) to collect the root advisory ids of each high/critical finding; a finding is excused only when all root ids have rows. Ids that cannot be resolved stay n/a and still fail the job (fail-safe behaviour unchanged).
  2. security/vulnerability-exceptions.md — deferral row for GHSA-vfj7-8cjw-p6xm / CVE-2026-93687:
  3. Scope: development (npm audit --omit=dev --audit-level=high exits 0)
  4. Impact: high — CVSS 7.5 DoS, uncaught stack exhaustion (CWE-674) from deeply nested brace patterns
  5. Mitigation: dev-only chain (stylelint, workbox-cli, depcheck, repomix, globby, findup-sync, fast-glob, micromatch, chokidar); glob patterns are repo-authored config, never attacker input; no patched release exists; Scorecard ignore in osv-scanner.toml
  6. next-review: 2027-01-04 (≤ 90 days, tracking issue [#532] carries the review checklist)
  7. The policy section now documents how chain findings resolve to their root advisory.
  8. osv-scanner.toml already carries the matching Scorecard ignore (unchanged).

Verification

  • Extracted the embedded gate script and ran it against the CI artifact: passes with the row (exit 0); with the row removed it fails listing GHSA-vfj7-8cjw-p6xm for all 10 findings (exit 1) — the gate is not neutered.
  • CI-exact cspell (204 files): 0 issues. markdownlint on the edited file: clean. actionlint on the workflow: clean. npm run check: green (1082 tests).
  • After merge: workflow_dispatch the Security Audit workflow to confirm the scheduled job goes green.

Tracking issue: [#532] (labels triage, security), next review 2027-01-04.

Related

Tickets: #532
Tickets: #534

Discussion

  • Anonymous

    Anonymous - 6 days ago
     
  • Anonymous

    Anonymous - 6 days ago

    Originally posted by: github-actions[bot]

    Looking at this PR, I'll review the changes systematically:

    Summary of Changes:

    1. .github/workflows/security-audit.yml - Updated the vulnerability checking logic to properly handle npm audit's via links. The original code incorrectly assumed the advisory URL was present on the vulnerability entry itself (vuln.url), which was always undefined. The fix introduces a collectRootIds function that recursively traverses via links to collect all root advisory IDs from the dependency chain.

    2. security/vulnerability-exceptions.md - Added a new row documenting the exception for GHSA-vfj7-8cjw-p6xm / CVE-2026-93687, including scope (development), impact (high - CVSS 7.5 DoS), mitigation (dev-only chain of tools), and next-review date (2027-01-04).

    Code Review Analysis:

    ✅ Correctness: The fix addresses the core issue described - npm audit places advisory URLs on via leaf objects, not on the vulnerability entry itself. By walking these links, the gate can now properly resolve root advisory IDs and check if they're covered by exceptions.

    ✅ Logic: The collectRootIds function correctly handles:

    • String nodes (package names) by looking up vulnerabilities in report.vulnerabilities
    • Arrays (multiple targets)
    • Objects with via links and optional url fields containing advisory URLs

    ✅ Edge cases handled:

    • Cycle prevention via seen set
    • Missing via links (returns empty array, causing the finding to be marked unexcepted)
    • Non-advisory URLs in url field (filtered out)

    ✅ Documentation: The vulnerability-exceptions.md update is clear and follows the project's format, adding the required row with proper columns.

    ✅ No regressions: The changes maintain the fail-safe behavior - if a root advisory isn't covered by an exception row, the job still fails (as intended). Only findings whose root advisories are explicitly documented as exceptions are excused.

    The PR appears well-implemented and addresses the root cause of the weekly security audit failures. The verification steps (running the gate script against the CI artifact) confirm the fix works correctly.

     
  • Anonymous

    Anonymous - 6 days ago

    Originally posted by: github-actions[bot]

    Gemini review skipped: API quota exceeded (daily free-tier limit). The review will run automatically again once quota resets.

     
  • Anonymous

    Anonymous - 6 days ago

    Originally posted by: github-actions[bot]

    PR Statistics

    Metric Value
    Files changed 2
    Additions 30
    Deletions 8
    Net change +22
    Commits 1

    Changed files:

    • .github/workflows/security-audit.yml (+23/-3)
    • security/vulnerability-exceptions.md (+7/-5)
     
  • Anonymous

    Anonymous - 6 days ago

    Originally posted by: github-actions[bot]

    🏗️ DOM Review\n\n✅ No issues found across all pages.\n

     
  • Anonymous

    Anonymous - 6 days ago

    Originally posted by: github-actions[bot]

    Depcheck

    No dependency issues found.

     
  • Anonymous

    Anonymous - 6 days ago

    Ticket changed by: Redo-San

    • status: open --> closed
     

Log in to post a comment.