Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
216 commits
Select commit Hold shift + click to select a range
919d5c6
docs: design patch-validator image supply chain
seonghobae Aug 6, 2026
f9dc807
docs: plan patch-validator image implementation
seonghobae Aug 6, 2026
192e50c
test: define patch-validator image profile contract
seonghobae Aug 6, 2026
e3ad66e
test: isolate patch-validator image profile API
seonghobae Aug 6, 2026
ace9960
feat: add image-bound patch validation profile
seonghobae Aug 6, 2026
80e7b04
feat: export image-bound patch validator API
seonghobae Aug 6, 2026
8569e91
test: cover patch-validator image runner failures
seonghobae Aug 6, 2026
9a2a385
test: include patch-validator runtime in coverage
seonghobae Aug 6, 2026
137f0e9
test: define shell-free patch-validator runtime contract
seonghobae Aug 6, 2026
c4d7bc7
feat: add shell-free patch-validator runtime
seonghobae Aug 6, 2026
4e1ce3f
feat: add corrected patch-validator runtime module
seonghobae Aug 6, 2026
4cabceb
test: cover corrected patch-validator runtime
seonghobae Aug 6, 2026
594fb2d
fix: remove superseded invalid runtime draft
seonghobae Aug 6, 2026
fc95a35
fix: keep stable runtime test import shim
seonghobae Aug 6, 2026
369203f
test: replace patch-validator runtime coverage suite
seonghobae Aug 6, 2026
720d4a3
test: restore exact-digest runtime coverage suite
seonghobae Aug 6, 2026
24fcbb5
test(patch-validator): correct parser expectations
seonghobae Aug 6, 2026
8e9713e
test: widen coverage diagnostics
seonghobae Aug 6, 2026
d7bb58c
test(patch-validator): cover fail-closed runtime edges
seonghobae Aug 6, 2026
27115bc
test(patch-validator): fix deterministic fault injection
seonghobae Aug 6, 2026
72ee23e
test(patch-validator): cover final parser and size boundaries
seonghobae Aug 6, 2026
26ed658
test(patch-validator): cover BOM-only empty diff
seonghobae Aug 6, 2026
3818da7
test(patch-validator): reach missing-header guard
seonghobae Aug 6, 2026
bc59e3a
test(patch-validator): cover remaining runtime branches
seonghobae Aug 6, 2026
d7784cf
test(patch-validator): define immutable image contract
seonghobae Aug 6, 2026
9138d4e
feat(patch-validator): add digest-pinned image
seonghobae Aug 6, 2026
a41c0c1
build(patch-validator): restrict image context
seonghobae Aug 6, 2026
b0f1a68
test(patch-validator): require Dockerfile-specific ignore contract
seonghobae Aug 6, 2026
8153b3d
build(patch-validator): use Dockerfile-specific ignore file
seonghobae Aug 6, 2026
9e3e00c
test(sandbox): cover patch-validator dockerignore control path
seonghobae Aug 6, 2026
e881270
build(patch-validator): remove inactive ignore file
seonghobae Aug 6, 2026
d4e7bac
test(patch-validator): bind control path to active Docker ignore file
seonghobae Aug 6, 2026
16ebd22
test(patch-validator): define read-only image verification workflow
seonghobae Aug 6, 2026
e543013
test(patch-validator): define bounded receipt verification
seonghobae Aug 6, 2026
eccd8c6
feat(patch-validator): verify bounded image receipts
seonghobae Aug 6, 2026
a7b1216
feat(patch-validator): add receipt verifier CLI
seonghobae Aug 6, 2026
f4243b5
test(patch-validator): cover receipt library instead of CLI wrapper
seonghobae Aug 6, 2026
64abc66
test(patch-validator): cover image receipt verifier
seonghobae Aug 6, 2026
adf71dd
build(patch-validator): expose receipt verification command
seonghobae Aug 6, 2026
fc09211
test(patch-validator): require exact-head image builds
seonghobae Aug 6, 2026
507ade6
ci(patch-validator): verify exact-head image without publication auth…
seonghobae Aug 6, 2026
aa936f8
test(patch-validator): reproduce silent image entrypoint
seonghobae Aug 6, 2026
8ee191b
test(patch-validator): specify fail-closed executable contract
seonghobae Aug 6, 2026
723f45d
test(patch-validator): exercise shell-free image command
seonghobae Aug 6, 2026
8263556
test(patch-validator): require executable Node image command
seonghobae Aug 6, 2026
2f8a0f5
fix(patch-validator): execute image validation entrypoint
seonghobae Aug 6, 2026
10391da
test(patch-validator): reproduce read-only Vite config mutation
seonghobae Aug 6, 2026
f36c24b
test(patch-validator): require isolated runtime facade in image
seonghobae Aug 6, 2026
2813f00
test(patch-validator): execute isolated runtime facade
seonghobae Aug 6, 2026
a36ee6f
test(patch-validator): bind receipts to isolated runtime entrypoint
seonghobae Aug 6, 2026
d52c00f
fix(patch-validator): isolate Vite config loading from read-only depe…
seonghobae Aug 6, 2026
af68e92
build(patch-validator): include isolated runtime facade
seonghobae Aug 6, 2026
5d693f9
fix(patch-validator): execute read-only-safe runtime facade
seonghobae Aug 6, 2026
063ca6b
fix(patch-validator): verify isolated runtime entrypoint
seonghobae Aug 6, 2026
514c077
test(patch-validator): cover read-only runtime facade
seonghobae Aug 6, 2026
859912d
test(patch-validator): require canonical create/delete parity
seonghobae Aug 6, 2026
81e1bec
fix(patch-validator): allow canonical regular-file create and delete
seonghobae Aug 6, 2026
ad96603
test(patch-validator): require live-head refusal and pinned frontend
seonghobae Aug 6, 2026
1e147e2
fix(patch-validator): pin Dockerfile frontend
seonghobae Aug 6, 2026
e4ad190
fix(patch-validator): refuse stale PR heads
seonghobae Aug 6, 2026
32924bb
test(security): prove image output cannot forge host evidence
seonghobae Aug 6, 2026
9636e38
docs(patch-validator): document image verification boundary
seonghobae Aug 6, 2026
437dea6
docs(doctoring): record patch-validator image standards
seonghobae Aug 6, 2026
d2f6e70
test(patch-validator): require every-head image verification
seonghobae Aug 6, 2026
3308e5b
test(security): require internal result creation
seonghobae Aug 6, 2026
089b3ba
fix(patch-validator): verify every PR head
seonghobae Aug 6, 2026
279d944
fix(security): synthesize patch image evidence on trusted host
seonghobae Aug 6, 2026
cd5e6af
fix(security): keep validator result inside private tmpfs
seonghobae Aug 6, 2026
5df05b9
test(security): remove container-authored evidence expectations
seonghobae Aug 6, 2026
1b17d03
fix(security): keep smoke result off untrusted mounts
seonghobae Aug 6, 2026
a4f01bb
test(security): require trusted smoke receipt synthesis
seonghobae Aug 6, 2026
93aee36
fix(runtime): preserve fail-closed environment diagnostics
seonghobae Aug 6, 2026
ebbceff
test(security): align image profile tests with trusted host evidence
seonghobae Aug 6, 2026
e883860
test(runtime): cover explicit private result path
seonghobae Aug 6, 2026
fa38aa0
test(runtime): cover process environment result path
seonghobae Aug 6, 2026
ee7eabe
test: cover patch runtime wrapper branches
seonghobae Aug 6, 2026
090c219
docs(patch-validator): align trusted smoke evidence boundary
seonghobae Aug 6, 2026
cfdd7c3
test(security): require image-owned validation policy
seonghobae Aug 6, 2026
985f481
docs(doctoring): align trusted image evidence boundary
seonghobae Aug 6, 2026
fd48ac7
test(security): bind expected image-owned tool entrypoints
seonghobae Aug 6, 2026
26cd061
fix(security): add image-owned TypeScript policy
seonghobae Aug 6, 2026
1728e7c
docs(changelog): record patch-validator image boundary
seonghobae Aug 6, 2026
3a69cb7
fix(security): add image-owned Vitest policy
seonghobae Aug 6, 2026
826bab7
fix(security): enforce image-owned validation policy
seonghobae Aug 6, 2026
29aa3ba
fix(security): package immutable validation policy
seonghobae Aug 6, 2026
5eb8fe2
test(build): require trusted policy in Docker context
seonghobae Aug 6, 2026
f8b2bd3
fix(build): include image-owned validation policy
seonghobae Aug 6, 2026
e4362f7
test(security): expect image-owned Vitest configuration
seonghobae Aug 6, 2026
9c9c2cf
test(patch-validator): include image-owned policy files
seonghobae Aug 6, 2026
0bb1ea2
test(security): bind SBOM and vulnerability receipts
seonghobae Aug 6, 2026
afd1cea
fix(security): bind SBOM and vulnerability receipts
seonghobae Aug 6, 2026
e985d47
fix(security): require vulnerability receipt verification
seonghobae Aug 6, 2026
45918d4
fix(security): verify vulnerability receipt identity
seonghobae Aug 6, 2026
3afcdb0
test(security): require vulnerability receipt wiring
seonghobae Aug 6, 2026
462b278
test(security): prove source policy cannot influence image smoke
seonghobae Aug 6, 2026
eecd7bb
test(patch-validator): require minimal runtime dependency tree
seonghobae Aug 6, 2026
99361f1
test(security): exercise hostile source policy in real image
seonghobae Aug 6, 2026
326900e
fix(security): prune Worker-only validator dependencies
seonghobae Aug 6, 2026
5e76b04
test(operations): bound untrusted smoke diagnostics
seonghobae Aug 6, 2026
601ca5b
test(operations): cover every smoke diagnostic field
seonghobae Aug 6, 2026
89968ad
feat(operations): add bounded untrusted smoke diagnostics
seonghobae Aug 6, 2026
a6cbcae
test(operations): require bounded private smoke diagnostics
seonghobae Aug 6, 2026
746e7f7
test(coverage): gate smoke diagnostic production code
seonghobae Aug 6, 2026
d1f6770
fix(operations): expose bounded private smoke diagnostics
seonghobae Aug 6, 2026
e556eea
test(operations): require bounded image failure diagnostics
seonghobae Aug 6, 2026
10be0f0
feat(operations): emit bounded image failure diagnostics
seonghobae Aug 6, 2026
5aaed33
refactor(operations): keep image diagnostic entrypoint pure
seonghobae Aug 6, 2026
9692f9d
test(coverage): gate image diagnostic entrypoint
seonghobae Aug 6, 2026
8035734
fix(operations): emit bounded failure diagnostics from image
seonghobae Aug 6, 2026
fb9fbe3
fix(build): include image diagnostic entrypoint
seonghobae Aug 6, 2026
8224ade
fix(provenance): bind image diagnostic entrypoint
seonghobae Aug 6, 2026
c52d1c9
test(provenance): expect diagnostic image entrypoint
seonghobae Aug 6, 2026
7e52ac4
test(patch-validator): require host-captured bounded diagnostic
seonghobae Aug 6, 2026
2831c05
test(image): bind bounded diagnostic entrypoint
seonghobae Aug 6, 2026
27be94b
test(operations): capture bounded stderr diagnostics
seonghobae Aug 6, 2026
9c0ff75
fix(patch-validator): capture bounded stderr diagnostic
seonghobae Aug 6, 2026
af7a8fd
fix(coverage): remove unreachable diagnostic branch
seonghobae Aug 6, 2026
cb89076
fix(runtime): resolve trusted TypeScript inputs from config location
seonghobae Aug 6, 2026
fd288fd
test(runtime): require image-owned TypeScript transform
seonghobae Aug 6, 2026
f4fd169
fix(runtime): own TypeScript transform policy
seonghobae Aug 6, 2026
9610367
fix(runtime): load compiler without Vite dependency transform
seonghobae Aug 6, 2026
2a4be60
test(security): reject unfixed vulnerability exceptions
seonghobae Aug 6, 2026
7c4604c
fix(security): fail on all serious image vulnerabilities
seonghobae Aug 6, 2026
85db096
test(patch-validator): require static scratch runtime
seonghobae Aug 7, 2026
9432595
fix(patch-validator): build a static scratch runtime
seonghobae Aug 7, 2026
b22f0a5
ci(patch-validator): verify the static scratch image
seonghobae Aug 7, 2026
840639a
test(patch-validator): enforce the static image contract
seonghobae Aug 7, 2026
b0790c6
test(patch-validator): verify static image evidence
seonghobae Aug 7, 2026
2c1ab99
test(patch-validator): inspect the static binary entrypoint
seonghobae Aug 7, 2026
d89aaa1
test(security): require portable runtime inventory regex
seonghobae Aug 7, 2026
6fe1b10
fix(security): use POSIX ERE for runtime payload scan
seonghobae Aug 7, 2026
164c675
fix(test): match immutable Dockerfile frontend digest
seonghobae Aug 7, 2026
bad3444
test(security): require static runtime vulnerability inventory
seonghobae Aug 7, 2026
8b129fd
fix(security): verify static runtime vulnerability evidence
seonghobae Aug 7, 2026
46ee9e2
test(security): cover static runtime evidence verifier
seonghobae Aug 7, 2026
038edb7
test(coverage): include static runtime evidence verifier
seonghobae Aug 7, 2026
75e06c2
fix(security): bind static runtime scan receipts
seonghobae Aug 7, 2026
bb24065
fix(security): scan self-compiled runtime binaries
seonghobae Aug 7, 2026
38c8b8a
test(security): bind static runtime verifier contract
seonghobae Aug 7, 2026
0626f2d
docs(security): document static runtime scan boundary
seonghobae Aug 7, 2026
45d0d71
docs(doctoring): record static runtime vulnerability control
seonghobae Aug 7, 2026
95d8496
test(coverage): cover missing Syft image identity
seonghobae Aug 7, 2026
b1c7218
fix(security): inventory static Node ELF identity
seonghobae Aug 7, 2026
2272c31
fix(security): verify real Syft CPE records exactly
seonghobae Aug 7, 2026
fb542f8
test(security): cover real Syft CPE serialization
seonghobae Aug 7, 2026
95a9219
test(runtime): require immutable Node ELF inventory note
seonghobae Aug 7, 2026
5a4f6c7
test(runtime): fail closed on embedded dependency advisories
seonghobae Aug 7, 2026
c0b64db
fix(runtime): authenticate embedded static dependencies
seonghobae Aug 7, 2026
10936c3
test(runtime): cover embedded dependency evidence contract
seonghobae Aug 7, 2026
fa2dab4
fix(runtime): require embedded dependency scan receipts
seonghobae Aug 7, 2026
c3c3219
test: target embedded component-set mismatch accurately
seonghobae Aug 7, 2026
96c91e4
test(security): require embedded runtime evidence wiring
seonghobae Aug 7, 2026
cd9b4ca
test(security): distinguish runtime metadata from dependencies
seonghobae Aug 7, 2026
1de1070
fix(security): classify Node runtime metadata explicitly
seonghobae Aug 7, 2026
9a99189
fix(test): preserve static-runtime verifier diagnostics
seonghobae Aug 7, 2026
c13dcd7
fix(security): scan embedded static runtime dependencies
seonghobae Aug 7, 2026
be514ea
test(security): block vulnerable bundled ngtcp2
seonghobae Aug 7, 2026
f3c891d
test(security): preserve fixed ngtcp2 acceptance floor
seonghobae Aug 7, 2026
b3095ff
test(security): fail closed on ambiguous ngtcp2 versions
seonghobae Aug 7, 2026
fd14b3a
fix(security): enforce ngtcp2 advisory floor
seonghobae Aug 7, 2026
a152db1
test(docs): require current embedded runtime evidence
seonghobae Aug 7, 2026
20cffe4
docs(sandbox): document embedded runtime evidence
seonghobae Aug 7, 2026
f181ca9
docs(doctoring): record embedded runtime vulnerability lane
seonghobae Aug 7, 2026
13382ee
docs(changelog): align patch-validator runtime evidence
seonghobae Aug 7, 2026
3f0b8e4
test(security): reject unassessed embedded identities
seonghobae Aug 7, 2026
7b06009
fix(security): require positive embedded scan assessments
seonghobae Aug 7, 2026
fddfa83
test(security): cover embedded assessment binding
seonghobae Aug 7, 2026
8cd19ee
test(security): bind metadata scan assessments
seonghobae Aug 7, 2026
1f4acc7
fix(security): bind positive embedded scan assessments
seonghobae Aug 7, 2026
19e844f
docs(security): document positive embedded scan evidence
seonghobae Aug 7, 2026
74cd61f
docs(doctoring): record embedded assessment evidence
seonghobae Aug 7, 2026
a1478c1
docs(changelog): record positive embedded scan evidence
seonghobae Aug 7, 2026
6a0aa78
test(security): reject unsupported embedded scan identity
seonghobae Aug 7, 2026
1c19f98
fix(security): reject unsupported generic scan identities
seonghobae Aug 7, 2026
001d22f
test(security): require raw embedded scanner evidence
seonghobae Aug 7, 2026
f8e1f1c
test(security): bind embedded scans to raw Grype evidence
seonghobae Aug 7, 2026
bb730f9
fix(security): bind embedded results to raw Grype evidence
seonghobae Aug 7, 2026
02babcf
test(security): align zero-match failure with raw evidence contract
seonghobae Aug 7, 2026
72484a1
test(security): bind metadata fixtures to raw Grype evidence
seonghobae Aug 7, 2026
e44d3cb
test(security): bind embedded scanner identity evidence
seonghobae Aug 7, 2026
7d4631f
fix(security): bind embedded scans to exact identities
seonghobae Aug 7, 2026
1b33223
test(security): bind clean Grype matches to artifacts
seonghobae Aug 7, 2026
b854259
test(security): retain exact embedded scan identity
seonghobae Aug 7, 2026
55650f4
fix(security): retain reviewed embedded scan identity
seonghobae Aug 7, 2026
b46e0ee
test(security): assert retained database identity
seonghobae Aug 7, 2026
742b06c
test(security): require direct frozen-db component scans
seonghobae Aug 7, 2026
54e8bf8
test(security): require reviewed runtime identity catalog
seonghobae Aug 7, 2026
c32fcc5
fix(security): enforce reviewed runtime identity catalog
seonghobae Aug 7, 2026
880369b
test(docs): require current raw scanner evidence contract
seonghobae Aug 7, 2026
22d42bb
docs(security): replace synthetic scan assessment contract
seonghobae Aug 7, 2026
c884a62
test(docs): bind raw scanner control to amendment
seonghobae Aug 7, 2026
7773fd2
fix(security): validate raw embedded scanner evidence
seonghobae Aug 7, 2026
22924bc
fix(security): bind embedded scans to reviewed identities
seonghobae Aug 7, 2026
939a0fb
docs(doctoring): record direct embedded scan migration
seonghobae Aug 7, 2026
34a8eb5
test(security): cover structured CPE artifact evidence
seonghobae Aug 7, 2026
48ef9cd
test(security): cover database snapshot canonicalization
seonghobae Aug 7, 2026
c574f4f
test: reject generic static runtime identity
seonghobae Aug 7, 2026
4d45e66
fix: remove generic static runtime identity
seonghobae Aug 7, 2026
d6ed3cc
test: reject superseded patch-validator evidence claims
seonghobae Aug 7, 2026
bf0a6fa
test: bind current unreleased evidence wording
seonghobae Aug 7, 2026
81de9c8
docs: describe raw embedded runtime evidence
seonghobae Aug 7, 2026
a8cfac8
docs: align changelog with raw embedded evidence
seonghobae Aug 7, 2026
4ccb5fc
test: distinguish rejected synthetic assessment claims
seonghobae Aug 7, 2026
9ba042d
test(ci): retain bounded smoke diagnostic evidence
seonghobae Aug 9, 2026
4dd522a
test(ci): bind smoke diagnostics to retained evidence
seonghobae Aug 9, 2026
605ffdd
fix(ci): retain bounded smoke failure evidence
seonghobae Aug 9, 2026
720599a
test(ci): cover smoke diagnostic retention boundaries
seonghobae Aug 9, 2026
700d58c
test(sandbox): require Unicode-capable static Node runtime
seonghobae Aug 9, 2026
08dbfdc
fix(sandbox): retain Unicode regex support in static Node
seonghobae Aug 9, 2026
878ae76
test(image): fail closed on undecided outbound license
seonghobae Aug 10, 2026
57ff5b2
fix(image): do not invent outbound license metadata
seonghobae Aug 10, 2026
c5f36bc
docs(image): keep outbound rights undecided
seonghobae Aug 10, 2026
341b710
test(docs): reject invented image license claims
seonghobae Aug 10, 2026
162b98e
revert(test): avoid unmatched documentation RED
seonghobae Aug 10, 2026
d7e1204
test(security): reject ambiguous validator receipt JSON
seonghobae Aug 10, 2026
abc038c
fix(security): fail closed on ambiguous validator receipts
seonghobae Aug 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
603 changes: 603 additions & 0 deletions .github/workflows/patch-validator-image.yml

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions CHANGELOG.md

Large diffs are not rendered by default.

94 changes: 94 additions & 0 deletions Dockerfile.patch-validator
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# syntax=docker/dockerfile:1.7@sha256:a57df69d0ea827fb7266491f2813635de6f17269be881f696fbfdf2d83dda33e

FROM alpine:3.24.1@sha256:79ff19e9084a00eece421b2523fb93e22d730e2c0e525905de047e848e56d95f AS node_builder

ARG NODE_VERSION=24.19.0
ARG NODE_SOURCE_SHA256=f6d95e10a0431ee1067fc6aabe9f762908b4716dd35324e1ddb4b1466b76659f

RUN apk add --no-cache \
binutils-gold \
g++ \
gcc \
libgcc \
linux-headers \
make \
python3 \
py3-setuptools \
xz

ADD --checksum=sha256:${NODE_SOURCE_SHA256} https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}.tar.xz /tmp/node.tar.xz

RUN mkdir -p /usr/src/node \
&& tar -xJf /tmp/node.tar.xz --strip-components=1 -C /usr/src/node \
&& cd /usr/src/node \
&& ./configure \
--prefix=/opt/node \
--fully-static \
--with-intl=small-icu \
--without-npm \
--without-corepack \
--disable-single-executable-application \
&& make -j"$(getconf _NPROCESSORS_ONLN)" V= \
&& make install \
&& test "$(/opt/node/bin/node --version)" = "v${NODE_VERSION}" \
&& /opt/node/bin/node --input-type=module --eval="new RegExp('\\p{ID_Continue}', 'u')" \
&& ! readelf -l /opt/node/bin/node | grep -q 'Requesting program interpreter' \
&& ! readelf -d /opt/node/bin/node | grep -q '(NEEDED)' \
&& strip /opt/node/bin/node \
&& printf '%s\n' \
'{"name":"node","version":"24.19.0","cpe":"cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*","license":"MIT","type":"binary","architecture":"x86_64","appCpe":"cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*","system":"nodejs","vendor":"nodejs","sourceRepo":"https://github.com/nodejs/node"}' \
>/tmp/node-package-note.json \
&& objcopy \
--add-section .note.package=/tmp/node-package-note.json \
--set-section-flags .note.package=noload,readonly \
/opt/node/bin/node \
&& readelf -p .note.package /opt/node/bin/node \
| grep -Fq 'cpe:2.3:a:nodejs:node.js:24.19.0:*:*:*:*:*:*:*' \
&& test "$(/opt/node/bin/node --version)" = "v${NODE_VERSION}" \
&& /opt/node/bin/node --input-type=module --eval="new RegExp('\\p{ID_Continue}', 'u')" \
&& ! readelf -l /opt/node/bin/node | grep -q 'Requesting program interpreter' \
&& ! readelf -d /opt/node/bin/node | grep -q '(NEEDED)'

FROM node:24.18.0-alpine3.24@sha256:4ba75f835bb8802193e4c114572113d4b26f95f6f094f4b5229d2a77773e0afc AS dependencies

WORKDIR /build

COPY package.json package-lock.json ./
RUN npm_config_os=wasip1-threads npm_config_cpu=wasm32 \
npm ci --include=optional --ignore-scripts --no-audit --no-fund \
&& npm pkg delete devDependencies.@cloudflare/workers-types devDependencies.wrangler \
&& npm_config_os=wasip1-threads npm_config_cpu=wasm32 \
npm prune --include=optional --ignore-scripts --no-audit --no-fund \
&& test -f node_modules/typescript/bin/tsc \
&& test -f node_modules/vitest/vitest.mjs \
&& test -f node_modules/@vitest/coverage-v8/package.json \
&& test -f node_modules/@rolldown/binding-wasm32-wasi/package.json \
&& test -z "$(find node_modules -type f -name '*.node' -print -quit)" \
&& test ! -e node_modules/@cloudflare/workers-types \
&& test ! -e node_modules/wrangler \
&& test ! -e node_modules/workerd \
&& test ! -e node_modules/miniflare

FROM scratch AS runtime

ARG SOURCE_REVISION
LABEL org.opencontainers.image.source="https://github.com/ContextualWisdomLab/noema" \
org.opencontainers.image.revision="${SOURCE_REVISION}" \
org.opencontainers.image.title="Noema Patch Validator" \
org.opencontainers.image.description="Credential-free exact-head text patch validation runtime" \
org.opencontainers.image.documentation="https://github.com/ContextualWisdomLab/noema/blob/main/docs/patch-validator-image.md"

ENV NAPI_RS_FORCE_WASI=error

USER 65532:65532
WORKDIR /workspace

COPY --from=node_builder --chown=65532:65532 /opt/node/bin/node /nodejs/bin/node
COPY --from=dependencies --chown=65532:65532 /build/node_modules /opt/noema/node_modules
COPY --chown=65532:65532 patch-validator/entrypoint.mjs /opt/noema/entrypoint.mjs
COPY --chown=65532:65532 patch-validator/validate-patch.mjs /opt/noema/validate-patch.mjs
COPY --chown=65532:65532 patch-validator/runtime.mjs /opt/noema/runtime.mjs
COPY --chown=65532:65532 patch-validator/validator-tsconfig.json /opt/noema/validator-tsconfig.json
COPY --chown=65532:65532 patch-validator/validator-vitest.config.mjs /opt/noema/validator-vitest.config.mjs

ENTRYPOINT ["/nodejs/bin/node", "--input-type=module", "--eval", "import { runCli } from '/opt/noema/runtime.mjs'; import { runEntrypoint } from '/opt/noema/entrypoint.mjs'; process.exitCode = runEntrypoint({ runCliImpl: runCli, writeDiagnostic: (message) => process.stderr.write(message) });"]
10 changes: 10 additions & 0 deletions Dockerfile.patch-validator.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*
!package.json
!package-lock.json
!patch-validator/
patch-validator/*
!patch-validator/entrypoint.mjs
!patch-validator/validate-patch.mjs
!patch-validator/runtime.mjs
!patch-validator/validator-tsconfig.json
!patch-validator/validator-vitest.config.mjs
69 changes: 69 additions & 0 deletions docs/doctoring/patch-validator-embedded-scan-assessment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Doctoring amendment: raw embedded-runtime scanner evidence

## Status

- **Decision date:** 2026-08-07
- **Applies to:** PR #67 patch-validator static-runtime evidence
- **Release claim:** none
- **Production activation claim:** none
- **Workflow migration state:** direct raw per-component scanning is implemented for the reviewed identity catalog; integrated acceptance remains fail-closed until the exact runtime component set is fully reviewed and exact-head verification passes

This amendment supersedes the earlier locally synthesized completion model. The exact-head regressions demonstrated that a zero-match component could look complete without proving that Grype evaluated the reviewed package identity, and that independently valid per-component results could still be substituted across artifacts or vulnerability-database snapshots.

## Finding

An empty vulnerability match list is negative finding evidence, not proof that a particular package identity was evaluated. The earlier workflow constructed a local completion object after an aggregate SBOM scan and used generic package identities for native dependencies. That was insufficient for a fully static Node runtime because an unsupported or weak identity could produce zero matches without distinguishing “evaluated and clean” from “no applicable matcher.”

The workflow now builds its inventory only from a bounded reviewed identity catalog, updates the Grype vulnerability database once, disables per-component automatic database updates, scans each reviewed PURL or CPE directly, and retains each raw scanner result. Any `process.versions` dependency without a reviewed identity aborts evidence generation instead of being omitted, converted to a generic package, or marked locally complete. The verifier independently rejects unsupported identities, synthetic completion fields, mismatched match artifacts, blocking findings, and database drift.

## Control decision

The embedded-runtime evidence boundary uses a **reviewed identity catalog** keyed by the exact `process.versions` key. A bundled dependency is eligible for scanning only when the catalog binds that key to the expected inventory name and to exactly one scanner-supported identity form:

1. an exact npm PURL whose package name and version match the catalog and `process.versions`; or
2. an exact CPE 2.3 application identity whose reviewed vendor, product, and version match the catalog and `process.versions`.

Unknown keys, generic PURLs, wildcard or placeholder CPE vendors/products, arbitrary aliases, and identities inferred from receipt-controlled fields are explicit release blockers. Current catalog entries are deliberately bounded; adding a new native dependency requires evidence review rather than automatic identity fabrication.

Every bundled dependency must carry **raw Grype** JSON for a direct scan of that exact reviewed identity. The verifier requires:

- scanner descriptor `grype` at the pinned version;
- scanner source type consistent with PURL or CPE and a source target exactly equal to the reviewed identity;
- a valid vulnerability-database status record;
- bounded provider metadata with capture timestamps and input digests;
- no ignored matches;
- every reported match artifact bound back to the same reviewed PURL or CPE and exact component version;
- no MEDIUM, HIGH, CRITICAL, or UNKNOWN finding; and
- the **same vulnerability database** identity across every component scan.

The canonical shared database identity is derived from the database schema/build metadata plus sorted provider capture/input metadata and is retained in verification output. This makes database drift visible rather than allowing two components in one acceptance decision to be evaluated against different snapshots.

The workflow updates Grype's vulnerability database once, freezes per-component auto-update for the scan set, invokes each reviewed PURL or CPE directly, and retains the raw scanner result. A local “completed” flag, aggregate-only SBOM result, scanner process exit alone, or grouped synthetic result is not evidence of component evaluation. The workflow and verifier both fail closed when the reviewed catalog is incomplete; a red exact-head action caused by an unmapped runtime dependency is therefore expected evidence of a missing review, not a reason to weaken the gate.

## Why this is stricter than zero findings

Grype's *Supported scan targets* documentation treats individual PURL and CPE identities as explicit scan targets. Its vulnerability-database documentation also explains that the database is locally cached and can be updated explicitly. Noema therefore binds acceptance to the literal scanner target and one shared database snapshot rather than inferring assessment from an empty match array.

The National Vulnerability Database maintains the Official Common Platform Enumeration (CPE) Dictionary. Noema treats an authoritative NVD CPE mapping as reviewed identity evidence where a CPE is used; a merely syntactically valid CPE is not sufficient. For example, NVD records OpenSSL under vendor/product `openssl:openssl`, and NVD's analysis of CVE-2026-40170 maps ngtcp2 through reviewed CPE configurations including `nghttp2:ngtcp2` while identifying 1.22.1 as the fixed floor. Those mappings are controls, not heuristics generated from a package name at runtime.

Node.js documents `process.versions` as version information for Node.js and its dependencies. Noema uses it as the exact-runtime dependency declaration that the reviewed component set must match, not as a cryptographic proof of binary composition. `modules` and `napi` remain explicitly reviewed runtime metadata rather than fabricated vulnerable packages.

## Residual risk

Raw scanner evidence does not prove that vulnerability databases are complete or that every upstream project has an authoritative ecosystem identity. Catalog omissions therefore fail closed. The scanner binary, database acquisition path, hosted runner, workflow source, CPE/PURL review process, and upstream advisory coverage remain part of the trust chain. Future registry publication must separately bind signature, SBOM, vulnerability evidence, SLSA provenance, and the published digest before release acceptance.

## APA 7th references

Anchore. (2026). *Supported scan targets*. Anchore Open Source. https://oss.anchore.com/docs/guides/vulnerability/scan-targets/

Anchore. (2026). *Vulnerability database*. Anchore Open Source. https://oss.anchore.com/docs/guides/vulnerability/database/

National Institute of Standards and Technology. (2025). *Official Common Platform Enumeration (CPE) dictionary*. National Vulnerability Database. https://nvd.nist.gov/products/cpe

National Institute of Standards and Technology. (2026). *CVE-2026-40170 detail*. National Vulnerability Database. https://nvd.nist.gov/vuln/detail/CVE-2026-40170

Node.js contributors. (2026). *Process: `process.versions`* (Node.js v24 documentation). OpenJS Foundation. https://nodejs.org/download/release/latest-v24.x/docs/api/process.html#processversions

OWASP Foundation. (2025). *CycloneDX specification 1.7*. https://cyclonedx.org/specification/overview/

Souppaya, M., Scarfone, K., & Dodson, D. (2022). *Secure Software Development Framework (SSDF) version 1.1: Recommendations for mitigating the risk of software vulnerabilities* (NIST Special Publication 800-218). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-218
Loading
Loading