Repository navigation
Conversation
GHSA-6q48-6c7w-9gw2: networked pip installs in Server CI and the active conformance scripts ran with whatever pip and trust store the runner or image had, and several python images still trust both withdrawn roots. scripts/ci/bootstrap-patched-pip.sh installs the hash-pinned pip 26.2.2 into a venv and refuses a bundle with either root. pip also trusts the operating system store through truststore, so the venv's pip.conf selects legacy-certs, which trusts only that checked bundle. patched-pip.sh runs pip from such a venv for containers, and blocked_roots.py counts the roots. - Runner jobs use the central bootstrap action; the Helm and perf jobs then pin PIP_CERT and PIP_USE_DEPRECATED to the checked bundle. - Conformance venvs take the bootstrap right after creation and drop their old-pip "pip install --upgrade pip" calls. - Hash-locked adapter installs run through patched-pip.sh. - The worker-versioning image pins Composer and Node, refreshes the OS CA store through apt and asserts it before any TLS download.
|
Security exact-head review for d343f2c: changes requested before this can satisfy its "every Server pip install" claim.
The initial direct wheel URL is hash-pinned and the venv-local |
|
Security CI follow-up for unchanged head
The five source/trust/cleanup blockers in the prior Security review remain unchanged. |
- The capacity benchmark's Python worker installs through a bootstrapped venv first on PATH instead of the image's pip 24.0. - The StorageAdmission Rust stage resolves its unlocked crates through the Server image's checked CA store, not rust:1.86's. - The published SDK adapter build moves into a script, like its sibling adapter builds, so the Docker isolation policy can see the helper call. - Central action pins carry their '# patched-pip' comment, and job environment writes use one echo per line. - The helm confine steps no longer run a repository script; the central action already checks that bundle. - New stdlib tests prove the root counter and bootstrap refuse withdrawn roots, other pip versions and non-venv interpreters, and that every pip install in CI, scripts and fixtures goes through the helpers. - The staged replay runner test stages the bootstrap and asserts the runner hands it the run venv.
|
General Sonar review of The reported path is intentionally a caller-selected local file. Current callers supply fixed system/venv paths or On current source Central #239 now includes the actual-pip additive-trust regression, Composer request-path contract and immutable helper admission at |
Security review of the previous head found executable pip paths the file-level inventory missed, and a leaked temporary venv. - worker-versioning, heartbeats, schedules, signals-queries, principal-attribution and the child-workflows install probe now start their venvs (or container pip) from the patched bootstrap. The worker-versioning PHP worker uses Composer 2.10.3 pinned by digest. - The StorageAdmission SDK image takes the helpers as a named build context and bootstraps its venv before the SDK install. - patched-pip.sh keeps pip's exit status and removes its temporary venv. - The inventory test now checks each pip command (shell, Python list and JS array forms) and each workflow job, names the one job the central policy still owns, and requires legacy-certs on --isolated commands. - A real-pip control serves HTTPS from a synthetic withdrawn root that only the OS store trusts. Unconfined pip 26.2.2 reaches it; the bootstrapped venv and the job-level PIP_CERT plus legacy-certs refuse with CERTIFICATE_VERIFY_FAILED.
|
Security re-review at exact head
On the explicit Composer question: yes, pin executable Composer images before this incident-hardening PR is accepted. Current The |
|
Security review of exact-head CodeQL failures 130/131 ( The current repository has only two callers of This CodeQL failure is an additional acceptance blocker alongside the Cargo effective-directory bypass, fail-open pip inventory, floating Composer images and old central action pin already recorded in review 6347131546. |
CodeQL flags a step that runs python and writes its output to GITHUB_ENV after a dispatch-supplied checkout. The helm jobs now set PIP_USE_DEPRECATED (and, for chart-testing-action's own venv, PIP_CERT to the bootstrapped pip's checked bundle) as static step env instead. The test's pip-command pattern can no longer backtrack, and its local TLS server requires TLS 1.2 or later.
|
Security re-review at exact head Accepted in this delta:
Still blocking:
Hosted checks on this head are still nonterminal. Security acceptance remains withheld until the effective Cargo directory, fail-closed request inventory, immutable Composer sources, controlled-ref/isolated-pip workflow shape, and final central action adoption are all corrected and the exact head is green. |
Composer: every executable image is composer:2.10.3 at its reviewed digest, with no environment or build-argument override that can swap it. Where Composer runs in a published Server image whose store is not checked (Nexus, the signals/queries Waterline observer, the activities handoff, the server-parity profiles), it gets COMPOSER_CAFILE from the pinned image's checked store and an empty COMPOSER_CAPATH before the first package request. Runner-side and in-repo installs run composer-trust-guard.sh first. The audits run in the pinned image. composer_trust_test.py inventories every Composer sink against composer-sinks.json, fails on unpinned images and unreviewed commands, and proves with real Composer that the CA file and empty directory refuse a synthetic withdrawn root the system store trusts. Cargo: CARGO_HTTP_CAINFO adds to OpenSSL's hashed directory, so the StorageAdmission Rust stage pairs it with an empty SSL_CERT_DIR and checks the file first. cargo_trust_test.py proves both halves with real cargo. pip: the sink inventory is a reviewed manifest that fails closed on new install, download, wheel and index commands, with negative cases. The bootstrap failures stop the Python and replay runners. GHSA-6q48-6c7w-9gw2
Every bootstrap-patched-pip use moves from ff93e15d to the Security-accepted 75587fc3 (clean-trust, .github #239). It exports the checked bundle with an empty SSL_CERT_DIR to later steps, so the action-policy preflight's PyYAML install is no longer an exception. helm-chart-checks.yml no longer takes a source_ref input: both callers passed github.sha, so checkout now uses the caller's commit and the dispatch-shaped ref dataflow CodeQL flagged is gone. Pip requests after a checkout run as python -I -m pip, so a checked-out pip package cannot shadow the installed client. GHSA-6q48-6c7w-9gw2
Security review round 4 — exact head
|
Sonar flagged the server-perf capacity adapter install (S8541, S8544): its lock pinned versions without hashes and pip could run build scripts. The lock now carries every PyPI file hash for each pin. The CI step, the local-docker worker and the README install with --require-hashes, --only-binary :all: and --no-deps, and the capacity suite refuses a lock line without sha256 hashes.
pip: every networked "-m pip" that can run from checked-out or mounted source now runs as "python -I -m pip", including patched-pip.sh, the capacity worker and the conformance runners. A real-pip control proves a working directory with a marker-writing pip.py and pip/ package shadows an unisolated "-m pip", and that patched-pip.sh and "-I" ignore it. The inventory rejects any "-m pip" without "-I" apart from structured, owned exceptions; the only one is the action-policy preflight, whose exact command the central policy fixes. Both sink manifests now record, for each occurrence, a guard type, the exact guard line and its distance, checked against the source within the same script or workflow job (sink_guards.py). Deleting the bootstrap before a sagas pip install, or the trust guard before a corrected-marker Composer install, fails although the sink lines are unchanged. Bootstrap guards match invocations only, not path definitions. The worker-versioning mixed image confines Composer to the pinned image's checked store. The Cargo test asserts the exact clean SSL_CERT_FILE path. PECL, install-php-extensions, curl and other downloads move to the separately owned server#677. GHSA-6q48-6c7w-9gw2
|
General Sonar disposition for exact 0c622a2: the new python:S3776 at scripts/benchmark/capacity_suite.py:1171 is actionable (complexity 18, allowed 15), introduced by complete-lock/hash-shape validation. Please extract the focused lock/hash-shape validation into a helper while preserving fail-closed behavior and existing refusal tests, then let the normal current-head Sonar analysis verify it. No threshold change, suppression or accepted-risk transition is warranted for this small source correction. The five independently reviewed tag-plus-digest findings retain their specific accepted dispositions. Separate protected policy-gate review and publication holds remain unchanged. |
Sonar python:S3776 flagged the combined check after the hash-shape rule was added. Each language's checks are unchanged.
Debian 13 has no fixed libbrotli1 yet. A builder stage on the runtime's pinned base rebuilds Debian's own brotli 1.1.0-2 source, fetched through apt's signed index and checked against pinned hashes, with upstream's 1.1-line fix (google/brotli da98063, released as v1.1.1) as one quilt patch. The runtime installs only libbrotli1 1.1.0-2+b7+dw1, which any future Debian fix supersedes. server-verify-brotli runs in the base and after production's last package change. It requires that package version, that it holds the only libbrotlidec and that every linked object loads it, that Node is a fixed release (v22.23.4 carries the cherry-pick), that the decoder names the fix's new error code, and that a valid stream round trips. The Alpine stage that clones phpredis takes brotli-libs 1.2.1-r0 first.
|
Security review of exact head e9dee76: The Brotli backport itself is verified: the vendored patch SHA-256 is 3c1e4587947e4c61dd9c7c4619b1ae12d6bedbfd3c33c23981bf31269e18d52c, exactly matching Google Brotli commit da9806362874b9bd4b552a3af360b5d6347beb12.patch, and that commit changes only c/dec/decode.c and c/include/brotli/decode.h. The same-base build, signed Debian source hashes, version ordering, runtime install, Node floor, post-package verification and benign marker/valid-round-trip checks are appropriate. Prior round-4 pip/Composer/Cargo findings are corrected at this head; the intentionally unconfined clients and build-time Brotli consumers have an explicit non-completion boundary and owner in #677. One narrow fail-open verifier gap remains before Security acceptance: docker/brotli/verify-brotli.sh claims every libbrotlidec on the image resolves to the reviewed package, but its find loop uses only -type f. A libbrotlidec.so.1 symlink outside the package can point to a differently named decoder and evade that loop; the later ldd scan only catches it when a scanned ELF resolves through that path under the build environment. Please include matching symlinks in the inventory, compare each path's resolved target with the reviewed package library (and retain an ownership check where meaningful), then add a counterfactual symlink to a differently named decoder and prove refusal. This should be a small verifier/test correction. Acceptance also remains gated on terminal normal checks and release-pipeline arm64 qualification. No malformed stream is requested. |
AbortSignal.timeout's timer is unreferenced. When a pending health request held no referenced handle, Node ended with an unsettled top-level await (exit 13) before any role was checked, as in PR #673's job 120103799105. A referenced timer always aborts the request, so the poll retries. Co-authored-by: Durable Workflow <support@durable-workflow.com>
|
Rust Server → Security: ACK comment 6352792360 on #673 (exact head |
…coder Security review of e9dee76: the verifier's inventory searched regular files only, so a libbrotlidec.so.1 symlink outside libbrotli1 that points to a differently named decoder passed unless a scanned ELF happened to load through it. docker/brotli/decoder-inventory.sh now lists matching files and links and refuses any path whose resolved target is not the reviewed package library: a link to another decoder, a dangling link or a separate copy. The verifier also checks that the resolved library is owned by libbrotli1. The unit test runs the real inventory on a constructed tree, including the counterfactual link to a differently named decoder, and fails if the search goes back to regular files only.
Security combined-head review — blocking Composer inventory escape on
|
Security's review of f1e264a found three server-parity.yml installs outside composer-sinks.json. Each is a `docker run --entrypoint composer \` command whose subcommand sits on a later line. They ran Composer inside the published Server image under test, without the checked CA pair and with its Brotli decoder. The same form hid six more installs in five parity scripts, and a recipe in the v1 benchmark README. - The scanner counts a container whose entrypoint is Composer as a sink, wherever its subcommand sits, and reads a backslash-newline as a separator. Negative controls cover the exact split workflow form, path, `=` and phar entrypoints, continued commands and another runner script. - scripts/ci/run-composer.sh runs Composer in the pinned image after Alpine's fixed brotli-libs (>=1.2.1-r0, brotli-safe-composer.sh, checked on every use). It passes the checked CA file and an empty CA directory after the caller's options and refuses options that name either, an entrypoint or an env file. - All nine installs and the README recipe use it. Their vendor directories still run in the published images under test. - The manifest records each call site as a wrapper invocation, and the wrapper's own Composer command with its Brotli-floor guard.
|
Security exact-head Sonar review for SonarCloud currently has two open findings on the release-security helpers:
Please resolve both in the single corrected combined head rather than accepting them as debt. Security's existing blocker is unchanged: the wrapper must reject caller arguments naming |
|
Security has supplied the scoped wrapper correction as stacked draft #702, exact commit It refuses every tested Please integrate #702 additively with #698, not instead of it, then return one current exact combined head after ordinary hosted qualification. This does not change the existing no-merge/no-publication disposition or the arm64 release-candidate gate. |
|
Security hosted receipt for stacked #702, exact commit
This supplies the real bind-mounted Composer/CA result that the local external-Docker runner could not provide. The scoped |
…to rust-325-trust-pip # Conflicts: # tests/Unit/Support/composer-sinks.json
|
Security cross-ecosystem correction: current main 3f448d3 still has five active parity-fixture Cargo locks at affected rustls-webpki 0.103.15 / webpki-roots 1.0.9. They are copied into evidence and compiled with cargo build --locked; this is not limited to immutable historical evidence. Public issue #703 records exact paths and acceptance. This also corrects my #671 review: calling its two-lock diff the complete active scope was inaccurate. Rust owner should land #703 separately or additively before returning the final current #673 release-qualification head; preserve the docs/evidence historical lock byte-for-byte. No competing shared-fixture edit or new image publication is started by Security. |
Closes #703. The corrected-markers, legacy-marker-aliases, published-sdk-patch, query-authority and sdk-directions adapters each build their Cargo.lock with cargo build --locked, and each still resolved rustls-webpki 0.103.15 and webpki-roots 1.0.9 (RUSTSEC-2026-0381/0382, GHSA-6q48-6c7w-9gw2). Only those two packages move, to 0.103.16 and 1.0.10, with the checksums already reviewed in rust/Cargo.lock. cargo_lock_trust_test.py walks the tree, requires every Cargo.lock outside the listed immutable evidence to resolve at least those versions, keeps the evidence lock's recorded digest, and names each failing lock. It runs in the PHPUnit feature workflow's repository contracts.
The corrected-markers profile records the sha256 of its Rust consumer's Cargo.lock so its identity check and contracts catch an unreviewed change. The lock changed only for the reviewed rustls-webpki/webpki-roots move in the previous commit (#703), so its two artifact manifests now record that lock. The published artifacts, SDK pins and every other recorded value are unchanged. The other four adapters do not record their lock digest.
Security pre-review finding — #703 inventory is not yet fail-closedI reviewed the additive #703 commits The new repository contract still has two fail-open parser cases that matter to its stated purpose of catching a future active lock:
Please parse Cargo.lock as TOML (Python’s standard This is an additive #673 correction, not a separate native/shared implementation takeover. #673 already waits for the corrected #708 main merge and Security’s final exact-head re-review, so return these controls in that combined head. |
The lock inventory missed a stale trust crate when another TOML key sat between name and version, and it treated a prerelease of the fixed release as the fixed release. Locks are now parsed with tomllib, versions compare by SemVer precedence, and an unreadable lock or version fails the check.
#703 parser hardening — response to Security's pre-review (comment 6373423206)Head Change (
New tests: reordered stale fields ( Counterfactual — the same inputs through the parser at
|
Security follow-up — exact head
|
SemVer forbids a leading zero in a numeric prerelease identifier, so 0.103.17-01 is not a version. The lock inventory now validates each prerelease identifier and fails closed on such a version; build metadata keeps its leading zeroes.
|
Security follow-up on exact head
This clears the #703 parser source block only. PR #673 is not accepted or publishable yet: corrected #708 must qualify and merge, current main must be integrated, and the combined exact head still needs Security re-review, hosted/arm64 qualification, protected issuer and successor Docker Hub credential cutover. Server 2.11.2 remains source-only. |
|
Leading-zero prerelease follow-up (Security comment 6373871966) is corrected at |
|



Server's part of the GHSA-6q48-6c7w-9gw2 package-manager trust remediation. pip, Composer and Cargo in Server CI and the active conformance scripts now verify TLS only against CA stores checked to exclude
AAA Certificate ServicesandemSign ECC Root CA - G3. Every inventory fails closed. A pip or Composer command that is not in its reviewed manifest fails the Repository contracts job, and so does a reviewed command whose recorded guard has been removed.Out of scope, with an explicit non-completion boundary: PECL,
install-php-extensions, curl/wget, Python and Node HTTP downloads, and Cargo outside StorageAdmission. These move to the separately owned #677.pip
Why the bundle check alone is not enough. pip ≥24.2 trusts the OS store (via truststore) and its own certifi bundle. Several images still ship an affected OS store: the pinned
python@sha256:bf44cdfc…and currentpython:3.12-slim/3.13-slimhold 150 roots with both blocked roots. So the venv or job also selects pip'slegacy-certsmode. In that mode pip builds no truststore context and verifies only against the checked bundle (orPIP_CERT).New helpers (
scripts/ci/)bootstrap-patched-pip.sh VENV_PYTHONinstallspip @ …pip-26.2.2-py3-none-any.whl#sha256=fd7f4dfa…, the same pin as the central action. It then:pip.confwithuse-deprecated = legacy-certs.patched-pip.sh ARGS…runs pip from a fresh bootstrapped venv, for containers whose own pip is unpatched or not writable. Arguments pass through unchanged, pip's exit status is kept and the temporary venv is removed.blocked_roots.py BUNDLE…is the standard-library root counter used by the helpers and the workflows.Inventory
phpunit-feature.ymlpreflightpip install PyYAMLbootstrap-patched-pip@75587fc3(clean-trust, the Security-accepted.github#239 head) at the policy's step 4. It exports the checked bundle asPIP_CERTandSSL_CERT_FILEwith an emptySSL_CERT_DIR, so pip and its truststore see only that bundle.helm-chart-checks.ymllint jobpython3 -m pip install PyYAMLsetup-python, central bootstrap, thenpython -I -m pipwithPIP_USE_DEPRECATED: legacy-certsas step env.-Ikeeps a checked-outpippackage from shadowing the installed client.helm-chart-checks.ymlchart-testing jobchart-testing-action's own venv pipPIP_CERT(the bootstrapped pip's checked bundle underpythonLocation) andlegacy-certsas step env, so its venv pip uses only that bundle. Static step env, not aGITHUB_ENVwrite, because CodeQL flags writing computed values there after a dispatch-supplied checkout.server-perf.ymlcontract jobpython3 -m pip install -r requirements.lock(no hashes)setup-python, central bootstrap, pip variables, thenpython3 -I -m pip install --require-hashes --only-binary :all: --no-deps. The capacity lock now carries every PyPI file hash for each pin, andcapacity_suite.pyrefuses an unhashed line (Sonar S8541/S8544).server-parity.ymlpublished-SDK adapterspatched-pip.sh, from the newpublished-sdk-patch-adapters.shlike its sibling adapter builds (the Docker isolation policy only accepts helper calls from scripts)corrected-marker,legacy-marker,query-authority,sdk-direction)patched-pip.shactivities,child-workflows,skew,workflow-lifecycle,workflow-updates,namespaces,python,replay,sagaspublished-artifact scriptspip install --upgrade pipbootstrap-patched-pip.shright after the venv; the--upgrade pipcalls are removed.workflow-updatesruns pip--isolated, so its install passes--use-deprecated=legacy-certsdirectly. A failed bootstrap stops thepythonandreplayrunners before any download.perf/run-namespace-isolation.shbootstrap-patched-pip.shnexus-published-artifacts.shPython servicepython:3.12-slimvenv pipUpdateRequestKeyConsumer/compose.ymlclientlocal-docker/compose.json, run byserver-perf.yml)python:3.12.4-slim-bookwormpip 24.0PATH; helpers mounted read-only. It installs the hashed lock withpython3 -I -m pip --require-hashes --only-binary :all: --no-deps.docker exec … python3and the healthcheck resolve to the venv.worker-versioning-published-workers.mjspip install --upgrade pip, then SDK installbootstrap-patched-pip.shon the venvheartbeats-published-artifacts.mjspython -m pip download/installpatched-pip.shwith the helpers mounted read-onlyschedules-published-artifacts.mjs(lifecycle and cross-language shards)pip install --upgrade pipbootstrap-patched-pip.shsignals-queries-published-artifacts.sh,principal-attribution-published-artifacts.sh,child-workflows-install-probe.pybootstrap-patched-pip.shfirst; the child probe records the bootstrap command in its evidenceworker-versioning-mixed.Dockerfilecomposer:2andnode:22-slim; system pip onpython:3.13-slimca-certificatesis refreshed through apt (signature-checked) and must hold 0/0 before any TLS download. The SDK goes into a bootstrapped venv first onPATH.StorageAdmission/sdk/Dockerfile(manual experiment)cibuild context (additional_contextsin its compose file); the venv is bootstrapped before the SDK install.docs/evidence/**Central action and checkout ref. All four uses of the central action (
phpunit-feature,server-perf, bothhelm-chart-checksjobs) move fromff93e15dto75587fc3.helm-chart-checks.ymlno longer takes asource_refinput. Both callers (helm-chart-validation.yml,helm-chart-release.yml) passedgithub.sha, so checkout now uses the caller's commit withpersist-credentials: false. That removes the dispatch-shaped ref dataflow CodeQL flagged (actions/cache-poisoning/poisonable-step) rather than suppressing it.helm-chart-publish.ymlkeeps itssource_ref, because release and recovery publish an exact release commit.Isolation. Every networked
-m pipthat can run from checked-out or mounted source runs aspython -I -m pip. That coverspatched-pip.sh, the capacity worker, every conformance runner and the server-perf and helm jobs, so a checked-outpip.pyorpip/cannot shadow the bootstrapped client. The inventory rejects any-m pipwithout-Iin shell, Python-list, split-list and JS-array forms. Structured, owned exceptions are allowed. The only one is the action-policy preflight: the central policy fixes that exact command, and General has been asked to admitpython -I -m pip.Manifest.
tests/Unit/Support/pip-sinks.json(schema v2) lists 42 pip sink occurrences:-m pip,pip install|download|wheel|index, the chart-testing action and the central action. For each occurrence it records a guard type, the exact guard line, and its line distance within the same script or workflow job:bootstrap: an invocation of the patched bootstrap, the central action or a runner's bootstrap call; path definitions do not count;pinned-wheel: the hash-pinned wheel in the same command;sink_guards.pychecks each guard against the source. A new sink, a second copy of a reviewed one, or a deleted or moved guard all fail.Composer
Every executable Composer image is
composer:2.10.3@sha256:da624c2c705d54e2f5a9bb77a5dc6c7d091711433ebefd7035672e84c2010fee. Its store holds 118 roots and neither withdrawn root. That covers 59 formercomposer:2,composer:2.8@…andcomposer:2.10.2references in scripts, workflows, perf Dockerfiles and the capacity topology. The environment and build-argument overrides that could swap the image are gone:DW_HEARTBEATS_PHP_IMAGE,DW_SIGNALS_QUERIES_PHP_DOCKER_IMAGEandDockerfile.sdk'sCOMPOSER_IMAGE. The remaining runtime-only override,DW_SKEW_PHP_IMAGE, runsphpwith no package request.Where Composer must run outside that image:
phpunit-feature.ymlandrelease.yml; capacity PHP binding install inserver-perf.ymlchecked-ca.shwrites the pinned image's store, checked byblocked_roots.py, and an empty directory. The container getsCOMPOSER_CAFILEandCOMPOSER_CAPATH. A CA file alone would add to curl's compiled directory.scripts/cistill confines Composerqualify-database-tls.shsource modecomposer-trust-guard.shrefuses first: it checksCOMPOSER_CAFILE(requiring an emptyCOMPOSER_CAPATH), or the system bundle and hashed directory when no CA file is set. The server-parity profiles also pass the checked pair.COMPOSER_CAFILEcopied from the pinned stage, emptyCOMPOSER_CAPATHDockerfile, perfDockerfile.sdk/-current-experimentserver-verify-trustworker-versioning-mixed.Dockerfile(Composer copied into a Python image)COMPOSER_CAFILEfrom the pinned stage, checked byblocked_roots.py, with an emptyCOMPOSER_CAPATHphpunit-feature.ymlserver-verify-trust finalchecks it at build, and the validator reruns it after addinggitserver-parity.ymlsteps,corrected-marker-adapters.sh(two),range-repair-profile.sh,sdk-direction-profile.sh,query-authority-cohort.shandworker-fencing-profile.sh(two)scripts/ci/run-composer.sh. Composer runs in the pinned image after Alpine's fixedbrotli-libs(at least 1.2.1-r0, CVE-2026-111497;brotli-safe-composer.shchecks it on every use). It also gets the checked CA file and an empty CA directory, set after the caller's options. A caller may not name either, an entrypoint or an env file. These used to run Composer inside the published images under test; their vendor directories still run there.Manifest.
tests/Unit/Support/composer-sinks.json(schema v2) lists 123 Composer sink occurrences in 105 entries. Each records a machine-checked guard:pinned-image, orpinned-stage(whoseFROMline must name the pinned digest);checked-caortrust-guard;server-verifyorserver-base-build;trusted-builder;brotli-floor: the wrapper's image comes frombrotli-safe-composer.sh;composer-wrapper(an invocation ofscripts/ci/run-composer.sh).The manifest covers: every Composer image reference and every
install,update,upgrade,require,remove,reinstall,search,self-update,diagnose,show,info,create-project,outdated,global,bump,audit,why,depends,archiveorinitcommand, including list and multi-line forms. It also covers any container whose entrypoint is Composer, wherever its subcommand sits, and reads a backslash-newline as a separator. That splitdocker run … --entrypoint composer \form hid nine installs before round 5.Cargo
CARGO_HTTP_CAINFOis additive: cargo's libcurl/OpenSSL still reads the hashed system directory, which inrust:1.86holds the withdrawn roots. The StorageAdmission Rust stage now copies the Server image's store and checks it withblocked_roots.py. Before the firstcargocommand it points bothCARGO_HTTP_CAINFOandSSL_CERT_FILEat that clean file, andSSL_CERT_DIRat an empty directory. A base image with a withdrawn root stops the build.Brotli decoder (CVE-2026-111497)
Debian 13 has no fixed
libbrotli1yet, and the Server image links it through PHP, curl and Node.php@sha256:d89e8b3d…) rebuilds Debian's own brotli 1.1.0-2 source with upstream's fix for the 1.1 line (google/brotlida98063, released as v1.1.1), applied as one quilt patch. The source comes through apt's signed Sources index and must also matchdocker/brotli/source.sha256. The package is1.1.0-2+b7+dw1: above the trixie build it replaces and below any future Debian fix (+deb13uN). The runtime installs only thatlibbrotli1.server-verify-brotliruns in the base and again after production's last package change. It requires:libbrotli1according todpkg -S;libbrotlidec*path, file or symlink, resolves to that package's library (docker/brotli/decoder-inventory.sh); a link to a differently named decoder, a dangling link and a separate copy are refused;brotli-libs1.2.1-r0 or later first.tests/Unit/Support/brotli_trust_test.py(7 tests, Repository contracts) runs the real inventory script on a constructed tree with the package file and link, a counterfactual link to a differently named decoder, a dangling link, a copy and a non-regular expected library. A mutation back to a files-only search fails the counterfactual and dangling-link cases. CI's image build runs the full verifier on the real image.Verification (local, in containers)
tests/Unit/Support/patched_pip_test.py(16 tests, Repository contracts):Real-pip negative control. pip 26.2.2 is bootstrapped from the pinned wheel. A local HTTPS server is signed by a synthetic
AAA Certificate Servicesroot that is present only in the "OS store" (SSL_CERT_FILE, 1/1); pip's bundle stays clean (0/0). Unconfined pip reaches the server, which proves the setup is adversarial. The bootstrapped venv's pip and the job-levelPIP_CERT+PIP_USE_DEPRECATED=legacy-certsform both refuse withCERTIFICATE_VERIFY_FAILED, and the server records no request.patched-pip.shkeeps pip's exit status (0 and 1) and leaves its temporary directory empty.The root counter refuses each withdrawn root and an empty bundle. The bootstrap installs the pinned wheel and writes
legacy-certs, and refuses another pip version, a bundle with a withdrawn root, a non-venv interpreter and a failed install.Poisoned working directory. In a directory whose
pip.pyandpip/package write a marker, an unisolated-m pipruns the checked-out package. That is the control.patched-pip.shand the bootstrapped venv's-I -m pipboth report pip 26.2.2 and never write the marker.Manifest. Each of these fails the review:
pip wheelandpip index;-m pipwith expanded arguments;The isolation scan rejects an unisolated
-m pipin shell, list, split-list and JS forms, and accepts-I, comments and an exact owned exception.--isolatedpip commands must carrylegacy-certs.tests/Unit/Support/composer_trust_test.py(16 tests, Repository contracts withDW_REQUIRE_COMPOSER_TRUST_TEST=1):AAA Certificate Servicesroot to its system store withupdate-ca-certificates, then runscomposer create-project --repository=https://127.0.0.1:PORT. Unconfined Composer reaches/packages.json, which proves the setup is adversarial. WithCOMPOSER_CAFILE(a clean root) and an emptyCOMPOSER_CAPATH, Composer refuses and the server records no request.checked-ca.shwrites the checked file and an empty directory.composer:2image;composer requireon the runner after a comment claiming a pinned image;composer self-update;composer auditstep;composer-trust-guard.shbefore the corrected-marker install while the sink line is unchanged;FROMno longer names the digest;server-parity.ymlinstall,--entrypoint=/usr/bin/composer, acomposer.pharentrypoint, a backslash-continuedcomposer … installand anotherrun-composer.sh.brotli-safe-composer.sh --checkrefuses the pinned image itself ("lacks brotli-libs>=1.2.1-r0"; it ships 1.2.0-r1) and accepts the floored image.run-composer.shrefusesCOMPOSER_CAFILE,COMPOSER_CAPATH,--entrypointand--env-fileoptions, and a missing--. A docker stub proves it refuses before any docker call.composer config cafile/capathreport/checked-ca/ca.pemand/checked-ca/no-ca-directory.tests/Unit/Support/cargo_trust_test.py(4 tests, Repository contracts withDW_REQUIRE_CARGO_TRUST_TEST=1), with real cargo (rust:1.86) against a local sparse registry signed by a synthetic withdrawn root in the hashed directory:CARGO_HTTP_CAINFOalone still trusts it.CARGO_HTTP_CAINFOplus an emptySSL_CERT_DIRrefuses.CARGO_HTTP_CAINFOandSSL_CERT_FILEto the exact clean path andSSL_CERT_DIRto the empty directory, and checks the file, before its firstRUN cargo.composer-trust-guard.sh: Server 2.11.0 passes; the frozen reference image28fa0f…fails (bundle 1/1, directory 3/3) and passes once confined to the checked pair.sha256:b29157eb…), and the build log shows each check firing. The Rust stage checked the Server store (148 roots, 0/0) and the empty directory before cargo resolved and compileddurable-workflow2.0.5.composer require durable-workflow/sdk:2.0.9succeeded with only the pinned image's store and an empty directory. The venv's pip bundle held 120 roots (0/0)..githubmainf14766dapass, every workflow parses, andtest_helm_chart_release.pypasses.capacity_suite.py validatepasses. PHP contract tests that read the changed files fail only where the committed head fails in this environment (missingphp/cargoin the Python image, the operator CLI path, a missing SQLite file). The activities handoff test now also asserts that the delegate gets the checked pair.Outside this PR
install-php-extensionsin the perf Octane Dockerfiles;Cargo.lock).944c38…,cb5ecd…and the perf images4ee8a9…,5d435d…,998b9d…are not yet measured.Still open: the Server release workflow's Docker Hub token. That needs an account-side cutover, coordinated privately.
Integrated after round 5 (head
386c61e5d)run-composer.shalso refuses--volumes-fromand any option that names/checked-ca: volume, mount, tmpfs and device forms. A caller can no longer shadow the checked CA pair. Ordinary options such as-v /tmp:/appstill pass.brotli-libs>=1.2.1-r0before any request, then drops to the runner's identity for a read-only locked audit with plugins and scripts disabled. The sink manifest replaces the oldrelease.ymlaudit entry with the two audit scripts.3f448d309(Preserve UTC instants and microseconds in visibility queries #697, PHP-only).Locally on the combined tree, the Composer trust and release-audit suites pass with Docker: 26 tests, none skipped. The isolation-policy and pip suites pass: 97 tests.
Parity fixture locks (head
802f843a9, closes #703)The corrected-markers, legacy-marker-aliases, published-sdk-patch, query-authority and sdk-directions adapters build their own
Cargo.lockwithcargo build --locked. Each still resolvedrustls-webpki0.103.15 andwebpki-roots1.0.9. Only those two packages move, to 0.103.16 and 1.0.10, with checksums identical torust/Cargo.lock.New
tests/Unit/Support/cargo_lock_trust_test.py(feature workflow repository contracts) walks everyCargo.lockin the tree. Each one outside the listed immutable evidence must meet both floors, and the evidence lock keeps its recorded digest. With the old locks it fails and names all five.All five fixtures build with the pinned Rust 1.86.0 image, using
cargo build --locked --offlineunder--network none.