mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
Merge pull request #894 from MBombeck/chore/scanning-sweep
chore(security): close seven scanning alerts and the guard that hid one
This commit is contained in:
7 files changed
+212
-42
No files matched your search
@@ -2,14 +2,20 @@ name: Auto-merge Dependabot
|
||||
|
||||
on: pull_request
|
||||
|
||||
# Nothing outside the one job needs more than a checkout, so the default for
|
||||
# the workflow is read-only and the write scopes sit on the job that spends
|
||||
# them: `gh pr merge --auto` writes to the repository's merge queue state, and
|
||||
# both the merge and the review comment write to the pull request.
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
auto-merge:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
@@ -15,6 +15,31 @@
|
||||
base URL that is not a URL at all behaves as it did. The operator card now
|
||||
says which providers the field accepts. Found in a fork by @sweidinger.
|
||||
|
||||
### Security
|
||||
|
||||
- **The published image no longer ships four flagged dependency versions.**
|
||||
Three floors in the override block had gone stale: the sanitiser behind the
|
||||
doctor-report PDF sat below the fix for GHSA-55q2-fjhq-7xh7, the CSS
|
||||
processor the build runs on sat below the fix for CVE-2026-69153, and a
|
||||
schema library that arrives through two unrelated parents had no floor at
|
||||
all (CVE-2026-59952). All three are raised and re-resolved, each inside its
|
||||
existing major, so nothing changes shape for anyone.
|
||||
- **The Prisma command line inside the image gets the same pins as the app.**
|
||||
The image carries two separate installs, and only one of them reads the
|
||||
project's override block. The other is an npm install of the Prisma CLI, and
|
||||
it was quietly resolving an HTTP server (GHSA-frvp-7c67-39w9,
|
||||
CVE-2026-39406) and a schema library (CVE-2026-59952) at the versions the
|
||||
image scan flagged, while the same packages were pinned and clean in the
|
||||
application tree. Both are now pinned on the npm side too, verified by
|
||||
rebuilding that install both ways. This is the second time the same gap has
|
||||
produced a finding, so the guard that compares the two files was widened: it
|
||||
had been skipping every scoped package name, which is exactly the case that
|
||||
went unnoticed here.
|
||||
- The Dependabot auto-merge workflow no longer hands a write token to the
|
||||
whole run. The workflow default is read-only and the write scopes sit on the
|
||||
one job that spends them. Nothing about which updates merge automatically
|
||||
changes.
|
||||
|
||||
## [1.38.3] — 2026-09-02
|
||||
|
||||
An account with two-factor can be deleted from the phone, and every data
|
||||
|
||||
+10
@@ -191,11 +191,21 @@ COPY --from=builder /app/src/generated ./src/generated
|
||||
# still reports 7.8.0. Keep the range in step with the entry in
|
||||
# `pnpm-workspace.yaml` — they are one decision applied to two package
|
||||
# managers, and a fix that lands in only one of them is the defect above.
|
||||
#
|
||||
# The same class recurred on 2026-09-02: the image scan reported
|
||||
# `@hono/node-server@1.19.11` (GHSA-frvp-7c67-39w9, CVE-2026-39406) and
|
||||
# `valibot@1.2.0` (CVE-2026-59952) under this path, both reached through
|
||||
# `prisma -> @prisma/dev`, while the app tree carried 1.19.17 and a pin the
|
||||
# npm install never reads. Rebuilding this install both ways confirms it:
|
||||
# without the two fields below npm resolves 1.19.11 and 1.2.0, with them it
|
||||
# resolves 1.19.17 and 1.4.2, and `prisma --version` still reports 7.8.0.
|
||||
RUN mkdir -p /opt/prisma-cli && \
|
||||
cd /opt/prisma-cli && \
|
||||
npm init -y && \
|
||||
npm pkg set 'overrides.deepmerge-ts=^8.0.0' && \
|
||||
npm pkg set 'overrides.mysql2=^3.22.0' && \
|
||||
npm pkg set 'overrides.@hono/node-server=^1.19.15' && \
|
||||
npm pkg set 'overrides.valibot=^1.4.2' && \
|
||||
npm install --omit=dev prisma@7.8.0 @prisma/engines@7.8.0 tsx@4.23.1 dotenv@17.4.2 && \
|
||||
ln -sfn /opt/prisma-cli/node_modules/.bin/tsx /usr/local/bin/healthlog-tsx && \
|
||||
ln -sfn /opt/prisma-cli/node_modules/dotenv /app/node_modules/dotenv && \
|
||||
|
||||
Generated
+17
-26
@@ -5,10 +5,10 @@ settings:
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
overrides:
|
||||
dompurify@<=3.4.10: ^3.4.11
|
||||
postcss@<8.5.10: ^8.5.10
|
||||
dompurify@<3.4.13: ^3.4.13
|
||||
postcss@<8.5.23: ^8.5.23
|
||||
nanoid@<3.3.18: ^3.3.18
|
||||
'@hono/node-server@<1.19.13': ^1.19.13
|
||||
'@hono/node-server@<1.19.15': ^1.19.15
|
||||
hono@<4.12.25: ^4.12.25
|
||||
picomatch@<4.0.4: ^4.0.4
|
||||
body-parser@<2.3.0: ^2.3.0
|
||||
@@ -21,6 +21,7 @@ overrides:
|
||||
sharp@<0.35.0: ^0.35.3
|
||||
pdfjs-dist@>=5.6.83 <6.2.108: 6.2.108
|
||||
deepmerge-ts@<8.0.0: ^8.0.0
|
||||
valibot@<1.4.2: ^1.4.2
|
||||
|
||||
importers:
|
||||
|
||||
@@ -40,7 +41,7 @@ importers:
|
||||
version: 3.2.2(react@19.2.7)
|
||||
'@hookform/resolvers':
|
||||
specifier: ^5.9.1
|
||||
version: 5.9.1(@standard-schema/spec@1.1.0)(ajv-formats@2.1.1(ajv@8.20.0))(ajv@8.20.0)(effect@3.20.0)(react-hook-form@7.83.0(react@19.2.7))(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3)
|
||||
version: 5.9.1(@standard-schema/spec@1.1.0)(ajv-formats@2.1.1(ajv@8.20.0))(ajv@8.20.0)(effect@3.20.0)(react-hook-form@7.83.0(react@19.2.7))(valibot@1.4.2(typescript@6.0.3))(zod@4.4.3)
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: ^1.30.0
|
||||
version: 1.30.0(@cfworker/json-schema@4.1.1)(supports-color@7.2.0)(zod@4.4.3)
|
||||
@@ -864,7 +865,7 @@ packages:
|
||||
react-hook-form: ^7.55.0
|
||||
superstruct: '>=0.12.0'
|
||||
typanion: ^3.3.2
|
||||
valibot: '>=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc'
|
||||
valibot: ^1.4.2
|
||||
vest: '>=6.0.0'
|
||||
yup: ^1.0.0
|
||||
zod: ^3.25.0 || ^4.0.0
|
||||
@@ -4204,8 +4205,8 @@ packages:
|
||||
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
dompurify@3.4.12:
|
||||
resolution: {integrity: sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==}
|
||||
dompurify@3.4.14:
|
||||
resolution: {integrity: sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==}
|
||||
|
||||
dot-prop@6.0.1:
|
||||
resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==}
|
||||
@@ -5961,10 +5962,6 @@ packages:
|
||||
resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
postcss@8.5.20:
|
||||
resolution: {integrity: sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
postcss@8.5.25:
|
||||
resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@@ -6923,8 +6920,8 @@ packages:
|
||||
utrie@1.0.2:
|
||||
resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
|
||||
|
||||
valibot@1.2.0:
|
||||
resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==}
|
||||
valibot@1.4.2:
|
||||
resolution: {integrity: sha512-gjdCvJ6d3RyHAneqxMYMW9QMCwYMb3jpOO0IyHZV1bnRHFBHrX3VkIILt5XYR0WhwHiH7Mty8ovuPZ/O3gamrg==}
|
||||
peerDependencies:
|
||||
typescript: '>=5'
|
||||
peerDependenciesMeta:
|
||||
@@ -7923,7 +7920,7 @@ snapshots:
|
||||
dependencies:
|
||||
hono: 4.13.3
|
||||
|
||||
'@hookform/resolvers@5.9.1(@standard-schema/spec@1.1.0)(ajv-formats@2.1.1(ajv@8.20.0))(ajv@8.20.0)(effect@3.20.0)(react-hook-form@7.83.0(react@19.2.7))(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3)':
|
||||
'@hookform/resolvers@5.9.1(@standard-schema/spec@1.1.0)(ajv-formats@2.1.1(ajv@8.20.0))(ajv@8.20.0)(effect@3.20.0)(react-hook-form@7.83.0(react@19.2.7))(valibot@1.4.2(typescript@6.0.3))(zod@4.4.3)':
|
||||
dependencies:
|
||||
'@standard-schema/utils': 0.3.0
|
||||
react-hook-form: 7.83.0(react@19.2.7)
|
||||
@@ -7932,7 +7929,7 @@ snapshots:
|
||||
ajv: 8.20.0
|
||||
ajv-formats: 2.1.1(ajv@8.20.0)
|
||||
effect: 3.20.0
|
||||
valibot: 1.2.0(typescript@6.0.3)
|
||||
valibot: 1.4.2(typescript@6.0.3)
|
||||
zod: 4.4.3
|
||||
|
||||
'@humanfs/core@0.19.1': {}
|
||||
@@ -8894,7 +8891,7 @@ snapshots:
|
||||
proper-lockfile: 4.1.2
|
||||
remeda: 2.33.4
|
||||
std-env: 3.10.0
|
||||
valibot: 1.2.0(typescript@6.0.3)
|
||||
valibot: 1.4.2(typescript@6.0.3)
|
||||
zeptomatch: 2.1.0
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
@@ -11068,7 +11065,7 @@ snapshots:
|
||||
dependencies:
|
||||
esutils: 2.0.3
|
||||
|
||||
dompurify@3.4.12:
|
||||
dompurify@3.4.14:
|
||||
optionalDependencies:
|
||||
'@types/trusted-types': 2.0.7
|
||||
optional: true
|
||||
@@ -12253,7 +12250,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
canvg: 3.0.11
|
||||
core-js: 3.49.0
|
||||
dompurify: 3.4.12
|
||||
dompurify: 3.4.14
|
||||
html2canvas: 1.4.1
|
||||
|
||||
jsx-ast-utils@3.3.5:
|
||||
@@ -12603,7 +12600,7 @@ snapshots:
|
||||
'@swc/helpers': 0.5.15
|
||||
baseline-browser-mapping: 2.10.43
|
||||
caniuse-lite: 1.0.30001805
|
||||
postcss: 8.5.20
|
||||
postcss: 8.5.26
|
||||
react: 19.2.7
|
||||
react-dom: 19.2.7(react@19.2.7)
|
||||
styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@7.2.0))(react@19.2.7)
|
||||
@@ -12990,12 +12987,6 @@ snapshots:
|
||||
cssesc: 3.0.0
|
||||
util-deprecate: 1.0.2
|
||||
|
||||
postcss@8.5.20:
|
||||
dependencies:
|
||||
nanoid: 3.3.18
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
postcss@8.5.25:
|
||||
dependencies:
|
||||
nanoid: 3.3.18
|
||||
@@ -14169,7 +14160,7 @@ snapshots:
|
||||
base64-arraybuffer: 1.0.2
|
||||
optional: true
|
||||
|
||||
valibot@1.2.0(typescript@6.0.3):
|
||||
valibot@1.4.2(typescript@6.0.3):
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
|
||||
+21
-3
@@ -1,8 +1,20 @@
|
||||
overrides:
|
||||
"dompurify@<=3.4.10": "^3.4.11"
|
||||
"postcss@<8.5.10": "^8.5.10"
|
||||
# GHSA-55q2-fjhq-7xh7: a crafted document gets past the sanitiser and its
|
||||
# markup survives into the output. The copy here is jspdf's optional HTML
|
||||
# renderer, which the doctor-report PDF path reaches.
|
||||
"dompurify@<3.4.13": "^3.4.13"
|
||||
# CVE-2026-69153. Next declares an exact `postcss@8.4.31`, so nothing except
|
||||
# this bound moves it. The build has run on the 8.5 line since the first
|
||||
# bump; the fix landed in 8.5.23.
|
||||
"postcss@<8.5.23": "^8.5.23"
|
||||
"nanoid@<3.3.18": "^3.3.18"
|
||||
"@hono/node-server@<1.19.13": "^1.19.13"
|
||||
# GHSA-frvp-7c67-39w9 raised the floor from 1.19.13 to 1.19.15. Mirrored for
|
||||
# /opt/prisma-cli in the Dockerfile, which is where the flagged 1.19.11
|
||||
# actually landed: prisma pulls it through @prisma/dev, and that install
|
||||
# reads npm `overrides`, not this file. The bound stays on the 1.x line
|
||||
# because the advisory is fixed there too and 2.x is a major nothing asked
|
||||
# for.
|
||||
"@hono/node-server@<1.19.15": "^1.19.15"
|
||||
"hono@<4.12.25": "^4.12.25"
|
||||
"picomatch@<4.0.4": "^4.0.4"
|
||||
"body-parser@<2.3.0": "^2.3.0"
|
||||
@@ -39,6 +51,12 @@ overrides:
|
||||
# override is the only way through. It runs on the config-loading and CLI
|
||||
# path, not under a request, but a red audit blocks the whole release train.
|
||||
"deepmerge-ts@<8.0.0": "^8.0.0"
|
||||
# CVE-2026-59952. Two copies arrive, neither of them ours to call: an
|
||||
# optional peer of `@hookform/resolvers` (this app validates with zod) and
|
||||
# prisma's local dev server. Mirrored for /opt/prisma-cli in the Dockerfile,
|
||||
# where the flagged 1.2.0 landed. 1.4.2 is the same major, so no consumer is
|
||||
# dragged onto a new one.
|
||||
"valibot@<1.4.2": "^1.4.2"
|
||||
|
||||
allowBuilds:
|
||||
"@prisma/engines": true
|
||||
|
||||
@@ -150,17 +150,86 @@ describe("container dependency installation", () => {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* `>= 0` comparison over a dotted version, enough for the floor checks below.
|
||||
* Pre-release suffixes are not expected in an override replacement and are
|
||||
* ignored rather than guessed at.
|
||||
*/
|
||||
function atLeast(version: string, floor: string): boolean {
|
||||
const parts = (value: string) =>
|
||||
value
|
||||
.replace(/^[\^~>=<\s]+/, "")
|
||||
.split("-")[0]
|
||||
.split(".")
|
||||
.map((piece) => Number.parseInt(piece, 10) || 0);
|
||||
const [a, b] = [parts(version), parts(floor)];
|
||||
for (let i = 0; i < Math.max(a.length, b.length); i += 1) {
|
||||
const left = a[i] ?? 0;
|
||||
const right = b[i] ?? 0;
|
||||
if (left !== right) return left > right;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
describe("production dependency advisory floors", () => {
|
||||
it("pins vulnerable transitive ranges to compatible patched versions", () => {
|
||||
/**
|
||||
* The floor an advisory demands, by package. Raising an override past one of
|
||||
* these must not break this test: an earlier version of it asserted the exact
|
||||
* key and replacement string, so every legitimate floor raise failed it while
|
||||
* a floor that had gone STALE against a newer advisory passed. It now asserts
|
||||
* the property that matters, which is that the pin is at or above the fixed
|
||||
* version. Update a floor here when a new advisory raises it.
|
||||
*/
|
||||
const floors: Record<string, string> = {
|
||||
// GHSA-55q2-fjhq-7xh7, reached through jspdf's optional HTML renderer.
|
||||
dompurify: "3.4.13",
|
||||
// CVE-2026-69153.
|
||||
postcss: "8.5.23",
|
||||
// GHSA-frvp-7c67-39w9 and CVE-2026-39406. Mirrored in the Dockerfile.
|
||||
"@hono/node-server": "1.19.15",
|
||||
hono: "4.12.25",
|
||||
// CVE-2026-59952. Mirrored in the Dockerfile.
|
||||
valibot: "1.4.2",
|
||||
};
|
||||
|
||||
it("pins vulnerable transitive ranges at or above the fixed version", () => {
|
||||
const workspace = parse(readRepoFile("pnpm-workspace.yaml")) as {
|
||||
overrides?: Record<string, string>;
|
||||
};
|
||||
const overrides = workspace.overrides ?? {};
|
||||
|
||||
expect(workspace.overrides).toMatchObject({
|
||||
"dompurify@<=3.4.10": "^3.4.11",
|
||||
"postcss@<8.5.10": "^8.5.10",
|
||||
"@hono/node-server@<1.19.13": "^1.19.13",
|
||||
"hono@<4.12.25": "^4.12.25",
|
||||
});
|
||||
const byName = new Map<string, string>();
|
||||
for (const [key, replacement] of Object.entries(overrides)) {
|
||||
const selectorAt = key.startsWith("@")
|
||||
? key.indexOf("@", 1)
|
||||
: key.indexOf("@");
|
||||
byName.set(
|
||||
selectorAt === -1 ? key : key.slice(0, selectorAt),
|
||||
replacement,
|
||||
);
|
||||
}
|
||||
expect(byName.size).toBeGreaterThan(0);
|
||||
|
||||
for (const [name, floor] of Object.entries(floors)) {
|
||||
const replacement = byName.get(name);
|
||||
expect(
|
||||
replacement,
|
||||
`${name} has no override in pnpm-workspace.yaml`,
|
||||
).toBeDefined();
|
||||
expect(
|
||||
atLeast(replacement as string, floor),
|
||||
`${name} is pinned to ${replacement}, below the advisory floor ${floor}.`,
|
||||
).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("compares versions rather than always agreeing", () => {
|
||||
// The comparison is the whole test above; a helper that never returns
|
||||
// false would make it vacuous.
|
||||
expect(atLeast("^3.4.13", "3.4.13")).toBe(true);
|
||||
expect(atLeast("^3.4.14", "3.4.13")).toBe(true);
|
||||
expect(atLeast("^3.4.12", "3.4.13")).toBe(false);
|
||||
expect(atLeast("^1.19.9", "1.19.15")).toBe(false);
|
||||
expect(atLeast("^2.0.5", "1.19.15")).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -20,6 +20,12 @@
|
||||
* would encode noise. It asserts agreement where both files speak, which is
|
||||
* the failure that actually happened.
|
||||
*
|
||||
* The matcher had a blind spot of its own until 2026-09-02: it refused any
|
||||
* workspace key beginning with `@`, so every scoped package was invisible to
|
||||
* it. `@hono/node-server` was pinned on one side and unpinned on the other and
|
||||
* the guard stayed green, which is the same shape of green the guard exists to
|
||||
* prevent. Scoped keys parse now, and a test below pins that they do.
|
||||
*
|
||||
* Limit, written down so the next reader does not over-trust a green run: this
|
||||
* compares declared ranges. It cannot see a NEW vulnerable transitive that
|
||||
* neither file mentions. Only the image scan can, and that job runs on
|
||||
@@ -44,17 +50,30 @@ function dockerfileOverrides(): Map<string, string> {
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces an overrides key to the bare package name. The key carries a version
|
||||
* selector, so `deepmerge-ts@<8.0.0` and a bare `deepmerge-ts` both land on the
|
||||
* same name. A scoped name opens with its own `@`, so the selector starts at
|
||||
* the SECOND one, not the first.
|
||||
*/
|
||||
function packageNameOf(key: string): string {
|
||||
const trimmed = key.trim();
|
||||
const selectorAt = trimmed.startsWith("@")
|
||||
? trimmed.indexOf("@", 1)
|
||||
: trimmed.indexOf("@");
|
||||
return (selectorAt === -1 ? trimmed : trimmed.slice(0, selectorAt)).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* `"<name>@<selector>": "<range>"` entries under the workspace `overrides:`
|
||||
* block. The key carries a version selector, so `deepmerge-ts@<8.0.0` and a
|
||||
* bare `deepmerge-ts` both have to reduce to the same package name.
|
||||
* block.
|
||||
*/
|
||||
function workspaceOverrides(): Map<string, string> {
|
||||
const found = new Map<string, string>();
|
||||
const pattern = /^\s+"([^"@][^"]*?)(?:@[^"]*)?"\s*:\s*"([^"]+)"/gm;
|
||||
const pattern = /^\s+"([^"]+)"\s*:\s*"([^"]+)"/gm;
|
||||
const block = WORKSPACE.split(/^allowBuilds:/m)[0];
|
||||
for (const match of block.matchAll(pattern)) {
|
||||
found.set(match[1].trim(), match[2].trim());
|
||||
found.set(packageNameOf(match[1]), match[2].trim());
|
||||
}
|
||||
return found;
|
||||
}
|
||||
@@ -74,6 +93,23 @@ describe("dependency overrides — pnpm workspace and the npm install agree", ()
|
||||
expect(workspace.has("deepmerge-ts")).toBe(true);
|
||||
});
|
||||
|
||||
it("reads scoped workspace keys rather than skipping them", () => {
|
||||
// The old matcher started the name at `[^"@]`, so `@hono/node-server` was
|
||||
// never in the shared set and could disagree across the two files without
|
||||
// failing anything. Both halves are asserted: the reduction itself, and
|
||||
// that a real scoped entry survives it.
|
||||
expect(packageNameOf("@hono/node-server@<1.19.15")).toBe(
|
||||
"@hono/node-server",
|
||||
);
|
||||
expect(packageNameOf("dompurify@<3.4.13")).toBe("dompurify");
|
||||
expect(packageNameOf("js-yaml@>=4.0.0 <4.3.1")).toBe("js-yaml");
|
||||
expect(packageNameOf("deepmerge-ts")).toBe("deepmerge-ts");
|
||||
|
||||
const workspace = workspaceOverrides();
|
||||
const scoped = [...workspace.keys()].filter((name) => name.startsWith("@"));
|
||||
expect(scoped.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("pins the same range wherever both files name the same package", () => {
|
||||
const docker = dockerfileOverrides();
|
||||
const workspace = workspaceOverrides();
|
||||
@@ -91,6 +127,21 @@ describe("dependency overrides — pnpm workspace and the npm install agree", ()
|
||||
}
|
||||
});
|
||||
|
||||
it("mirrors every pin the /opt/prisma-cli tree was scanned on", () => {
|
||||
// These three were each reported by the image scan under
|
||||
// `/opt/prisma-cli`, reached through `prisma`. Losing a mirror is not a
|
||||
// style regression, it is the vulnerable version coming back.
|
||||
const docker = dockerfileOverrides();
|
||||
for (const name of ["deepmerge-ts", "@hono/node-server", "valibot"]) {
|
||||
expect(
|
||||
docker.has(name),
|
||||
`${name} was flagged under /opt/prisma-cli and needs an ` +
|
||||
`\`npm pkg set 'overrides.${name}=...'\` line in the Dockerfile; ` +
|
||||
`pnpm-workspace.yaml does not reach that install.`,
|
||||
).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps the override ahead of the version Prisma's config asks for", () => {
|
||||
// `@prisma/config` requests deepmerge-ts 7.x; the advisory is fixed in
|
||||
// 8.0.0. Anything that lets a 7.x back in re-opens CVE-2026-40345.
|
||||
|
||||
Reference in new issue
Block a user