Skip to content

[security] Preserve maximum advisory severity when audit results are merged #1340

Description

@kang-heewon

Problem

When the same advisory is present in multiple audit passes, mergeAdvisories spreads the later record over the earlier one. A later moderate/low record can overwrite an earlier high/critical severity, causing isHighRisk to stop treating the merged advisory as blocking. Advisories without a stable identifier can also collapse under the same "undefined" key.

This is a P1 security-policy bug because merge order can downgrade a real blocker.

Evidence

  • Current trunk: 0590a47.
  • scripts/dependency-audit-policy.mts mergeAuditJsons combines results from multiple audit passes by advisoryKey.
  • mergeAdvisories returns { ...left, ...right, ... }, so right.severity overwrites left.severity without severity ordering.
  • isHighRisk later checks only the merged severity.
  • advisoryKey falls back to String(advisory.id); missing identifiers therefore share the same fallback key.

Desired outcome

Merging audit evidence must be monotonic: adding another audit result can preserve or increase risk, never lower it, and records without a stable identity must not be conflated.

Proposed implementation path

  1. Normalize severities through an explicit ordered enum/rank.
  2. Select the maximum observed severity while merging the remaining evidence sets deterministically.
  3. Require a stable advisory identity (GHSA, CVE, or validated audit id); fail closed or keep records distinct when it is missing.
  4. Make merged output independent of input ordering and retain provenance useful for diagnostics.

Acceptance criteria

  • The same high/low advisory merges to high in both input orders.
  • Critical/high cannot be overwritten by moderate/low/unknown values.
  • Two identifier-less advisories do not collapse into one record.
  • Invalid severity or identity evidence produces a stable diagnostic rather than silent normalization.
  • Existing valid audit fixtures remain deterministic.

Validation

  • Add table-driven tests for every severity ordering in both merge directions.
  • Add fixtures for GHSA, CVE-only, numeric-id, and missing-id records.
  • Run the dependency-audit policy suite and repository security gate.

Scope boundaries

  • Do not change which normalized severities are considered blocking.
  • Do not merge unrelated advisories solely because package names or descriptions match.
  • Keep allowlist review semantics unchanged.

Metadata

Metadata

Assignees

Labels

P1Priority 1 issuebugSomething isn't workingciContinuous integration checks and repository quality gateserror-handlingError handling and failure semanticsquality-gatesecurity

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions