Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
250 commits
Select commit Hold shift + click to select a range
6ffea8b
test(security): define agent artifact admission boundary
seonghobae Aug 28, 2026
77c1309
test(security): format red admission contract
seonghobae Aug 28, 2026
1a5d2c7
feat(security): add agent artifact admission crate
codex Aug 28, 2026
30df4f9
feat(security): harden agent artifact admission policy
codex Aug 28, 2026
b82edf2
test(security): lock admission audit durability contract
seonghobae Aug 29, 2026
68a3ae3
feat(security): add minimized admission audit sinks
seonghobae Aug 29, 2026
8ae3f66
feat(security): enable production audit serialization
seonghobae Aug 29, 2026
b495bd9
feat(security): expose append-only audit contract
seonghobae Aug 29, 2026
94483e1
test(security): lock admission config and credential contract
seonghobae Aug 29, 2026
497fe08
feat(security): add strict admission config loading
seonghobae Aug 29, 2026
cb79089
feat(security): expose strict admission configuration
seonghobae Aug 29, 2026
5f7f61c
fix(ci): format strict admission configuration
seonghobae Aug 29, 2026
45e41f2
fix(ci): format admission config contract tests
seonghobae Aug 29, 2026
5f41e1e
feat(security): add deny-all admission deployment example
seonghobae Aug 29, 2026
afc535c
feat(security): publish admission credential schema
seonghobae Aug 29, 2026
6405a99
test(security): define authenticated admission API contract
seonghobae Aug 29, 2026
2e882b7
feat(security): expose authenticated artifact admission service
seonghobae Aug 29, 2026
38a37be
chore(lock): refresh admission service dependencies
github-actions[bot] Aug 29, 2026
34f6305
chore(ci): format admission service exact head
seonghobae Aug 29, 2026
07be0ab
style(rust): format admission service
github-actions[bot] Aug 29, 2026
6eea129
fix(security): remove deprecated token compare
codex Aug 29, 2026
485ab06
test(ddd): enforce agent admission dependency direction
seonghobae Sep 1, 2026
e28756a
docs(ddd): define agent admission bounded context
seonghobae Sep 1, 2026
60a356b
docs(adr): record agent admission bounded context
seonghobae Sep 1, 2026
f5c69bc
docs(api): publish agent admission OpenAPI contract
seonghobae Sep 1, 2026
a24ecec
refactor(ddd): name admission domain explicitly
seonghobae Sep 1, 2026
d31043d
docs(ddd): align context map with admission module name
seonghobae Sep 1, 2026
4ce8a59
docs(ddd): align ADR with admission module name
seonghobae Sep 1, 2026
c9c51ab
test(admission): require audit evidence for oversized authenticated r…
seonghobae Sep 1, 2026
3654297
feat(admission): classify oversized request bodies
seonghobae Sep 1, 2026
5d19199
feat(audit): record authenticated body-limit rejection
seonghobae Sep 1, 2026
416fce1
refactor(audit): expose request rejection evidence builder
seonghobae Sep 1, 2026
b97e557
fix(admission): audit body-limit rejection before response
seonghobae Sep 1, 2026
a0275e1
test(admission): remove obsolete unaudited body-limit expectation
seonghobae Sep 1, 2026
ac991b9
docs(api): document audited body-limit rejection
seonghobae Sep 1, 2026
225ff0c
docs(security): model agent artifact admission threats
seonghobae Sep 1, 2026
af30a71
docs(ops): add artifact admission runbook
seonghobae Sep 1, 2026
ee495f4
docs(research): trace artifact admission standards
seonghobae Sep 1, 2026
3b1f1f1
merge(main): converge agent artifact admission with protected head
seonghobae Sep 1, 2026
e54e886
style(admission): apply rustfmt to HTTP boundary
seonghobae Sep 1, 2026
ba0082f
style(admission): format DDD fitness test
seonghobae Sep 1, 2026
3a23772
style(admission): format oversized-request contract
seonghobae Sep 1, 2026
704e222
merge: synchronize agent artifact admission with protected main
seonghobae Sep 1, 2026
e0a4ea0
test(admission): reject alternate install roots
seonghobae Sep 2, 2026
155335f
feat(admission): classify alternate install roots
seonghobae Sep 2, 2026
96badfa
fix(admission): block alternate install roots
seonghobae Sep 2, 2026
ad049ea
docs(admission): publish alternate-root denial
seonghobae Sep 2, 2026
ff68d4f
docs(admission): record install-root escape threat
seonghobae Sep 2, 2026
03ee834
test(admission): cover package-manager root escapes
seonghobae Sep 2, 2026
9ce6c8f
test(admission): reject uv and Cargo root overrides
seonghobae Sep 2, 2026
f39846f
test(admission): reject npm safety-flag override
seonghobae Sep 2, 2026
e220b49
fix(admission): reject conflicting script safety flags
seonghobae Sep 2, 2026
0cd8fa5
test(admission): cover npm negated safety flag
seonghobae Sep 2, 2026
54e882f
docs(admission): trace npm safety-flag precedence
seonghobae Sep 2, 2026
1df4a2a
test(admission): reject attached pip trust/root flags
seonghobae Sep 2, 2026
02125ad
fix(admission): reject attached short trust/root flags
seonghobae Sep 2, 2026
ffe89e3
docs(admission): trace pip trust and install-root controls
seonghobae Sep 2, 2026
5ea6b47
test(admission): reject uv index trust-root overrides
seonghobae Sep 2, 2026
7368cc0
fix(admission): block uv and cargo destination overrides
seonghobae Sep 2, 2026
cb80062
docs(admission): trace uv and cargo override controls
seonghobae Sep 2, 2026
a9ec111
test(admission): reject Cargo source overrides
seonghobae Sep 2, 2026
5c1725d
fix(admission): reject Cargo git and path sources
seonghobae Sep 2, 2026
a216aa1
docs(admission): trace Cargo source selectors
seonghobae Sep 2, 2026
73fa6a4
docs(changelog): record agent artifact admission controls
seonghobae Sep 2, 2026
3875e00
docs(threat-model): define package source and digest boundary
seonghobae Sep 2, 2026
79e8da0
docs(runbook): require post-admission artifact byte verification
seonghobae Sep 2, 2026
148f691
test(admission): reject npm workspace scope expansion
seonghobae Sep 2, 2026
2dd93c0
fix(admission): reject npm workspace scope overrides
seonghobae Sep 2, 2026
7c01c2d
docs(admission): trace npm workspace scope control
seonghobae Sep 2, 2026
52a77b9
docs(admission): model npm workspace scope escape
seonghobae Sep 2, 2026
bba4a18
docs(changelog): record npm workspace admission hardening
seonghobae Sep 2, 2026
f3c05de
test(admission): cover npm workspace short alias
seonghobae Sep 2, 2026
1ea226d
fix(admission): reject npm -w workspace selector
seonghobae Sep 2, 2026
2ea7391
test(admission): reject undeclared install operands
seonghobae Sep 2, 2026
0d8b7e2
fix(admission): bind argv operands to reviewed artifacts
seonghobae Sep 2, 2026
d64976d
test(admission): keep hitchhike regression focused
seonghobae Sep 2, 2026
51d91d5
test(admission): reject indirect package sources
seonghobae Sep 2, 2026
e552672
test(admission): cover attached indirect sources
seonghobae Sep 2, 2026
838e194
fix(admission): reject indirect artifact sources
seonghobae Sep 2, 2026
fcf0a58
test(admission): reject cross-ecosystem package manager reuse
seonghobae Sep 2, 2026
05dd7ab
fix(admission): bind artifacts to package-manager ecosystem
seonghobae Sep 2, 2026
c10e6dd
test(admission): preserve same-ecosystem cargo install
seonghobae Sep 2, 2026
7c38f25
docs(admission): trace package-manager ecosystem binding
seonghobae Sep 2, 2026
b3d0831
docs(changelog): record ecosystem-bound artifact admission
seonghobae Sep 2, 2026
080997c
test(security): reject Yarn workspace-root escape flags
seonghobae Sep 2, 2026
0a4f20d
fix(security): block Yarn workspace-root scope escape
seonghobae Sep 2, 2026
a2d7043
docs(security): trace Yarn workspace-root rejection
seonghobae Sep 2, 2026
350156b
docs(changelog): record Yarn workspace-scope hardening
seonghobae Sep 2, 2026
a5a80c7
test(admission): reject Bun scope and config escapes
seonghobae Sep 2, 2026
fdb75c2
fix(admission): fail closed on Bun scope overrides
seonghobae Sep 2, 2026
23863f0
test(admission): cover Bun flag aliases and split forms
seonghobae Sep 2, 2026
60279df
fix(admission): reject Bun filter alias
seonghobae Sep 2, 2026
fa22c4b
docs(admission): trace Bun scope and config controls
seonghobae Sep 2, 2026
86abdb9
docs(changelog): record Bun admission hardening
seonghobae Sep 2, 2026
4383730
test(admission): keep Bun argv construction explicit
seonghobae Sep 2, 2026
842f84d
test(admission): reject pnpm directory escape flags
seonghobae Sep 2, 2026
8fbd709
fix(admission): block pnpm workspace directory overrides
seonghobae Sep 2, 2026
eec758b
docs(changelog): record pnpm directory fail-closed policy
seonghobae Sep 2, 2026
2281586
docs(security): trace pnpm directory authority
seonghobae Sep 2, 2026
875ec62
test(admission): reject pnpm workspace selectors
seonghobae Sep 2, 2026
31d2600
fix(admission): block pnpm workspace scope overrides
seonghobae Sep 2, 2026
5f71cd5
docs(changelog): record pnpm workspace-scope controls
seonghobae Sep 2, 2026
538c905
docs(security): trace pnpm workspace selectors
seonghobae Sep 2, 2026
f3c03b3
test(admission): reject pnpm dotted config authority
seonghobae Sep 2, 2026
8f205a6
fix(admission): reject pnpm dotted config authority
seonghobae Sep 2, 2026
80230be
docs(changelog): record pnpm config-override hardening
seonghobae Sep 2, 2026
6d0823c
docs(security): model pnpm dotted-config authority
seonghobae Sep 2, 2026
eb6523a
docs(security): trace pnpm dotted configuration authority
seonghobae Sep 2, 2026
25be946
test(admission): reject npm config-file trust overrides
seonghobae Sep 2, 2026
c63f27b
fix(admission): block npm config-file trust overrides
seonghobae Sep 2, 2026
97399d5
docs(changelog): record npm config-file admission hardening
seonghobae Sep 2, 2026
7160f38
docs(security): trace npm config-file authority boundary
seonghobae Sep 2, 2026
f9b0453
test(admission): reject npm TLS trust overrides
seonghobae Sep 2, 2026
8be683a
fix(admission): block npm TLS trust overrides
seonghobae Sep 2, 2026
8edd045
docs(changelog): record npm TLS trust hardening
seonghobae Sep 2, 2026
217108b
docs(security): trace npm TLS trust authority boundary
seonghobae Sep 2, 2026
609cbde
test(admission): reject cargo target-dir escape
seonghobae Sep 2, 2026
2545b75
fix(admission): block Cargo target-dir escape
seonghobae Sep 2, 2026
02ede7e
test(admission): reject unreviewed Cargo build variants
seonghobae Sep 3, 2026
32d9609
fix(admission): bind Cargo install build variants
seonghobae Sep 3, 2026
66b7eb6
docs(security): bind Cargo install build variants
seonghobae Sep 3, 2026
3aaba99
test: reproduce pnpmfile execution escape
seonghobae Sep 3, 2026
d994e64
fix: suppress pnpmfile execution during admission
seonghobae Sep 3, 2026
cfbe3b8
docs: trace pnpmfile execution boundary
seonghobae Sep 3, 2026
85f0f65
docs: record pnpmfile admission hardening
seonghobae Sep 3, 2026
46363d7
test(security): reject option terminator safety bypass
seonghobae Sep 3, 2026
0ccab11
fix(security): reject argv parser terminators
seonghobae Sep 3, 2026
46772dd
docs(security): trace option parser authority boundary
seonghobae Sep 3, 2026
e10227f
docs(changelog): record argv parser hardening
seonghobae Sep 3, 2026
e88429e
test(admission): block Bun trust authority expansion
seonghobae Sep 3, 2026
8f7c477
fix(admission): reject Bun trust authority mutation
seonghobae Sep 3, 2026
2825de8
docs(security): trace Bun trust authority boundary
seonghobae Sep 3, 2026
b19e19f
docs(changelog): record Bun trust hardening
seonghobae Sep 3, 2026
af3341e
test(admission): reject Bun integrity bypass
seonghobae Sep 3, 2026
26eca37
fix(admission): preserve Bun integrity verification
seonghobae Sep 3, 2026
2df626e
docs(security): trace Bun integrity bypass boundary
seonghobae Sep 3, 2026
b90fd58
docs(changelog): record Bun integrity verification guard
seonghobae Sep 3, 2026
8310066
test(security): reject caller-selected OCI platform variants
seonghobae Sep 3, 2026
17ca3b9
fix(security): fail closed on OCI platform selection
seonghobae Sep 3, 2026
b84a30c
fix(security): bind OCI platform choice to artifact policy
seonghobae Sep 3, 2026
890aba0
test(architecture): keep artifact variant policy in domain
seonghobae Sep 3, 2026
8d3663d
docs(security): trace OCI platform artifact identity boundary
seonghobae Sep 3, 2026
75f003e
test(security): cover OCI platform guard branches
seonghobae Sep 3, 2026
e24f8ea
test(security): reject Podman OCI selector aliases
seonghobae Sep 3, 2026
950e105
fix(security): bind Podman OCI selector aliases
seonghobae Sep 3, 2026
09a2e50
docs(security): trace Podman OCI selector authority
seonghobae Sep 3, 2026
857da84
docs(changelog): record OCI selector alias hardening
seonghobae Sep 3, 2026
186be29
test(security): reject Podman registry TLS trust overrides
seonghobae Sep 3, 2026
7725ae8
test(security): cover Podman TLS false spellings
seonghobae Sep 3, 2026
b7b13e5
feat(security): classify Podman registry TLS trust overrides
seonghobae Sep 3, 2026
c4cb573
fix(security): fail closed on Podman registry TLS overrides
seonghobae Sep 3, 2026
7c833b6
test(architecture): keep OCI trust policy in domain boundary
seonghobae Sep 3, 2026
d45cb23
docs(security): trace OCI registry TLS trust authority
seonghobae Sep 3, 2026
de69e71
docs(changelog): record OCI registry TLS hardening
seonghobae Sep 3, 2026
d7f429c
test(security): reject OCI repository-wide pull expansion
seonghobae Sep 4, 2026
7f06137
fix(security): bind OCI pulls to exact artifact set
seonghobae Sep 4, 2026
37751af
docs(security): record exact-set OCI pull invariant
seonghobae Sep 4, 2026
3a63247
docs(security): trace OCI pull cardinality authority
seonghobae Sep 4, 2026
883d1d3
test(admission): cover assigned OCI all-tags forms
seonghobae Sep 4, 2026
e9e07e6
fix(admission): block assigned OCI all-tags expansion
seonghobae Sep 4, 2026
2207a6f
test(admission): cover OCI all-tags boolean assignments
seonghobae Sep 4, 2026
6dfd777
docs(admission): trace assigned OCI all-tags repair
seonghobae Sep 4, 2026
a1105c5
test(security): reject bundled OCI all-tags shorthands
seonghobae Sep 4, 2026
f35db9e
fix(security): parse bundled OCI all-tags shorthand
seonghobae Sep 4, 2026
897a790
test(security): preserve quiet-only OCI pulls
seonghobae Sep 4, 2026
5b7fd58
docs(security): trace bundled OCI shorthand authority
seonghobae Sep 4, 2026
f75817e
docs(changelog): record OCI shorthand hardening
seonghobae Sep 4, 2026
dd6b930
test(security): cover assigned OCI shorthand bundles
seonghobae Sep 4, 2026
0f6a02a
fix(security): honor assigned OCI shorthand semantics
seonghobae Sep 4, 2026
578e493
docs(security): trace assigned OCI shorthand semantics
seonghobae Sep 4, 2026
7309878
docs(changelog): record assigned OCI shorthand semantics
seonghobae Sep 4, 2026
400c532
test(admission): reject caller-selected OCI registry credentials
seonghobae Sep 4, 2026
3eade5d
fix(admission): deny OCI registry credential overrides
seonghobae Sep 4, 2026
bd9d210
docs(security): trace OCI registry authentication authority
seonghobae Sep 4, 2026
d944a30
docs(changelog): record OCI registry auth admission hardening
seonghobae Sep 4, 2026
d7aa94f
test(admission): reject caller-selected OCI decryption keys
seonghobae Sep 4, 2026
261ecc2
fix(admission): deny caller-selected OCI decryption keys
seonghobae Sep 4, 2026
841abfd
docs(security): trace OCI decryption authority boundary
seonghobae Sep 4, 2026
32c748e
docs(changelog): record OCI decryption authority hardening
seonghobae Sep 4, 2026
c2ac4c2
docs(threat-model): bind OCI decryption and registry credential autho…
seonghobae Sep 4, 2026
9f11a7f
test(admission): reject caller-selected PyPI artifact variants
seonghobae Sep 4, 2026
a23583a
fix(admission): bind PyPI artifact and build variants
seonghobae Sep 4, 2026
b333670
refactor(admission): use generic artifact variant guard
seonghobae Sep 4, 2026
bab0f8b
docs(changelog): record PyPI variant admission
seonghobae Sep 4, 2026
f501261
docs(doctoring): trace PyPI artifact variant authority
seonghobae Sep 4, 2026
aaecfe6
test(admission): reject attached pip build settings
seonghobae Sep 4, 2026
c8546f4
fix(admission): reject attached pip config settings
seonghobae Sep 4, 2026
462d984
docs(doctoring): record attached pip config parsing
seonghobae Sep 4, 2026
2b78613
test(admission): reject unbound uv artifact variants
seonghobae Sep 4, 2026
c655cbc
fix(admission): bind uv pip artifact variants
seonghobae Sep 4, 2026
5522439
test(admission): reject unreviewed PyPI dependency expansion
seonghobae Sep 4, 2026
3069570
fix(admission): model exact PyPI dependency cardinality
seonghobae Sep 4, 2026
3eb2a32
fix(admission): enforce exact PyPI dependency set
seonghobae Sep 4, 2026
28333cd
test(admission): keep exact PyPI positives dependency-bounded
seonghobae Sep 4, 2026
ad52a44
docs(admission): trace uv and dependency cardinality controls
seonghobae Sep 4, 2026
c83e235
docs(security): bind PyPI resolver authority
seonghobae Sep 4, 2026
f25e20b
docs(changelog): record exact PyPI dependency admission
seonghobae Sep 4, 2026
4484acd
test(admission): bind Cargo version identity
seonghobae Sep 4, 2026
de5bc32
test(admission): align Cargo identity reason
seonghobae Sep 4, 2026
a193266
fix(admission): bind Cargo version identity
seonghobae Sep 4, 2026
d268908
style(admission): format Cargo selector guard
seonghobae Sep 4, 2026
aa24fb9
docs(admission): trace Cargo version authority
seonghobae Sep 4, 2026
6fe642f
test(admission): isolate Cargo version selector
seonghobae Sep 4, 2026
4c5883d
test(admission): reject Cargo overwrite authority
seonghobae Sep 4, 2026
76823b8
fix(admission): classify Cargo overwrite authority
seonghobae Sep 4, 2026
c35f646
fix(admission): fail closed on Cargo overwrite authority
seonghobae Sep 4, 2026
46fae7c
docs(security): trace Cargo overwrite authority
seonghobae Sep 4, 2026
a13afe2
docs(changelog): record Cargo overwrite guard
seonghobae Sep 4, 2026
213987c
docs(security): model Cargo overwrite authority
seonghobae Sep 4, 2026
4cfdaf9
test(admission): cover Cargo mutation flag variants
seonghobae Sep 4, 2026
7caadbb
test(admission): reject npm package-spec source substitution
seonghobae Sep 4, 2026
551101f
test(admission): reject PyPI direct-source substitution
seonghobae Sep 4, 2026
ec72427
feat(admission): bind package operand to reviewed source identity
seonghobae Sep 4, 2026
13cd6dd
fix(admission): reject package operand source substitution
seonghobae Sep 4, 2026
dcf5c9e
fix(config): fail closed on package source-coordinate drift
seonghobae Sep 4, 2026
3b47849
docs(security): bind package specs to reviewed source identity
seonghobae Sep 4, 2026
e4def8f
docs(changelog): record package source-coordinate binding
seonghobae Sep 4, 2026
66e3173
test(architecture): include artifact source identity domain module
seonghobae Sep 4, 2026
debcc26
test(admission): expose npm transitive dependency widening
seonghobae Sep 4, 2026
395bfe7
fix(admission): fail closed on npm resolver widening
seonghobae Sep 4, 2026
b7ae0d8
fix(admission): reject unreviewed npm dependency closure
seonghobae Sep 4, 2026
a2dc368
test(admission): bind npm closure failure to artifact authority
seonghobae Sep 4, 2026
afc1268
test(admission): keep exact allow on non-resolving package path
seonghobae Sep 4, 2026
f3a3bea
test(admission): keep audited allow on cargo path
seonghobae Sep 4, 2026
d5a5c4a
test(admission): separate pnpm hook hardening from closure authority
seonghobae Sep 4, 2026
26abebb
test(admission): keep npm source identity distinct from closure approval
seonghobae Sep 4, 2026
c19aadc
docs(admission): record npm-family dependency-closure boundary
seonghobae Sep 4, 2026
1f4cc25
docs(admission): operationalize npm dependency-closure denial
seonghobae Sep 4, 2026
55e8952
docs(admission): model npm transitive resolver authority
seonghobae Sep 4, 2026
96f5f28
docs(admission): trace npm-family dependency-closure decision
seonghobae Sep 4, 2026
032d74e
test(security): reject disabling PyPI hash checking
seonghobae Sep 4, 2026
4c0de8a
fix(security): identify disabled pip hash requirement
seonghobae Sep 4, 2026
bba656c
fix(security): fail closed on disabled pip hash checking
seonghobae Sep 4, 2026
a93f7e7
docs(security): record pip hash-mode denial
seonghobae Sep 4, 2026
3f3da03
docs(doctoring): trace PyPI hash-mode authority
seonghobae Sep 4, 2026
f688907
chore: integrate protected main into artifact admission
seonghobae Sep 4, 2026
a618bd3
style(admission): apply rustfmt to crate facade
seonghobae Sep 5, 2026
2397960
style(admission): apply rustfmt to intent model
seonghobae Sep 5, 2026
266b213
style(admission): apply rustfmt to artifact variant guards
seonghobae Sep 5, 2026
e050c94
style(admission): apply rustfmt to security contract tests
seonghobae Sep 5, 2026
d34abc3
style(admission): format Bun and DDD contracts
seonghobae Sep 5, 2026
6ea20f5
style(admission): format npm security contracts
seonghobae Sep 5, 2026
45d14cd
style(admission): format pnpm and PyPI contracts
seonghobae Sep 5, 2026
f46b068
style(admission): format indirect artifact source tests
seonghobae Sep 5, 2026
24a5748
style(admission): format npm source identity test
seonghobae Sep 5, 2026
379e6e1
style(admission): format PyPI source identity test
seonghobae Sep 5, 2026
750da52
style(admission): format pnpm scope test
seonghobae Sep 5, 2026
16486a8
style(admission): format Yarn workspace test
seonghobae Sep 5, 2026
402cfe2
style(admission): format install root contract
seonghobae Sep 5, 2026
db921e7
style(admission): complete rustfmt repair
seonghobae Sep 5, 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
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,20 @@

### Security

- Added the independently deployable Agent Artifact Admission Controller for authenticated, loopback-only, fail-closed pre-execution package-install admission. Reviewed policy binds workspace manifests and exact artifact ecosystem/name/version/HTTPS registry/owner/SHA-256 evidence, structured argv, minimized append-before-response audit evidence, and deny-all defaults without taking over hostile-workload execution from the quarantine runtime.
- Hardened package-manager command admission so approved artifacts cannot be reinterpreted by a different package-manager ecosystem or widened through alternate package sources, destinations, executable install hooks, parser boundaries, persistent trust mutation, integrity-verification disablement, opaque runtime configuration, or undeclared resolver output: standalone `--` option terminators are rejected so required safety flags cannot move behind a downstream CLI parsing boundary; npm-family commands bind to npm artifacts, pip/uv pip to PyPI, Cargo to Cargo, and Docker/Podman to OCI; npm caller-selected `--userconfig`/`--globalconfig` files and `--ca`/`--cafile`/`--strict-ssl` TLS trust overrides, pip source/root short and long forms, uv index/environment selectors, Cargo registry/Git/path/config/root selectors, npm workspace controls, pnpm `--dir`/`-C` working-directory, filter/recursive/workspace-root selectors, `--config.<key>=<value>` runtime overrides, and pnpmfile hooks not suppressed by `--ignore-scripts`, Yarn Classic `-W`/`--ignore-workspace-root-check`, Bun `--cwd`/`--filter`/`-F` workspace selectors, caller-supplied `--config`, `--trust` persistent `trustedDependencies` expansion, and `--no-verify` registry-integrity bypass, and contradictory lifecycle-script Boolean flags fail closed with stable reason codes. pnpm requests still require both `--ignore-scripts` and `--ignore-pnpmfile` before resolver authority is considered; pip, pip3, and `uv pip install` require exact `--no-deps` so the resolver cannot add artifacts absent from the reviewed intent.
- Fail closed when a pip/pip3 install request includes `--no-require-hashes`: Wardnet's approved PyPI path requires hash-checking mode and does not accept a contradictory installer option that disables automatic hash enforcement alongside the positive requirement. This parser-boundary denial is separate from downstream proof that retrieved bytes match the reviewed artifact digest.
- Fail closed on direct `npm install`, `pnpm add/install`, `yarn add`, and `bun add/install` even when the direct package coordinate and execution-hardening flags match policy, because the v0.1 intent carries only reviewed direct artifacts and cannot prove the transitive dependency closure those commands may resolve. `--ignore-scripts` is execution hardening, not dependency identity. A future npm-family allow path requires a reviewed immutable lockfile/material-set contract plus an executor command that is proven to consume that exact closure without rewriting it; until then resolver-selected transitive artifacts have no Wardnet admission authority.
- Bound registry/index package source identity to the reviewed artifact coordinate: npm/pnpm/Yarn/Bun direct package operands must encode the exact reviewed `<name>@<version>`, and pip/pip3/`uv pip install` operands must encode the exact reviewed `<name>==<version>`. npm aliases, tarball/git/folder package specs and pip direct URL/VCS/local-source requirements cannot inherit approval from a different reviewed registry/index coordinate; unsafe policy drift fails closed during service configuration as well as request admission.
- Bound Cargo install mutation authority to reviewed policy: caller-supplied `-f` / `--force` overwrite capability and `--no-track` metadata/concurrent-install bypass now fail closed as `artifact_not_approved` because the approved artifact coordinate does not authorize replacing existing binaries or disabling Cargo's install tracking/collision protection.
- Bound PyPI approval to the reviewed artifact/build identity rather than caller-selected installer resolution or build variants: pip `--platform`, `--python-version`, `--implementation`, `--abi`, binary/source selectors, build-isolation controls, and `-C` / `--config-settings`, together with the corresponding `uv pip install` target-platform/binary/source/build/backend controls, fail closed as `artifact_not_approved` until policy can bind the selected distribution/build identity explicitly.
- Bound OCI pull approval to the reviewed artifact identity rather than caller-selected client variants: Docker/Podman `--platform` and Podman-equivalent `--arch`, `--os`, and `--variant` selectors fail closed as `artifact_not_approved` until a versioned policy schema can authorize the selected platform-specific manifest identity or equivalent provenance.
- Bound OCI pull cardinality to the exact reviewed artifact set: Docker/Podman `-a` / `--all-tags`, true Boolean assignments, and bundled Boolean shorthand semantics fail closed as `artifact_not_approved` whenever they enable repository-wide mutable tag expansion. This includes `-aq` / `-qa` and assigned bundles such as `-aq=false`, where the preceding `-a` remains enabled; quiet-only shorthand and a final explicitly false all-tags shorthand such as `-qa=false` remain admissible.
- Bound Podman registry transport, authentication, and image-decryption authority to reviewed policy: false forms of `--tls-verify`, caller-selected `--cert-dir` / `--authfile`, inline `--creds`, and `--decryption-key` key/passphrase material fail closed as `alternate_trust_root`, while explicit TLS verification remains compatible with the approved registry identity. Registry credentials and image-decryption secrets remain separately governed downstream deployment/secret authorities rather than untrusted install argv.
- Removed the distributable Kubernetes administrator `Secret` and historical placeholder credential. Production deployments must provision `waf-ids-ai-soc-admin` / `ADMIN_TOKEN` through the external secret-management control plane; the workload's `secretKeyRef` is explicitly non-optional.
- Added a structural regression contract that rejects shipped administrator Secret objects, placeholder credentials, decoy workloads, init-container false positives, and optional administrator Secret references.

### Operations

- Documented administrator credential provisioning, rotation, rollout verification, rollback, evidence handling, and the boundary with the separate runtime-authentication fail-closed work tracked in issue #78.
- Documented Agent Artifact Admission deployment, incident response, immutable policy rollout, audit durability, external provenance authority, package-manager ecosystem binding, package-manager trust/destination/parser controls, package source-coordinate binding, npm-family transitive dependency-closure denial, Cargo overwrite/tracking authority, PyPI artifact/build-variant and dependency-cardinality controls, exact-set OCI pull cardinality, OCI platform-variant and registry transport/authentication/decryption authority, Bun persistent trust and integrity-verification semantics, and current primary-source traceability.
- Documented administrator credential provisioning, rotation, rollout verification, rollback, evidence handling, and the boundary with the separate runtime-authentication fail-closed work tracked in issue #78.
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description = "Rust-first WAF/IDS/AI SOC gateway with DNSBL and commercial readi
license = "MIT"

[workspace]
members = [".", "crates/waf-ids-core"]
members = [".", "crates/waf-ids-core", "crates/agent-artifact-admission"]
resolver = "3"

[dependencies]
Expand All @@ -23,3 +23,4 @@ tower = { version = "0.5", features = ["util"] }
# Property-based testing (MIT OR Apache-2.0); mirrors the cargo-fuzz target for
# parse_admin_tokens so its invariants stay green in primary CI.
proptest = "1"
wardnet-agent-artifact-admission = { path = "crates/agent-artifact-admission" }
17 changes: 17 additions & 0 deletions crates/agent-artifact-admission/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "wardnet-agent-artifact-admission"
version = "0.1.0"
edition = "2024"
description = "Fail-closed package-install admission policy for AI coding agents"
license = "MIT"

[dependencies]
axum = "0.8"
ring = "0.17"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal"] }
url = "2"

[dev-dependencies]
tower = { version = "0.5", features = ["util"] }
283 changes: 283 additions & 0 deletions crates/agent-artifact-admission/src/admission.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
use serde::{Deserialize, Serialize};

/// Immutable admission policy loaded through reviewed configuration.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(deny_unknown_fields)]
pub struct AdmissionPolicy {
/// Stable policy identifier surfaced in responses and audit records.
pub policy_id: String,
/// Immutable policy revision identifier.
pub policy_revision: String,
/// Executables that may be considered for admission.
#[serde(default)]
pub allowed_executables: Vec<String>,
/// Reviewed workspace manifest digests.
#[serde(default)]
pub approved_manifests: Vec<ApprovedManifest>,
/// Exact approved install artifacts.
#[serde(default)]
pub approved_artifacts: Vec<ApprovedArtifact>,
}

impl AdmissionPolicy {
/// Test helper that proves the evaluator blocks when nothing is approved.
pub fn deny_all_for_test() -> Self {
Self {
policy_id: "deny-all".to_string(),
policy_revision: "test".to_string(),
allowed_executables: Vec::new(),
approved_manifests: Vec::new(),
approved_artifacts: Vec::new(),
}
}
}

/// Reviewed manifest identity allowed by policy.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ApprovedManifest {
/// Workspace identifier the reviewed manifest belongs to.
pub workspace_id: String,
/// Exact SHA-256 digest of the reviewed manifest.
pub sha256: String,
}

/// Exact package artifact allowed by policy.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ApprovedArtifact {
/// Package ecosystem, such as `npm` or `cargo`.
pub ecosystem: String,
/// Exact package name.
pub name: String,
/// Exact package version.
pub version: String,
/// Normalized registry URL.
pub registry_url: String,
/// Reviewed package owner or publisher label.
pub owner: String,
/// Exact artifact SHA-256 digest.
pub sha256: String,
/// Exact argv token that names the artifact to install.
pub artifact_argument: String,
}

/// One requested artifact inside an install intent.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ArtifactCoordinate {
/// Package ecosystem, such as `npm` or `cargo`.
pub ecosystem: String,
/// Exact package name.
pub name: String,
/// Exact package version.
pub version: String,
/// Normalized registry URL.
pub registry_url: String,
/// Claimed package owner or publisher label.
pub owner: String,
/// Exact artifact SHA-256 digest.
pub sha256: String,
/// Exact argv token that names the artifact to install.
pub artifact_argument: String,
}

/// Provenance of the instruction that requested the install.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct InstructionSource {
/// Untrusted source category.
pub kind: InstructionSourceKind,
/// Canonical source URI when available.
pub uri: Option<String>,
/// SHA-256 digest of the retrieved source content.
pub content_sha256: Option<String>,
}

/// Untrusted instruction source kinds.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum InstructionSourceKind {
/// `llms.txt` retrieved from a remote origin.
LlmsTxt,
/// `llms-full.txt` retrieved from a remote origin.
LlmsFullTxt,
/// Arbitrary web page content.
WebPage,
/// Issue or PR comment content.
IssueComment,
/// Local reviewed manifest or operator-entered content.
ReviewedConfig,
}

/// Structured install request evaluated before any executor runs it.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct InstallIntent {
/// Stable request identifier supplied by the caller.
pub request_id: String,
/// Identity of the requesting agent or broker.
pub actor_id: String,
/// Workspace or repository identifier.
pub workspace_id: String,
/// Structured operation, limited to install in this slice.
pub operation: String,
/// Tokenized command vector; shell strings are forbidden upstream.
pub argv: Vec<String>,
/// Exact reviewed dependency-manifest digest for the workspace.
pub manifest_sha256: String,
/// Instruction provenance.
pub source: InstructionSource,
/// Exact install artifacts represented in `argv`.
pub artifacts: Vec<ArtifactCoordinate>,
}

impl InstallIntent {
/// Test helper representing an untrusted `llms.txt` package suggestion.
pub fn unowned_llms_package_for_test() -> Self {
Self {
request_id: "req-test-0001".to_string(),
actor_id: "agent:codex:test".to_string(),
workspace_id: "ContextualWisdomLab/wardnet".to_string(),
operation: "install".to_string(),
argv: vec![
"npm".to_string(),
"install".to_string(),
"@unowned/example@1.2.3".to_string(),
"--ignore-scripts".to_string(),
],
manifest_sha256: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
.to_string(),
source: InstructionSource {
kind: InstructionSourceKind::LlmsTxt,
uri: Some("https://example.invalid/llms.txt".to_string()),
content_sha256: Some(
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb".to_string(),
),
},
artifacts: vec![ArtifactCoordinate {
ecosystem: "npm".to_string(),
name: "@unowned/example".to_string(),
version: "1.2.3".to_string(),
registry_url: "https://registry.npmjs.org".to_string(),
owner: "Unowned".to_string(),
sha256: "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
.to_string(),
artifact_argument: "@unowned/example@1.2.3".to_string(),
}],
}
}
}

/// Deterministic allow/block result returned to the caller.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AdmissionDecision {
/// Original caller request identifier or a content-addressed malformed surrogate.
pub request_id: String,
/// Final policy decision.
pub decision: DecisionKind,
/// Stable machine-readable block reasons.
pub reason_codes: Vec<ReasonCode>,
/// Stable policy identifier.
pub policy_id: String,
/// Stable policy revision.
pub policy_revision: String,
/// Normalized source URI when present.
pub normalized_source_uri: Option<String>,
/// SHA-256 of the structured command vector or malformed request body.
pub command_sha256: String,
/// Number of artifacts the caller asked to install.
pub artifact_count: usize,
}

/// Admission outcome.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DecisionKind {
/// The command exactly matches policy.
Allow,
/// The command must not be executed.
Block,
}

impl DecisionKind {
/// Stable string form used by tests and callers that do not deserialize.
pub fn as_str(self) -> &'static str {
match self {
Self::Allow => "allow",
Self::Block => "block",
}
}
}

/// Stable machine-readable block reason.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ReasonCode {
/// The request body could not be parsed as the strict install-intent schema.
MalformedRequest,
/// The authenticated request body exceeded the configured materialization limit.
RequestBodyTooLarge,
/// A bounded identifier, argument vector, source field, or count was invalid.
InvalidRequest,
/// The structured operation was not the supported install operation.
InvalidOperation,
/// The reviewed workspace manifest digest was malformed.
InvalidManifestDigest,
/// One or more artifact coordinates were malformed or unpinned.
InvalidArtifact,
/// Duplicate artifact identities or artifact argument tokens were supplied.
DuplicateArtifact,
/// No exact approved artifact matched the requested install.
ArtifactNotApproved,
/// No reviewed manifest matched the workspace digest.
ManifestNotApproved,
/// The executable is not on the explicit allowlist.
ExecutableNotAllowed,
/// The request omitted an executable.
MissingExecutable,
/// The request omitted a required remote source URI.
MissingSourceUri,
/// The request omitted a required source content digest.
MissingSourceDigest,
/// The request used an insecure or malformed source URI.
InvalidSourceUri,
/// The command path is forbidden even if otherwise allowlisted.
ForbiddenCommand,
/// The command attempted to introduce an alternate package trust root.
AlternateTrustRoot,
/// The command attempted to install outside the executor-selected workspace root.
AlternateInstallRoot,
/// The package manager invocation omitted a mandatory hardening flag.
MissingSafetyFlag,
/// Durable audit evidence could not be persisted before returning a decision.
AuditUnavailable,
}

impl ReasonCode {
/// Stable string form used by tests and audit sinks.
pub fn as_str(self) -> &'static str {
match self {
Self::MalformedRequest => "malformed_request",
Self::RequestBodyTooLarge => "request_body_too_large",
Self::InvalidRequest => "invalid_request",
Self::InvalidOperation => "invalid_operation",
Self::InvalidManifestDigest => "invalid_manifest_digest",
Self::InvalidArtifact => "invalid_artifact",
Self::DuplicateArtifact => "duplicate_artifact",
Self::ArtifactNotApproved => "artifact_not_approved",
Self::ManifestNotApproved => "manifest_not_approved",
Self::ExecutableNotAllowed => "executable_not_allowed",
Self::MissingExecutable => "missing_executable",
Self::MissingSourceUri => "missing_source_uri",
Self::MissingSourceDigest => "missing_source_digest",
Self::InvalidSourceUri => "invalid_source_uri",
Self::ForbiddenCommand => "forbidden_command",
Self::AlternateTrustRoot => "alternate_trust_root",
Self::AlternateInstallRoot => "alternate_install_root",
Self::MissingSafetyFlag => "missing_safety_flag",
Self::AuditUnavailable => "audit_unavailable",
}
}
}
Loading
Loading