Skip to content

UID2-7653, UID2-7654, UID2-7658, UID2-7659: suppress 4 CVEs in .trivyignore - #1055

Merged
swibi-ttd merged 1 commit into
mainfrom
swi-suppress-20260811-110031
Aug 11, 2026
Merged

UID2-7653, UID2-7654, UID2-7658, UID2-7659: suppress 4 CVEs in .trivyignore#1055
swibi-ttd merged 1 commit into
mainfrom
swi-suppress-20260811-110031

Conversation

@swibi-ttd

Copy link
Copy Markdown
Contributor

Suppresses 4 vulnerabilities in .trivyignore, expiry 2026-11-11 (3 months). No code fixes — each is present in the image but not reachable from this service.

Reachability alone determines suppress-vs-fix: a fixed version existing upstream does not make an unreachable path exploitable. Change any expiry in review if you want a different window.

If another suppression PR is open on this repo, this one supersedes it. Each scan run raises a fresh branch carrying every outstanding suppression, so the newest PR is a superset of the older ones — merge this and close the rest rather than merging both, which would conflict on the same append.

CVE-2025-71329 — HIGH, image-size (npm, transitive via @docusaurus/mdx-loader)

The DoS requires a remote attacker to supply a crafted JXL/HEIF image buffer with a zero-valued box size to hang a running Node.js event loop. Both flagged repos are Docusaurus static-site generators: image-size is only a build-time transitive dependency of @docusaurus/mdx-loader, invoked during npm run build on trusted, repo-committed image assets. The build product is a static HTML/JS site served by GitHub Pages, with no Node.js process handling untrusted image input at runtime. No JXL/HEIF/HEIC images exist in either tree and no source calls image-size directly, so there is no path for attacker-controlled buffers to reach the vulnerable parsers. The vulnerable code path is unreachable.

Full triage report — CVE-2025-71329

CVE-2025-71329 — image-size DoS via zero-valued box size (JXL/HEIF)

What the CVE is

image-size through 2.0.2 contains a denial-of-service flaw (GHSA-5p2g-fcmc-qvqq, CVSS 3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H). A crafted image buffer with a zero-valued size field in a recognized JXL or HEIF box type causes the parser's offset to never advance, producing an infinite loop that permanently blocks the Node.js event loop. Exploitation requires a running Node.js process that parses an attacker-supplied image buffer.

Where it was found

Flagged in two repos:

  • uid2docspackage-lock.json pins image-size@2.0.2.
  • uid2-docs-previewpreview/package-lock.json pins image-size@2.0.2.

In both, image-size is not a declared dependency in package.json. It is pulled in transitively as a dependency of @docusaurus/mdx-loader@3.9.2 ("image-size": "^2.0.2"), which uses it at build time to determine the intrinsic dimensions of images embedded in markdown/MDX pages.

Why it is not reachable

Both repos are Docusaurus static-site generators:

  1. Build-time only. The GitHub Actions deploy workflows run npm ci then npm run build (docusaurus build). image-size executes during this static build to size images, and its output is baked into static HTML/CSS/JS.
  2. No production Node.js runtime. The build artifact (./build) is uploaded and served by GitHub Pages as static files (actions/upload-pages-artifactactions/deploy-pages). There is no long-lived Node.js event loop in production for the infinite loop to hang.
  3. Trusted inputs only. The only images image-size ever parses are assets committed to the repository by maintainers, not remote/untrusted buffers. The CVE's threat model — a remote attacker supplying a crafted image — does not apply.
  4. No triggering format present. A filesystem search found no .jxl, .heif, or .heic files in either repo, and no source code invokes image-size directly. The specific vulnerable JXL/HEIF parsers are never exercised.

Worst case, a malicious image would only be reachable by a maintainer committing one, which would hang a disposable CI build runner — not a production service, and not remotely exploitable.

Decision

not_affected for both repos. The package is present (consistent with the scan) but the vulnerable code path is unreachable: it runs only at build time over trusted inputs, targets image formats that are absent, and there is no production Node.js event loop exposed to attacker-controlled buffers.

Recommended action

Suppress this finding for both uid2docs and uid2-docs-preview (single repo-root .trivyignore in each). No upgrade is required for security, though a routine dependency refresh once an @docusaurus/mdx-loader release pulls a fixed image-size would clear the scanner noise. Re-evaluate only if either repo ever adds a server-side runtime that parses untrusted uploaded images.

CVE-2025-71330 — HIGH, image-size (npm, transitive via @docusaurus/mdx-loader)

The CVE is a remote DoS: an attacker supplies a crafted ICNS buffer to a live Node.js service and hangs the event loop via an infinite loop in the ICNS parser. Both flagged repos are Docusaurus static-site generators; image-size is pulled in only transitively by @docusaurus/mdx-loader and invoked at build time to compute dimensions of local images referenced in docs. Neither repo runs a persistent Node service — CI runs npm run build to emit static HTML to ./build, which is deployed to GitHub Pages, so there is no runtime event loop exposed to remote attackers. The parser only ever processes trusted, repo-committed images during the trusted CI build (and no .icns files are committed), which does not match the advisory's remote attacker-supplied-buffer vector. The vulnerable code is present but its exploitable path is unreachable.

Full triage report — CVE-2025-71330

CVE-2025-71330 — image-size ICNS infinite-loop DoS

What the CVE is

image-size through 2.0.2 contains a denial-of-service flaw (CWE-835, CVSS 3.1 HIGH, AV:N/AC:L/PR:N/UI:N/A:H). A crafted ICNS image with valid magic bytes and a zero-valued entry-length field drives the ICNS parser into an infinite loop — the buffer offset is never incremented when the entry length is 0, so the while loop condition stays true forever. A remote attacker who can get such a buffer parsed by a running Node.js service permanently blocks its event loop.

No fixed version is published in OSV/GHSA (only last_affected: 2.0.2), so fixed_version is unknown.

Where it appears in our repos

Flagged in uid2docs and uid2-docs-preview. In both, image-size@2.0.2 is present in the lockfile as a transitive dependency of @docusaurus/mdx-loader — it is not a declared dependency in either package.json. Docusaurus' MDX loader uses image-size at build time to determine width/height of images referenced from markdown/MDX docs.

Why it is not reachable

  • Both projects are static-site generators, not services. package.json build script is docusaurus build, and the deploy workflows (.github/workflows/deploy.yml in each) run npm ci + npm run build, then upload the generated ./build directory to GitHub Pages via actions/deploy-pages. There is no long-running Node.js process serving requests in production — the served artifact is static HTML/CSS/JS.
  • No runtime event loop to block. The advisory's impact — permanently blocking a Node.js event loop via an attacker-supplied buffer — requires a live Node service that parses untrusted image input. Our production surface is static files on GitHub Pages, so that vector has no target.
  • Build-time exposure is on trusted input only. image-size runs during the CI build against images committed to the repository (authored by docs maintainers), not against remote/untrusted input. No .icns files are committed to either repo, and there is no direct image-size import in src/. A malicious ICNS would have to be committed by someone with write access — a trusted actor — and would at most hang a CI build, which is not the remote-DoS scenario the CVE describes.

Decision

not_affected for both repos. The vulnerable package is genuinely present (confirming the scan), but the vulnerable code path is only exercised at build time over trusted content, and there is no runtime Node.js service exposed to remote attackers. Reachability of the advisory's attack vector is broken.

Recommended action: suppress in the repo-root .trivyignore of each affected repo. Upgrading if/when a fixed image-size release becomes available is good hygiene but is not required to close the risk, since the path is unreachable.

CVE-2026-67213 — HIGH, nanoid (transitive via postcss)

The DoS lives specifically in nanoid's customAlphabet/customRandom when called with size:0. In all flagged repos nanoid 3.3.16 exists only as a single transitive dependency of postcss (build-time CSS tooling for Docusaurus docs sites and CRA example apps). No repo source imports nanoid or calls customAlphabet/customRandom, and postcss itself only uses the plain default nanoid() for internal node IDs — never the vulnerable functions and never with a caller-controlled size. There is no code path, let alone an attacker-controlled size:0 input, that reaches the vulnerable loop, so the vulnerable code is unreachable despite the package being present.

Full triage report — CVE-2026-67213

CVE-2026-67213 — nanoid infinite loop (customAlphabet/customRandom, size=0)

The vulnerability

nanoid before 3.3.17 / 5.1.6 contains an infinite loop in the customAlphabet and customRandom functions. When either is configured with size: 0, the internal generation loop never satisfies its exit condition and spins forever, hanging the calling thread. Exploitation requires an application to pass an unvalidated, attacker-controlled size: 0 into one of those two specific functions.

  • Advisory: GHSA-2v37-7h3g-55p8, CVSS 3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H (HIGH, Availability-only).
  • Installed: 3.3.16; fixed in 3.3.17 (3.x line) and 5.1.6.

How it appears in our repos

The scanner flagged four package-lock.json files across three repos. In every one, nanoid is:

  • Version 3.3.16, appearing as a single node_modules/nanoid entry.
  • Pulled in only transitively via postcss (postcss declares nanoid: "^3.3.12"). No repo declares nanoid as a direct dependency.
Repo Scanned lockfile(s) nanoid source
uid2-examples web-integrations/javascript-sdk/react-client-side & .../google-secure-signals/react-client-side postcss (via react-scripts/CRA)
uid2docs package-lock.json postcss (via Docusaurus)
uid2-docs-preview preview/package-lock.json postcss (via Docusaurus)

Reachability assessment

  1. No first-party usage. A search of all .js/.ts/.jsx/.tsx/.mjs/.cjs files across the repos found zero references to nanoid, customAlphabet, or customRandom. Our code never calls the vulnerable functions.
  2. The only consumer, postcss, does not use the vulnerable path. postcss uses nanoid solely to generate its own internal node/source-map identifiers via the plain default nanoid() export — it does not call customAlphabet or customRandom, and does not take a caller-supplied size. The specific vulnerable functions are therefore never invoked.
  3. No attacker-controlled size input. Even setting aside (2), there is no path by which external input reaches a nanoid size argument (which would need to be 0).
  4. Build-time only, not a request path. postcss runs during the static build of the Docusaurus documentation sites (uid2docs, uid2-docs-preview) and during the CRA build/start of the example React apps (uid2-examples). These are documentation and sample projects; the example server.js serves pre-built static assets and does not execute postcss at request time.

Because the vulnerable code path (customAlphabet/customRandom with size: 0) is not exercised by our code or by postcss, the CVE is unreachable in all flagged artifacts.

Decision

not_affected. The package is present (consistent with the scan) but the vulnerable path is not reachable. Per the decision logic, an available fix does not change a not_affected verdict.

Recommended remedy

Suppress this finding for the flagged repos via the repo-root .trivyignore in each. Optionally, the transitive nanoid can be bumped to ≥ 3.3.17 through the existing postcss override / dependency refresh during routine maintenance, but this is not security-required given unreachability.

GHSA-5p4m-2wfm-xmqj — HIGH, js-yaml (3.15.0 and 4.3.0, transitive npm dependency)

The advisory describes a quadratic-CPU DoS triggered by yaml.load() on untrusted YAML containing a large !!omap. In all four flagged repos js-yaml is only a dev/build-time transitive dependency (eslint, react-scripts, jest coverage, and Docusaurus's gray-matter). No production/runtime code parses attacker-controlled YAML: the portal and examples never invoke a YAML parser at runtime, and the docs sites only parse their own trusted markdown frontmatter during static-site builds. The vulnerable code path is therefore not reachable with untrusted input, so despite the affected versions being present the DoS vector does not apply.

Full triage report — GHSA-5p4m-2wfm-xmqj

GHSA-5p4m-2wfm-xmqj / CVE-2026-59870 — js-yaml quadratic !!omap DoS

What the CVE is

resolveYamlOmap() in js-yaml enforces key uniqueness for !!omap sequences with a linear objectKeys.indexOf(...) scan inside the per-element loop, making omap resolution O(n²) in the number of entries. A modestly sized YAML document with a large ordered map therefore burns disproportionate CPU inside yaml.load(), giving a denial of service against any consumer that parses untrusted YAML. !!omap is in the default schema, so plain yaml.load(untrustedInput) is enough — no custom schema needed. The 5.x fix (a Set) was never backported to 3.x/4.x; both 3.15.0 and 4.3.0 remain affected. CVSS 3.1 AV:N/AC:L/PR:N/UI:N/A:H.

Presence

Confirmed present in all four flagged repos, matching the affected versions:

  • js-yaml 3.15.0 and 4.3.0 appear throughout the npm lock files. Both repos' overrides even pin these exact (affected) versions.

Reachability analysis (per repo)

The vulnerability requires a runtime code path that feeds untrusted YAML into yaml.load(). That path does not exist in any of the flagged artifacts:

  • uid2-self-serve-portal — js-yaml 3.15.0 (hoisted) and 4.3.0 (under eslint/@eslint/eslintrc) are all "dev": true, pulled transitively by ESLint and @istanbuljs/load-nyc-config (Jest coverage). A search of src/ and server/ finds no js-yaml import and no yaml.load call. The Express backend does not parse YAML.
  • uid2-examples — 3.15.0/4.3.0 are dev/tooling transitives of eslint, react-scripts, and @istanbuljs/load-nyc-config inside static integration-example apps. No production YAML parsing.
  • uid2docs and uid2-docs-preview — Docusaurus static-site generators. js-yaml reaches a production dependency only via gray-matter (markdown frontmatter parsing) and via ESLint. gray-matter runs at build time over the repositories' own, trusted markdown — input an external attacker does not control. There is no long-running service that ingests untrusted YAML.

In short, js-yaml here is a dev-/build-time dependency. The single real parse path (Docusaurus/gray-matter) processes trusted repo-authored content during a build; a hostile payload would at most slow a CI build, not DoS a running service, and cannot be supplied by an external attacker.

Decision

not_affected. The affected code is present but the network-facing DoS vector — yaml.load() on untrusted input — is not reachable in any of the built/run artifacts. A fixed version existing (3.15.1 / 4.3.1) does not change this; the finding is non-exploitable as deployed.

Recommended action: suppress this finding for all four repos (repo-root .trivyignore). If desired for hygiene, the pinned js-yaml@3/js-yaml@4 overrides could be bumped to 3.15.1 / 4.3.1, but this is optional and not security-driving given the dependency is dev/build-time only.


Opened by uid2-vul-scan-agent (general_use_claude-opus-4-8), verdict confidence high. Please sanity-check each reachability argument before approving.

…ignore (exp 2026-11-11)

- CVE-2025-71329 (UID2-7653)
- CVE-2025-71330 (UID2-7654)
- CVE-2026-67213 (UID2-7658)
- GHSA-5p4m-2wfm-xmqj (UID2-7659)

Each is present but not reachable from this service; see the linked tickets for the per-CVE impact assessments. Reachability alone determines suppress-vs-fix.
@swibi-ttd
swibi-ttd merged commit d038993 into main Aug 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants