Skip to content

chore(ci): revisit the braces audit exception before it expires on 2026-11-14 (GHSA-vfj7-8cjw-p6xm) #17890

Description

@mrveiss

The exception expires 2026-11-14 and someone has to look again before then

pipeline-scripts/npm_audit_gate.py now carries one recorded exception, added in PR #17889 under an owner decision on 2026-10-03. This issue exists so the expiry has a home that is open, rather than a date inside a closed issue's comment thread.

The advisory, from the GitHub advisory API rather than from the audit summary:

GHSA-vfj7-8cjw-p6xm   braces — stack-exhaustion DoS through deeply nested patterns
vulnerable_version_range   <= 3.0.3
first_patched_version      null
published                  2026-09-18
severity                   high

Every lockfile here already carries braces 3.0.3 — .mcp, autobot-frontend, autobot-slm-frontend, libs/autobot-sdk-ts, and the structured-thinking MCP tool — so there is no version to bump to. The six packages npm audit reports are one root cause: micromatch, fast-glob, globby, stylelint and @vue/eslint-config-typescript are transitive dependents, and the chain is dev: true throughout, so nothing in a shipped bundle imports it.

What to check when this comes up, in the order that settles it fastest:

  • Has braces published a fix? If yes the exception is already inert — the gate withdraws it the moment npm reports fixAvailable, and the right action is the bump, then deleting the entry.
  • If still unpatched, is the chain still reachable only through devDependencies? The justification rests on that, and a dependency change could move it.
  • Can the chain be dropped rather than excused? stylelint and @vue/eslint-config-typescript are the two roots; if either is replaceable the advisory stops applying to this repo at all, which is better than renewing.
  • If renewing, renew deliberately with a new expiry and a note saying what was re-checked — not by moving the date.

The gate fails loudly either way, which is the backstop rather than the plan: an expired entry fails naming its date, and an entry whose advisory is no longer reported fails as dead policy. So the worst case is a blocked PR with an accurate message, not a silent yield.

Refs #13400 (where the gate's "if an advisory has no published fix, change it deliberately and record why" instruction lives) · PR #17889

Activity

  1. mrveiss commented on Oct 3, 2026

    @mrveiss
    OwnerAuthor

    This became urgent before the expiry date: the exception is not holding, and the frontend queue is red

    #17887 is RED on Security Scan right now, and every frontend-touching PR will be. The exception recorded today is being withdrawn by the gate, so this needs a ruling well before 2026-11-14.

    The exception's stated reasoning does not support its conclusion

    It reads: "first_patched_version null — every lockfile here is already at 3.0.3, so no bump exists."

    Both clauses are true and the conclusion does not follow. No bump of braces exists. A fix path via the parent does, and that is the question the gate actually asks:

    braces: fixAvailable = {"name": "stylelint", "version": "7.7.0", "isSemVerMajor": true}
            isDirect=false, effects=["micromatch"], nodes=["node_modules/braces"]
    

    gh api /advisories/GHSA-vfj7-8cjw-p6xm confirms first_patched_version: null and vulnerable_version_range: <= 3.0.3; autobot-frontend/package-lock.json pins 3.0.3. Both sources are accurate and answer different questions — the advisory DB answers "is there a patched braces?", npm answers "is there a fix path?", and for a transitive package npm's answer is a parent bump. The record is correct about braces and wrong about the question the gate asks.

    What the only offered fix actually is

    All six high advisories are one dependency chain:

    bump clears
    stylelint@7.7.0 (isSemVerMajor) 5 — braces, fast-glob, globby, micromatch, stylelint
    @vue/eslint-config-typescript@14.0.1 (isSemVerMajor) 1
    fast-uri moderate — below the failing threshold

    stylelint is a devDependency at ^17.15.0 and npm proposes 7.7.0 — a downgrade across ten major versions. npm does this when the only non-vulnerable version is older. This is not an upgrade that was overlooked; it is the same trade already weighed when the exception was recorded, now surfacing as the gate's only offered remedy.

    Do not run npm audit fix --force here. It would roll stylelint back ten majors to clear a devDependency-only DoS that nothing in a shipped bundle imports.

    Options

    1. Re-state the exception and keep stylelint where it is. "No bump of braces exists, and the only fix npm offers is a major downgrade of a devDependency, which the owner declines." Requires the gate to distinguish a patched version of the package from a parent-bump fix path, and to let the exception cover the latter.
    2. Take the downgrade. Clears five highs immediately; costs ten major versions of a linter and whatever its config migration entails.
    3. Scope the gate by dependency type — devDependencies that never enter a shipped bundle judged separately from runtime dependencies. The largest change, and the only one that stops this recurring for the next dev-only advisory.

    Recommendation: 1, with 3 filed as the durable follow-up. The owner has already ruled on this trade once; the gate not honouring that ruling is the defect, not the ruling. 2 pays a real maintenance cost to silence a dev-only finding.

    Separately — a latent gate defect found while diagnosing this, which is NOT what is firing

    _entry_problem(advisory, exception, ids, fixable, today) takes a single global fixable meaning "any failing package anywhere in the report has a fix", with no link to the advisory being judged. So an unrelated fixable advisory would withdraw a valid exception, and #17889's "and only to that" is untrue of its implementation.

    It is not the cause of today's red — braces' own entry is fixable, so a per-advisory flag returns the same verdict. Recording it here so the two are not conflated: fixing it is correct and will not turn Security Scan green. A fix is in progress and has been reclassified from base-unblock to correctness fix for exactly that reason.

  2. added
    needs-decisionBlocked on an owner decision; options and a recommendation are on the issue
    on Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-decisionBlocked on an owner decision; options and a recommendation are on the issuetesting

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions