Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f3c6f30a9 | ||
|
|
2eb5d74f59 | ||
|
|
bef1b99c78 | ||
|
|
5980e2caba | ||
|
|
27a6d98d0c | ||
|
|
59f169e32d | ||
|
|
1a5338e876 | ||
|
|
bbb163c25c | ||
|
|
2c7a3b8465 | ||
|
|
d37538264a | ||
|
|
cd5eeafa08 | ||
|
|
3d2ec5869b | ||
|
|
bc27894b38 |
No files matched your search
@@ -4,6 +4,14 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# One deploy at a time: `surfer deploy` swaps the site atomically, so two runs
|
||||||
|
# racing each other is not corruption, but it is a wasted build and the last
|
||||||
|
# swap wins.
|
||||||
|
concurrency:
|
||||||
|
group: surfer-datacontroller-io
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Build-and-publish:
|
Build-and-publish:
|
||||||
@@ -18,8 +26,44 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci --legacy-peer-deps
|
run: npm ci --legacy-peer-deps
|
||||||
|
|
||||||
|
# Blocking gate. `npm audit --audit-level=<x>` is all-or-nothing and this
|
||||||
|
# tree cannot pass a flat gate at any level: the Gatsby 5 build toolchain
|
||||||
|
# carries ~100 advisories with no non-breaking fix, so gating on the tree
|
||||||
|
# as a whole stops publishing permanently. scripts/audit-gate.mjs instead
|
||||||
|
# accepts the known set (scripts/audit-baseline.json, with an owner and a
|
||||||
|
# reason) and FAILS on any new critical/high advisory.
|
||||||
|
- name: Audit for new critical/high advisories
|
||||||
|
run: node scripts/audit-gate.mjs
|
||||||
|
|
||||||
|
# The prettier and type checks used to live in a GitHub workflow that
|
||||||
|
# never ran on this forge; keep them ahead of the build so a type or
|
||||||
|
# formatting error blocks the deploy rather than shipping.
|
||||||
|
- name: Typecheck
|
||||||
|
run: npm run typecheck
|
||||||
|
|
||||||
|
- name: Check prettier offences
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
|
# Deploy tooling pinned to an exact version: the workflow publishes
|
||||||
|
# whatever is committed, and an unpinned `latest` would let a breaking or
|
||||||
|
# compromised upstream release ship straight to the live site.
|
||||||
|
#
|
||||||
|
# `deploy` (v7) replaces the site atomically - it extracts to a staging
|
||||||
|
# folder and swaps it in, so a failed upload leaves the current site
|
||||||
|
# serving. The v6 `put` this replaces was token authenticated and is
|
||||||
|
# gone; v7 takes the Cloudron username plus an app password for this app.
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: npx surfer put --token ${{ secrets.SURFER_TOKEN }} --server datacontroller.io public/* /
|
env:
|
||||||
|
SURFER_PASSWORD: ${{ secrets.SURFER_PASSWORD }}
|
||||||
|
REF_NAME: ${{ gitea.ref_name }}
|
||||||
|
COMMIT_SHA: ${{ gitea.sha }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
npx --yes @cloudron/surfer@7.2.0 deploy public \
|
||||||
|
--server datacontroller.io \
|
||||||
|
--username allan \
|
||||||
|
--password "$SURFER_PASSWORD" \
|
||||||
|
--message "Build from ${REF_NAME} @ ${COMMIT_SHA:0:8}"
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
name: Gatsby Publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Use Node.js from .nvmrc
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: .nvmrc
|
|
||||||
cache: npm
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci --legacy-peer-deps
|
|
||||||
|
|
||||||
- name: Check prettier offences
|
|
||||||
run: npm run lint
|
|
||||||
|
|
||||||
- uses: enriikke/gatsby-gh-pages-action@v2
|
|
||||||
with:
|
|
||||||
access-token: ${{ secrets.DCSITE }}
|
|
||||||
deploy-branch: gh-pages
|
|
||||||
gatsby-args: --prefix-paths
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Secret scanning for staged content, so a credential is caught before it is
|
||||||
|
# committed rather than after it has been pushed and published.
|
||||||
|
#
|
||||||
|
# gitleaks is pinned to an exact tag: a floating rev would pull whatever the
|
||||||
|
# hook's upstream does next into every contributor's commit path.
|
||||||
|
#
|
||||||
|
# Install once per clone: `pre-commit install`.
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/gitleaks/gitleaks
|
||||||
|
rev: v8.30.1
|
||||||
|
hooks:
|
||||||
|
- id: gitleaks
|
||||||
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 119 KiB |
@@ -133,7 +133,7 @@ An expression can reference a column that is hidden from a user by [Column Level
|
|||||||
|
|
||||||
## Availability
|
## Availability
|
||||||
|
|
||||||
Derived variables ship in the next release, on SAS 9, Viya and SASjs Server. The configuration table, the settings and the post-edit validation are created by the usual upgrade - there is nothing to install beyond the release itself.
|
Derived variables are available on SAS 9, Viya and SASjs Server. The configuration table, the settings and the post-edit validation are created by the usual upgrade - there is nothing to install beyond the release itself.
|
||||||
|
|
||||||
The full reference, including every column of `MPE_DERIVED` and the validation rules applied at submit time, is in the [docs](https://docs.datacontroller.io/derived-variables/).
|
The full reference, including every column of `MPE_DERIVED` and the validation rules applied at submit time, is in the [docs](https://docs.datacontroller.io/derived-variables/).
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 119 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
title: 'The column that is not in the table'
|
||||||
|
description: 'Derived variables give the EDIT screen columns that do not exist in the table - computed on every read, never stored, and filterable like any other column. The full story is in the article.'
|
||||||
|
date: '2026-10-27 09:00:00'
|
||||||
|
author: 'Data Controller'
|
||||||
|
authorLink: https://www.linkedin.com/showcase/data-controller-for-sas
|
||||||
|
tags:
|
||||||
|
- Announcements
|
||||||
|
- Features
|
||||||
|
previewImg: './derived-fx.png'
|
||||||
|
---
|
||||||
|
|
||||||
|
# The column that is not in the table
|
||||||
|
|
||||||
|
Every reporting team has a version of this request, and it always sounds like a five minute job: "can we have a region column? It is just the state, mapped. And a line value - quantity times price. We do not need it stored, we just need it on the screen."
|
||||||
|
|
||||||
|
It is never a five minute job - so Data Controller now does the obvious thing instead. You write the expression, and the EDIT screen shows the column: computed on every read, never stored, marked `fx` and read-only, so nobody has to wonder whether it is locked or simply has nothing to edit.
|
||||||
|
|
||||||
|
The part that took the thinking is that they filter like any other column. That needed a DATA step view rather than a data step, and the reasoning is worth reading: [Derived variables: computed columns you can filter on](/derived-variables/).
|
||||||
|
|
||||||
|
Reference: [Derived Variables](https://docs.datacontroller.io/derived-variables/).
|
||||||
|
|
||||||
|
If a table of yours has been waiting for "just one more column", we would love to [hear from you](/contact).
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Feed teaser for the article at /derived-variables/. The article carries the
|
||||||
|
engineering - why a computed column is not automatically filterable, the DATA
|
||||||
|
step view, the configuration table, the limits - so this post links to it
|
||||||
|
rather than repeating it.
|
||||||
|
|
||||||
|
Image prompt (cover): a clean, modern illustration on a white background: a
|
||||||
|
spreadsheet grid rendered in soft slate and light blue, with the leftmost four
|
||||||
|
columns showing plain data and three further columns floating slightly to the
|
||||||
|
right, detached from the table, tinted light blue and italicised, each marked
|
||||||
|
with a small "fx" badge. A thin left border separates the floating block from
|
||||||
|
the stored columns. No text other than the fx badges. Flat vector style, brand
|
||||||
|
palette: slate #314351, light blue #d3e5f2, accent green #79a843 used sparingly
|
||||||
|
as a single dot.
|
||||||
|
-->
|
||||||
@@ -55,7 +55,6 @@
|
|||||||
"@types/react": "^18.3.31",
|
"@types/react": "^18.3.31",
|
||||||
"@types/react-dom": "^18.3.7",
|
"@types/react-dom": "^18.3.7",
|
||||||
"bootstrap": "^5.0.0-beta3",
|
"bootstrap": "^5.0.0-beta3",
|
||||||
"cloudron-surfer": "^6.4.1",
|
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"typescript": "^7.0.2"
|
"typescript": "^7.0.2"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,940 @@
|
|||||||
|
{
|
||||||
|
"$comment": "Advisories at critical/high accepted for this tree. scripts/audit-gate.mjs fails the build on anything not listed here, so removing an entry re-arms the gate for that advisory. Regenerate with: node scripts/audit-gate.mjs --write-baseline",
|
||||||
|
"owner": "Site maintainers (allan@4gl.io)",
|
||||||
|
"reason": "Gatsby 5 build toolchain: no non-breaking fix available upstream, and these are build-time dependencies of a statically generated site. Re-check on each Gatsby major bump.",
|
||||||
|
"accepted": [
|
||||||
|
{
|
||||||
|
"pkg": "@ardatan/relay-compiler",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@babel/plugin-transform-modules-systemjs",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-fv7c-fp4j-7gwp",
|
||||||
|
"title": "@babel/plugin-transform-modules-systemjs generates arbitrary code when compiling malicious input",
|
||||||
|
"range": ">=7.12.0 <=7.29.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-codegen/add",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-codegen/core",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-codegen/plugin-helpers",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-codegen/schema-ast",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-codegen/typescript-operations",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-codegen/typescript",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-codegen/visitor-plugin-common",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-tools/code-file-loader",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-tools/graphql-tag-pluck",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-tools/load",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-tools/merge",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-tools/relay-operation-optimizer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-tools/schema",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "@graphql-tools/utils",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-7mx3-vvmw-hjmv",
|
||||||
|
"title": "GraphQL Tools has prototype pollution in well-established utility function `mergeDeep`",
|
||||||
|
"range": "<=12.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-35jp-ww65-95wh",
|
||||||
|
"title": "axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy`",
|
||||||
|
"range": ">=1.0.0 <1.16.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3g43-6gmg-66jw",
|
||||||
|
"title": "axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollution Gadget in Config Merge",
|
||||||
|
"range": ">=1.0.0 <1.15.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3p68-rc4w-qgx5",
|
||||||
|
"title": "Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF",
|
||||||
|
"range": ">=1.0.0 <1.15.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3pq3-5fj3-cg6v",
|
||||||
|
"title": "Axios: HTTP/2 adapter bypasses configured DNS lookup and proxy controls",
|
||||||
|
"range": ">=1.13.0 <1.20.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3w6x-2g7m-8v23",
|
||||||
|
"title": "Axios: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`",
|
||||||
|
"range": ">=1.0.0 <1.15.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-42h9-826w-cgv3",
|
||||||
|
"title": "Axios: Excessive recursion in formDataToJSON can cause denial of service",
|
||||||
|
"range": ">=1.0.0 <1.18.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-43fc-jf86-j433",
|
||||||
|
"title": "Axios is Vulnerable to Denial of Service via __proto__ Key in mergeConfig",
|
||||||
|
"range": ">=1.0.0 <=1.13.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-445q-vr5w-6q77",
|
||||||
|
"title": "Axios: CRLF Injection in multipart/form-data body via unsanitized blob.type in formDataToStream",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-4hqw-qxg8-jxx2",
|
||||||
|
"title": "Axios: Fetch Adapter Header Injection via Inherited FormData getHeaders",
|
||||||
|
"range": ">=1.12.0 <1.20.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-542g-h47m-68v8",
|
||||||
|
"title": "Axios: Denial of Service via Unhandled 'error' Event in HTTP/2 ClientHttp2Session Initialization",
|
||||||
|
"range": ">=1.13.0 <1.20.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-5c9x-8gcm-mpgx",
|
||||||
|
"title": "Axios' HTTP adapter-streamed uploads bypass maxBodyLength when maxRedirects: 0",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-62hf-57xw-28j9",
|
||||||
|
"title": "Axios: unbounded recursion in toFormData causes DoS via deeply nested request data",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-6chq-wfr3-2hj9",
|
||||||
|
"title": "Axios: Header Injection via Prototype Pollution",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-777c-7fjr-54vf",
|
||||||
|
"title": "Allocation of Resources Without Limits or Throttling in Axios",
|
||||||
|
"range": ">=1.7.0 <1.16.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-7q8q-rj6j-mhjq",
|
||||||
|
"title": "Axios: Nested axios option objects can consume polluted prototype values",
|
||||||
|
"range": ">=1.0.0 <1.18.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-898c-q2cr-xwhg",
|
||||||
|
"title": "axios has DoS & Header Injection via Prototype Pollution Read-Side Gadgets in axios merge functions",
|
||||||
|
"range": ">=1.0.0 <1.16.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-9fr6-4gfg-395g",
|
||||||
|
"title": "Axios: Prototype-Pollution Gadget in the Default Instance Allows Inherited Object.prototype.method to Override HTTP Method",
|
||||||
|
"range": ">=1.0.0 <1.20.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-fvcv-3m26-pcqx",
|
||||||
|
"title": "Axios has Unrestricted Cloud Metadata Exfiltration via Header Injection Chain",
|
||||||
|
"range": ">=1.0.0 <1.15.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-hfxv-24rg-xrqf",
|
||||||
|
"title": "Axios: Regular Expression Denial of Service (ReDoS) via Cookie Name Injection",
|
||||||
|
"range": ">=1.0.0 <1.16.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-j5f8-grm9-p9fc",
|
||||||
|
"title": "Axios: Proxy-Authorization header leaks to redirect target when proxy is re-evaluated to direct connection",
|
||||||
|
"range": ">=1.0.0 <1.16.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-j8rh-479h-cp32",
|
||||||
|
"title": "Axios: Header Injection via Inherited headers After Minimal Interceptor",
|
||||||
|
"range": ">=1.0.0 <1.20.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-jqh4-m9w3-8hp9",
|
||||||
|
"title": "Axios: Fetch adapter `ReadableStream` uploads bypass `maxBodyLength`",
|
||||||
|
"range": ">=1.7.0 <1.18.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-m7pr-hjqh-92cm",
|
||||||
|
"title": "Axios: no_proxy bypass via IP alias allows SSRF",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-mmx7-hfxf-jppx",
|
||||||
|
"title": "Axios: Prototype pollution gadgets can alter axios request construction",
|
||||||
|
"range": ">=1.0.0 <1.18.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-mwf2-3pr3-8698",
|
||||||
|
"title": "Axios: HTTP/2 streamed uploads bypass `maxBodyLength`",
|
||||||
|
"range": ">=1.13.0 <1.18.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-p92q-9vqr-4j8v",
|
||||||
|
"title": "Axios: Proxy-Authorization Credential Leak to Origin Server Across HTTP-to-HTTPS Redirect in Axios Node.js HTTP Adapter",
|
||||||
|
"range": ">=1.0.0 <1.16.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-pf86-5x62-jrwf",
|
||||||
|
"title": "Axios: Prototype Pollution Gadgets - Response Tampering, Data Exfiltration, and Request Hijacking",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-pmv8-rq9r-6j72",
|
||||||
|
"title": "Axios: Deep formToJSON Key Recursion Can Cause Denial of Service",
|
||||||
|
"range": ">=1.0.0 <1.18.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-pmwg-cvhr-8vh7",
|
||||||
|
"title": "Axios: Incomplete Fix for CVE-2025-62718 — NO_PROXY Protection Bypassed via RFC 1122 Loopback Subnet (127.0.0.0/8) in Axios 1.15.0",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-q8qp-cvcw-x6jj",
|
||||||
|
"title": "Axios has prototype pollution read-side gadgets in HTTP adapter that allow credential injection and request hijacking",
|
||||||
|
"range": ">=1.0.0 <1.15.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-vf2m-468p-8v99",
|
||||||
|
"title": "Axios: HTTP adapter streamed responses bypass maxContentLength",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-vh66-26gq-q6x8",
|
||||||
|
"title": "Axios: Prototype pollution gadget in fetch adapter can alter outbound requests",
|
||||||
|
"range": ">=1.7.0 <1.20.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-w9j2-pvgh-6h63",
|
||||||
|
"title": "Axios: Authentication Bypass via Prototype Pollution Gadget in `validateStatus` Merge Strategy",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-xhjh-pmcv-23jw",
|
||||||
|
"title": "Axios: Null Byte Injection via Reverse-Encoding in AxiosURLSearchParams",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "axios",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-xx6v-rp6x-q39c",
|
||||||
|
"title": "Axios: XSRF Token Cross-Origin Leakage via Prototype Pollution Gadget in `withXSRFToken` Boolean Coercion",
|
||||||
|
"range": ">=1.0.0 <1.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "body-parser",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-27r3-jxmh-p828",
|
||||||
|
"title": "body-parser vulnerable to Denial of Service via trailing bytes after a compressed request body",
|
||||||
|
"range": "<1.20.9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "body-parser",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-qwcr-r2fm-qrc7",
|
||||||
|
"title": "body-parser vulnerable to denial of service when url encoding is enabled",
|
||||||
|
"range": "<1.20.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "body-parser",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-v422-hmwv-36x6",
|
||||||
|
"title": "body-parser vulnerable to denial of service when invalid limit value silently disables size enforcement",
|
||||||
|
"range": "<1.20.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "brace-expansion",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3jxr-9vmj-r5cp",
|
||||||
|
"title": "brace-expansion: DoS via exponential-time expansion of consecutive non-expanding {} groups",
|
||||||
|
"range": "<1.1.16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "brace-expansion",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-6j4f-fj2g-mc7p",
|
||||||
|
"title": "brace-expansion: DoS via uncontrolled recursion in parseCommaParts causing stack exhaustion",
|
||||||
|
"range": "<1.1.19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "brace-expansion",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-f886-m6hf-6m8v",
|
||||||
|
"title": "brace-expansion: Zero-step sequence causes process hang and memory exhaustion",
|
||||||
|
"range": "<1.1.13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "brace-expansion",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-mh99-v99m-4gvg",
|
||||||
|
"title": "brace-expansion: DoS via unbounded expansion length causing an out-of-memory process crash",
|
||||||
|
"range": "<1.1.17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "brace-expansion",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-q2hr-2g5m-vwhr",
|
||||||
|
"title": "brace-expansion: Quadratic-time expansion of the `{a},b}` rewrite causes CPU denial of service",
|
||||||
|
"range": "<1.1.21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "brace-expansion",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-qhr7-859c-m2p7",
|
||||||
|
"title": "brace-expansion: DoS via uncontrolled recursion on nested brace groups causing stack exhaustion",
|
||||||
|
"range": "<1.1.20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "brace-expansion",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-rgw5-rvv9-x895",
|
||||||
|
"title": "brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-14257 mitigation",
|
||||||
|
"range": "<1.1.18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "brace-expansion",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-v6h2-p8h4-qcjw",
|
||||||
|
"title": "brace-expansion Regular Expression Denial of Service vulnerability",
|
||||||
|
"range": ">=1.0.0 <=1.1.11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "browserslist",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-73wf-gq98-2v4g",
|
||||||
|
"title": "Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats.json custom stats (normalizeStats)",
|
||||||
|
"range": "<=4.28.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "browserslist",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-c83g-rgw3-j3cx",
|
||||||
|
"title": "Browserslist: Unbounded memory growth (no cache eviction) via distinct query results, leading to eventual OOM",
|
||||||
|
"range": "<=4.28.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "compression",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-vc2v-76pw-4v95",
|
||||||
|
"title": "compression vulnerable to Denial of Service via memory leak on premature response close",
|
||||||
|
"range": "<1.8.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "cross-spawn",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3xgq-45jj-v275",
|
||||||
|
"title": "Regular Expression Denial of Service (ReDoS) in cross-spawn",
|
||||||
|
"range": ">=7.0.0 <7.0.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "engine.io",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-2gc4-cqfq-p2gv",
|
||||||
|
"title": "Socket.IO: Engine.IO Protocol Revision Mismatch DoS",
|
||||||
|
"range": ">=6.6.0 <6.6.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "engine.io",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-gr94-w7qr-f4j3",
|
||||||
|
"title": "Socket.IO: Engine.IO WebTransport SID DoS",
|
||||||
|
"range": ">=6.5.0 <6.6.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "engine.io",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-r635-g3xr-vw7x",
|
||||||
|
"title": "Socket.IO: Engine.IO Polling Transport Connection Exhaustion",
|
||||||
|
"range": ">=4.1.0 <6.6.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "express",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-qw6h-vgh9-j6wx",
|
||||||
|
"title": "express vulnerable to XSS via response.redirect()",
|
||||||
|
"range": "<4.20.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "flatted",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-25h7-pfq9-p65f",
|
||||||
|
"title": "flatted vulnerable to unbounded recursion DoS in parse() revive phase",
|
||||||
|
"range": "<3.4.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "flatted",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-rf6f-7fwh-wjgh",
|
||||||
|
"title": "Prototype Pollution via parse() in NodeJS flatted",
|
||||||
|
"range": "<=3.4.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "form-data",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-hmw2-7cc7-3qxx",
|
||||||
|
"title": "form-data: CRLF injection in form-data via unescaped multipart field names and filenames",
|
||||||
|
"range": ">=4.0.0 <4.0.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "gatsby-plugin-manifest",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "gatsby-plugin-sharp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "gatsby-plugin-utils",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "gatsby-sharp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "gatsby-transformer-sharp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "gatsby",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "transitive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "http-cache-semantics",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-ch52-4w7c-c8xp",
|
||||||
|
"title": "http-cache-semantics max-stale handling can disclose cross-user cached responses",
|
||||||
|
"range": "<=4.2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "immutable",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-v56q-mh7h-f735",
|
||||||
|
"title": "Immutable.js `List` 32-bit trie overflow → unrecoverable DoS",
|
||||||
|
"range": "<3.8.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "immutable",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-wf6x-7x77-mvgw",
|
||||||
|
"title": "Immutable is vulnerable to Prototype Pollution",
|
||||||
|
"range": "<3.8.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "immutable",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-xvcm-6775-5m9r",
|
||||||
|
"title": "Immutable: Hash-collision algorithmic complexity denial of service in Immutable.Map/Set",
|
||||||
|
"range": "<3.8.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "joi",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-6h2x-m376-mqjq",
|
||||||
|
"title": "joi: Quadratic regular-expression backtracking in `Joi.string().isoDate()`",
|
||||||
|
"range": ">=17.2.0 <17.13.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "joi",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-6w3j-5fw6-r9vr",
|
||||||
|
"title": "joi: Prototype pollution via a `__proto__` language key in custom messages",
|
||||||
|
"range": ">=17.2.0 <17.13.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "joi",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-gg4h-3hg2-grpc",
|
||||||
|
"title": "joi: object().rename() with a template target can set the validated object's prototype",
|
||||||
|
"range": ">=16.0.0 <17.13.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "joi",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-wr44-6hxh-3jwq",
|
||||||
|
"title": "joi messages compilation allows prototype replacement through __proto__ error codes",
|
||||||
|
"range": "<17.13.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "js-yaml",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-2883-xcg3-v3hh",
|
||||||
|
"title": "js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources",
|
||||||
|
"range": ">=3.0.0 <3.15.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "js-yaml",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-52cp-r559-cp3m",
|
||||||
|
"title": "js-yaml: YAML merge-key chains can force quadratic CPU consumption",
|
||||||
|
"range": ">=3.0.0 <3.15.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "js-yaml",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-5p4m-2wfm-xmqj",
|
||||||
|
"title": "JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026-59870 fix not backported",
|
||||||
|
"range": ">=3.0.0 <3.15.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "js-yaml",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-h67p-54hq-rp68",
|
||||||
|
"title": "JS-YAML: Quadratic-complexity DoS in merge key handling via repeated aliases",
|
||||||
|
"range": "<3.15.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "js-yaml",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-mh29-5h37-fv8m",
|
||||||
|
"title": "js-yaml has prototype pollution in merge (<<)",
|
||||||
|
"range": "<3.14.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "lodash",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-f23m-r3pf-42rh",
|
||||||
|
"title": "lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and `_.omit`",
|
||||||
|
"range": "<=4.17.23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "lodash",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-r5fr-rjxr-66jc",
|
||||||
|
"title": "lodash vulnerable to Code Injection via `_.template` imports key names",
|
||||||
|
"range": ">=4.0.0 <=4.17.23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "lodash",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-xxjr-mmjv-4gpg",
|
||||||
|
"title": "Lodash has Prototype Pollution Vulnerability in `_.unset` and `_.omit` functions",
|
||||||
|
"range": ">=4.0.0 <=4.17.22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "minimatch",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-23c5-xmqv-rm74",
|
||||||
|
"title": "minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regular expressions",
|
||||||
|
"range": "<3.1.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "minimatch",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3ppc-4f35-3m26",
|
||||||
|
"title": "minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern",
|
||||||
|
"range": "<3.1.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "minimatch",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-7r86-cg39-jmmj",
|
||||||
|
"title": "minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent GLOBSTAR segments",
|
||||||
|
"range": "<3.1.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3p4h-7m6x-2hcm",
|
||||||
|
"title": "Multer vulnerable to Denial of Service via incomplete cleanup of aborted uploads",
|
||||||
|
"range": ">=2.0.0-alpha.1 <2.2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-535w-7cp7-47q4",
|
||||||
|
"title": "multer vulnerable to Denial of Service via oversized array index in field names",
|
||||||
|
"range": "<2.3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-5528-5vmv-3xc2",
|
||||||
|
"title": "Multer Vulnerable to Denial of Service via Uncontrolled Recursion",
|
||||||
|
"range": "<2.1.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-72gw-mp4g-v24j",
|
||||||
|
"title": "Multer vulnerable to Denial of Service via deeply nested field names",
|
||||||
|
"range": ">=1.0.0 <2.2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-q7qp-rjg7-q26m",
|
||||||
|
"title": "multer vulnerable to Denial of Service via a pending asynchronous fileFilter after request teardown",
|
||||||
|
"range": ">=2.0.0 <2.5.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-qvfw-j98x-7q72",
|
||||||
|
"title": "multer vulnerable to file size limit bypass via async fileFilter race condition",
|
||||||
|
"range": "<2.3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-v52c-386h-88mc",
|
||||||
|
"title": "Multer vulnerable to Denial of Service via resource exhaustion",
|
||||||
|
"range": "<2.1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-wc9g-mqfw-jrwm",
|
||||||
|
"title": "multer vulnerable to Denial of Service via crafted multipart field names",
|
||||||
|
"range": "<2.3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "multer",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-xf7r-hgr6-v32p",
|
||||||
|
"title": "Multer vulnerable to Denial of Service via incomplete cleanup",
|
||||||
|
"range": "<2.1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "nanoid",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-28wg-ghj8-5hjv",
|
||||||
|
"title": "nanoid: non-secure generators can loop indefinitely with negative size",
|
||||||
|
"range": "<3.3.16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "nanoid",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-2v37-7h3g-55p8",
|
||||||
|
"title": "nanoid: custom generators can loop indefinitely when size is zero",
|
||||||
|
"range": "<3.3.18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "nanoid",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-mwcw-c2x4-8c55",
|
||||||
|
"title": "Predictable results in nanoid generation when given non-integer values",
|
||||||
|
"range": "<3.3.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "nanoid",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-xwg4-73v4-xw9w",
|
||||||
|
"title": "nanoid: Integer Overflow or Wraparound",
|
||||||
|
"range": "<3.3.12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "path-to-regexp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-37ch-88jc-xwx2",
|
||||||
|
"title": "path-to-regexp vulnerable to Regular Expression Denial of Service via multiple route parameters",
|
||||||
|
"range": "<0.1.13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "path-to-regexp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-9wv6-86v2-598j",
|
||||||
|
"title": "path-to-regexp outputs backtracking regular expressions",
|
||||||
|
"range": "<0.1.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "path-to-regexp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-rhx6-c78j-4q9w",
|
||||||
|
"title": "path-to-regexp contains a ReDoS",
|
||||||
|
"range": "<0.1.12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "picomatch",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-3v7f-55p6-f55p",
|
||||||
|
"title": "Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Matching",
|
||||||
|
"range": "<2.3.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "picomatch",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-c2c7-rcm5-vvqj",
|
||||||
|
"title": "Picomatch has a ReDoS vulnerability via extglob quantifiers",
|
||||||
|
"range": "<2.3.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "postcss",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-6g55-p6wh-862q",
|
||||||
|
"title": "PostCSS: Arbitrary file read and information disclosure via attacker-controlled sourceMappingURL in CSS comments",
|
||||||
|
"range": "<=8.5.11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "postcss",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-fxqj-rqcc-2cmp",
|
||||||
|
"title": "PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappingURL reads arbitrary .map files when `from` is unset",
|
||||||
|
"range": "<=8.5.22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "postcss",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-qx2v-qp2m-jg93",
|
||||||
|
"title": "PostCSS has XSS via Unescaped </style> in its CSS Stringify Output",
|
||||||
|
"range": "<8.5.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "postcss",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-r28c-9q8g-f849",
|
||||||
|
"title": "PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) leads to Arbitrary .map File Disclosure",
|
||||||
|
"range": "<=8.5.17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "probe-image-size",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-gjj5-9665-rwrc",
|
||||||
|
"title": "probe-image-size: Quadratic-time Denial of Service in the SVG Parser",
|
||||||
|
"range": "<=7.3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "serialize-javascript",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-5c6j-r48x-rmvq",
|
||||||
|
"title": "Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.toISOString()",
|
||||||
|
"range": "<=7.0.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "serialize-javascript",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-m5mm-p8h7-m29v",
|
||||||
|
"title": "Serialize JavaScript: Cross-site scripting (XSS) via unescaped </script at the end of a serialized function body",
|
||||||
|
"range": "<7.1.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "serialize-javascript",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-qj8w-gfj5-8c6v",
|
||||||
|
"title": "Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like objects",
|
||||||
|
"range": ">=5.0.0 <7.0.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "sharp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-f88m-g3jw-g9cj",
|
||||||
|
"title": "sharp inherited vulnerabilities in libvips: CVE-2026-33327, CVE-2026-33328, CVE-2026-35590, CVE-2026-35591",
|
||||||
|
"range": "<0.35.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "sharp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-rgj7-g3m4-5g8c",
|
||||||
|
"title": "sharp: Vulnerabilities in libheif: GHSA-g89c-p67h-r497 and GHSA-2jg2-4ch7-h545",
|
||||||
|
"range": "<0.35.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "sharp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-wq5f-xc86-pv6w",
|
||||||
|
"title": "sharp : Vulnerability in librsvg dependency CVE-2026-96889",
|
||||||
|
"range": "<0.35.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "socket.io-parser",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-2m8v-j782-fhvr",
|
||||||
|
"title": "Socket.IO: Zero-attachment Memory Exhaustion",
|
||||||
|
"range": ">=4.0.0 <4.2.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "socket.io-parser",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-677m-j7p3-52f9",
|
||||||
|
"title": "socket.io allows an unbounded number of binary attachments",
|
||||||
|
"range": ">=4.0.0 <4.2.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "source-map-js",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-68fv-2mgg-jv7q",
|
||||||
|
"title": "source-map-js allows event-loop denial of service through indexed source-map section offsets",
|
||||||
|
"range": ">=1.0.0 <1.2.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "svgo",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-2p49-hgcm-8545",
|
||||||
|
"title": "SVGO removeScripts plugin leaves some executable scripts intact",
|
||||||
|
"range": ">=1.0.0 <2.8.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "svgo",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-4vpr-x523-8j87",
|
||||||
|
"title": "SVGO: removeScripts incompletely sanitizes executable HTML in SVG foreignObject elements",
|
||||||
|
"range": ">=1.0.0 <2.8.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "svgo",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-w27v-7q3p-w38r",
|
||||||
|
"title": "SVGO: removeScripts allows executable links through namespace and control-character bypasses",
|
||||||
|
"range": ">=1.0.0 <2.8.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "svgo",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-xpqw-6gx7-v673",
|
||||||
|
"title": "SVGO DoS through entity expansion in DOCTYPE (Billion Laughs)",
|
||||||
|
"range": ">=2.1.0 <2.8.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "tmp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-52f5-9888-hmc6",
|
||||||
|
"title": "tmp allows arbitrary temporary file / directory write via symbolic link `dir` parameter",
|
||||||
|
"range": "<=0.2.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "tmp",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-ph9p-34f9-6g65",
|
||||||
|
"title": "tmp has Path Traversal via unsanitized prefix/postfix that enables directory escape",
|
||||||
|
"range": "<0.2.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "webpack-dev-middleware",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-g84c-rxfj-3j2c",
|
||||||
|
"title": "webpack-dev-middleware vulnerable to Path Traversal via non-slash-terminated publicPath",
|
||||||
|
"range": "<7.4.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ws",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-58qx-3vcg-4xpx",
|
||||||
|
"title": "ws: Uninitialized memory disclosure",
|
||||||
|
"range": ">=8.0.0 <8.20.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ws",
|
||||||
|
"severity": "high",
|
||||||
|
"advisory": "GHSA-96hv-2xvq-fx4p",
|
||||||
|
"title": "ws: Memory exhaustion DoS from tiny fragments and data chunks",
|
||||||
|
"range": ">=8.0.0 <8.21.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Audit gate: fail the build on any advisory that is not a tracked exception.
|
||||||
|
*
|
||||||
|
* `npm audit --audit-level=<x>` is all-or-nothing, and this tree cannot pass a
|
||||||
|
* flat gate: the Gatsby 5 build toolchain carries ~100 advisories at
|
||||||
|
* low/moderate/high with no non-breaking fix, because gatsby is a runtime
|
||||||
|
* dependency of the build. Blocking on any of those stops publishing
|
||||||
|
* permanently; ignoring the tree lets a genuinely new advisory through. So the
|
||||||
|
* known set is committed to audit-baseline.json with an owner and a reason,
|
||||||
|
* and this script fails only when something NEW appears at or above the
|
||||||
|
* threshold.
|
||||||
|
*
|
||||||
|
* Usage: node scripts/audit-gate.mjs [--write-baseline]
|
||||||
|
*/
|
||||||
|
import { execFileSync } from 'node:child_process';
|
||||||
|
import { readFileSync, writeFileSync } from 'node:fs';
|
||||||
|
import { dirname, join } from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||||
|
const BASELINE = join(HERE, 'audit-baseline.json');
|
||||||
|
const BLOCKING = new Set(['critical', 'high']);
|
||||||
|
|
||||||
|
/** npm audit exits non-zero when it finds anything, so ignore the status. */
|
||||||
|
function auditReport() {
|
||||||
|
let out;
|
||||||
|
try {
|
||||||
|
out = execFileSync('npm', ['audit', '--json', '--omit=optional'], {
|
||||||
|
encoding: 'utf8',
|
||||||
|
stdio: ['ignore', 'pipe', 'ignore'],
|
||||||
|
maxBuffer: 32 * 1024 * 1024
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
out = err.stdout;
|
||||||
|
if (!out) throw err;
|
||||||
|
}
|
||||||
|
return JSON.parse(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Flatten the report to one key per package/severity/advisory triple. */
|
||||||
|
function currentFindings(report) {
|
||||||
|
const findings = new Map();
|
||||||
|
for (const [pkg, v] of Object.entries(report.vulnerabilities ?? {})) {
|
||||||
|
if (!BLOCKING.has(v.severity)) continue;
|
||||||
|
const advisories = (v.via ?? []).filter((x) => typeof x === 'object');
|
||||||
|
if (advisories.length === 0) {
|
||||||
|
// via is a chain of parent package names - attribute to the package.
|
||||||
|
findings.set(`${pkg}|${v.severity}|transitive`, { pkg, severity: v.severity, advisory: 'transitive' });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const a of advisories) {
|
||||||
|
const id = (a.url ?? '').split('/').pop() || a.title || 'unknown';
|
||||||
|
findings.set(`${pkg}|${v.severity}|${id}`, { pkg, severity: v.severity, advisory: id, title: a.title, range: a.range });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return findings;
|
||||||
|
}
|
||||||
|
|
||||||
|
const report = auditReport();
|
||||||
|
const current = currentFindings(report);
|
||||||
|
|
||||||
|
if (process.argv.includes('--write-baseline')) {
|
||||||
|
const accepted = [...current.values()].sort((a, b) => `${a.pkg}${a.advisory}`.localeCompare(`${b.pkg}${b.advisory}`));
|
||||||
|
writeFileSync(
|
||||||
|
BASELINE,
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
$comment:
|
||||||
|
'Advisories at critical/high accepted for this tree. scripts/audit-gate.mjs fails the build on anything not listed here, so removing an entry re-arms the gate for that advisory. Regenerate with: node scripts/audit-gate.mjs --write-baseline',
|
||||||
|
owner: 'Site maintainers (allan@4gl.io)',
|
||||||
|
reason:
|
||||||
|
'Gatsby 5 build toolchain: no non-breaking fix available upstream, and these are build-time dependencies of a statically generated site. Re-check on each Gatsby major bump.',
|
||||||
|
accepted
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
) + '\n'
|
||||||
|
);
|
||||||
|
console.log(`wrote ${accepted.length} accepted advisories to ${BASELINE}`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseline = JSON.parse(readFileSync(BASELINE, 'utf8'));
|
||||||
|
const accepted = new Set((baseline.accepted ?? []).map((a) => `${a.pkg}|${a.severity}|${a.advisory}`));
|
||||||
|
|
||||||
|
const fresh = [...current.entries()].filter(([key]) => !accepted.has(key));
|
||||||
|
const resolved = [...accepted].filter((key) => !current.has(key));
|
||||||
|
|
||||||
|
for (const [, f] of fresh) {
|
||||||
|
console.error(`NEW ${f.severity.toUpperCase()}: ${f.pkg} - ${f.title ?? f.advisory} (${f.advisory})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resolved.length > 0) {
|
||||||
|
// Not a failure: a bumped or removed dependency closes advisories, and the
|
||||||
|
// baseline should be trimmed in the same change that closes them.
|
||||||
|
console.log(`${resolved.length} baseline entries no longer present - consider re-running with --write-baseline:`);
|
||||||
|
for (const key of resolved) console.log(` stale: ${key}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fresh.length > 0) {
|
||||||
|
console.error(`\n${fresh.length} untracked advisory/ies at critical or high.`);
|
||||||
|
console.error('Fix it, or add it to scripts/audit-baseline.json with a reason and an owner.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`audit gate: no new critical/high advisories (${current.size} tracked in baseline)`);
|
||||||