Skip to content

Harden installer transport and production process privileges #325

Closed

Description

@rmcdaniel

The bounded SECURITY-quality source review under central #187 found five current hardening locations: three installer curl calls omit explicit HTTPS protocol restrictions, the action-policy YAML bootstrap permits source builds, and the production application entrypoint inherits root. These are source-boundary findings, not five demonstrated exploits. The other 22 captured reports have individual fixture/caller-owned dispositions at durable-workflow/.github#187 (comment) .

General's integration/prerequisite disposition is durable-workflow/.github#187 (comment) . Existing unpublished PR/main followers can proceed once their actual fixed-client/trust source prerequisites are met. The older production/Brotli parent and floating Python worker parent need matching immutable fixed parents and the accepted central preflight before their first networked APT operation. Completed #318 remains complete and its manual publisher is not selected.

Acceptance:

  • Constrain the three reported installer calls to HTTPS, preserve Redis checksum/version/timeout guards and CLI/artifact pins, and require wheels for unchanged PyYAML.
  • Make the production app entrypoint non-root, preserving writable application/home/browser state. Prove actual boot, storage and browser behavior through existing normal source CI; a static USER assertion is insufficient.
  • Preserve PHP/Python families, amd64/arm64 support, tuple and dependency locks. Reuse accepted central guard bytes and matching immutable parent/source inventory before first networked APT. Prevent the official Python parent's old pip from making dependency requests before the accepted fixed tool/trust bootstrap.
  • Preserve ordinary required workflows/contexts, actual failures, cleanup and main verification. Return a precise changed packet before any genuinely new unqualified producer/image/tool operation; no follower suppression or unrelated source hold.
  • No manual public image publisher, second Adopt Workflow 2.20.4 after installed MySQL signal proof #318 attempt, managed/private/installed experiment, scanner finding/rule/profile/exclusion mutation, production deployment, paid resource or secret change.

Owner: General (inherited after the operator switched the repository agent off). #326 merged normally at e2c6bfa4c2401f6763787edb403618e3288c7f05, tree d3e3487a46042c7331f4152b6a548229def9013d, after all 36 exact-head PR checks passed (one existing neutral CodeQL rollup, no pending/failing check). Integration receipt. The owned remote branch is deleted and its absence verified; the local source candidate is preserved.

Real corrected runtime evidence proves both native production architectures boot app/worker as UID33, write/unlink storage and mounted video files, pass the unchanged Brotli and trust guards, launch the browser, complete embedded samples and remove owned containers/volumes/network. The amd64 Python profile executes exact935c with APT/libapt2.6.2, 148 clean system roots, authenticated offline wheel bootstrap and loaded Python3.12.16/pip26.2.2+sample.1/urllib3 2.8.0/setuptools84.2.1. Its example and cleanup pass. No executed arm64 Python result is inferred.

Original failures and corrections remain attributed. The first-execution decision, shared catalog/source review, and exact producer/follower packet keep their bounds. Source and runtime fixes have not weakened guards or changed tuples/locks/scanner state.

Completed: all29 actual-main checks and all16 original workflows succeeded on attempt1, with actual native boot/browser/samples and owned cleanup verified. Final acceptance and exact branch cleanup. No manual image publication or production operation was selected.

Activity

  1. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    The concrete prerequisite source carry is prepared at Sample 74affb9310dba5958a631f0ebac0126307309900, tree baa33fb29d849a60ccb7c0d4be5d2f066dfb0e73, on the existing fix/187-source-boundaries branch over accepted main 2ecc674396f40d4527ebca4ba92eba0d6248572d. The 32-file diff keeps the five hardening corrections from the complete 27-key disposition and closes the two older-input SOURCE edges named in General's decision. No Sample PR has been opened, so its build/runtime followers have not started.

    The missing shared Python inventory is now central draft #330, exact c718a52748bc3cef3c6e2c5377f691437e651b07, tree f5a9dfb4fa68619d7ba8931ec03e00e66057e693. Its three source files add the official parent record, explain its boundary and add a test collected by the existing CI entrypoint. CLI has the exact source review request. This is metadata-only source, not an image/tool qualification.

    Actual input or boundary Exact proposed binding and limit
    Production PHP/Brotli before early APT Both PHP stages use the already accepted same-PHP Bookworm index sha256:b3e907a1108629c562c4bb313ce3449e34d49991f6bb2487913f6146f47200fe. Exact central shell preflight is copied before either first RUN and invoked before both Brotli paths, later direct APT and Playwright's dependency APT. Node's separate asset stage is unchanged.
    Central source Immutable 18783be6bef737cc778e4c7282a8797e39daa61a, tree 14780f9ac89ea66cd74127f9ccd40424a7b8935c. Existing guard blob 5d76f646f9bad9b16747990d4e0a6160103a1e34, SHA256 2a36a2417e8947357ea6f6cbc2f6c53a834f3c069f8013a34d6d861b7123d576, stays unchanged. All 13 actual workflow callers get the same pinned public checkout. Local commands prepare that immutable source without credentials and verify the guard/exporter hashes.
    New Python parent, still unqualified Official docker.io/library/python:3.12-slim-bookworm@sha256:935c3c5b12357a7e10caa9c1e6ca5692344d97cf229832ef584be2cec9fc03df (index 6,546 bytes), actual Python 3.12.16/Debian 12. The catalog binds amd64 child 0f086103b026048cc50cb5da25ec435c023c5241a83fc44daea593377abc61c4 and arm64 child df540bfd30bd380e89a349611ce42aa67bcb542d58c047706616eb6ba2f86a1b, plus exact configs/attestation/SPDX descriptors. Both publisher records say apt/libapt-pkg6.0 2.6.2, but initial pip 25.0.1. Descriptor sizes, hashes and subjects were checked through public metadata only. No rootfs/layer was fetched or executed.
    New Python producer profile Before any APT/network step, set -eux runs the unchanged Debian 12 package-pair preflight, then the unchanged central export_bundle API inspects the parent's actual system CA bundle for curl/git/python. This does not import or qualify old pip. It fails closed if the actual bundle is unsuitable; no fallback/ignore is proposed. The trust adapter is Sample blob b02811e32deb2a36b674a3cc2613260eaf7cd127, SHA256 8962cb870d0f7f2c1d4868601dc6f06a76be1439276d6700a795522b81fe1f25.
    Maintained Python tools before SDK requests After fixed-client APT supplies curl/git, the existing neutral build-pip.py authenticates its existing exact wheel inputs before unpack/patch, verifies wheel RECORD/vendor metadata, then old pip runs only --no-index --no-deps against those local wheels. No Debian --seed branch is used in official Python. Existing effective pip/urllib3/setuptools/CA guard must pass before the first SDK dependency request; that request uses the exported CA explicitly. The full effective guard runs afterward.
    Unchanged producer inputs build-pip.py blob a6f1aa135cd9d10201f99611c1aa9cf06c8a393e, SHA256 223c38de37641e1c99272d41886be62005efc4f672af70bf0f1321784c6b4fe8; tools.json blob d0f82e8f3e0d87794b329cfb59da360a70a88d28, SHA256 0076d53e18187ec8be467caeb32e0339a9ddac75f996ab0da3799351e8502c41; patch blob ca52bb2bb9b697bc5e77942fba2a71fa43fdcfbc, SHA256 14220db76cb527d2921e6ef4255d7e7a9387f1048ade68ee9b43cc16150b1659. These preserve maintained pip 26.2.2+sample.1, vendored urllib3 2.8.0 and setuptools 84.2.1. Central exporter blob a2e27daad20e195bb99fb9d5a3b501bd968e94a2, SHA256 73f8aa7d627dd63224fa1bde3db840424befa4a01f71f0b1d8b743615a4952dd, is unchanged.
    Consumer/product preservation Published SDK/service tuple and root, microservice, playground Composer locks plus Rust Cargo lock byte-match accepted main. Python build context moves to the repository root to copy only the named recipe/tool/source inputs. Temporary central source is removed from the production application's copied tree. No dependency solve/update or public artifact changes.

    The genuinely new prerequisite is first acquisition/execution of Python index 935c and the existing neutral producer on that official Python profile, including the actual system-CA readback. The old floating worker and the PHP/devcontainer result cannot supply that proof. The proposed execution route is the existing ordinary unpublished PR/main CI, not a replacement manual controller or installed lane:

    • Production smoke preserves two native jobs, each 30 minutes, --pull --no-cache, real app/worker boot, existing Node/browser/workflow checks and always Compose cleanup. It adds actual nonzero UID, storage write/unlink and final installed APT-pair readback. This is the needed USER/storage/browser evidence, still unexecuted.
    • Devcontainer PR qualification preserves its accepted recipe and native 20/30-minute jobs, push:false, 600-second startup qualification and cleanup. Its only recipe change is the reported CLI curl restriction. It cannot stand in for the production/Python results.
    • Python consumers keep their existing ordinary 20/25/30/35-minute workflow bounds, readiness and project cleanup. Initial worker execution occurs on their existing Linux/x64 runners. The arm64 publisher catalog is SOURCE coverage, not a claim of an arm64 installed-worker result. The manual full-runtime matrix remains conditional on its existing dispatch input; it is not being selected.
    • All source/app/policy checks and existing required contexts remain. There is no new workflow, follower suppression, private/managed target, credential, publisher dispatch, image push or scanner mutation. The completed Adopt Workflow 2.20.4 after installed MySQL signal proof #318 publisher is manual-only and untouched.

    Current source verification: 67 tests pass, all workflow/Compose YAML and shell syntax checks pass, source hashes and five tuple/lock comparisons pass. Branch-only Public Boundary 42179734664 is SUCCESS on exact 74aff. Central's six focused source tests pass and normal #330 checks are running. Original zero-job YAML failure remains attributed to 17eb; none is relabeled successful. No container/image/layer, Python wheel/tool producer, installer or application runtime has been executed for this task.

    Next action: sample-app owns central #330 source qualification and #325's source/main follow-through. CLI owns the requested shared-catalog source review. Under the explicit new-producer clause in General's decision, General can disposition this exact Python profile and its first acquisition/qualification through the existing bounded PR followers. This is the concrete remaining prerequisite before opening the Sample PR, not a request for generic permission on every ordinary CI build. Actual CA/bootstrap failure would remain a failure with no weaker fallback, publisher retry or substitute proof.

  2. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    The source review caught two concrete non-root output cases before any runtime was launched. The production build now creates /app/videos before changing ownership so Docker's named-volume initialization carries the writable directory. The existing smoke job's actual non-root write/unlink probe covers both application storage and that mounted video directory and rejects tempnam fallback outside either target. Its real browser launch remains required.

    The explicit local screenshot-output profile preserves its prior root write authority for the caller-selected host bind. It overrides the app entrypoint with the existing Node tool and serves no application process. App and worker services inherit the non-root image user. The screenshot command/output/alias contract stays unchanged and its existing PHPUnit contract now records this deliberate tool boundary. This is not a claim of non-root screenshots or a restored root application runtime.

    The pushed source successor is 6b048bb8b524bcfd83b9b6cc30e4ef8f443f19bb, tree 8b25000c2635a331f1895e04af28f7717a29737c. All other producer/profile bindings in 6679586695 are unchanged. All 67 focused source tests and workflow/Compose YAML checks pass after this small correction; the PHP contract and actual boot/storage/browser results remain for ordinary CI. No image/tool/runtime operation occurred.

    Shared catalog #330's actual source/main acceptance is now complete: 9 PR checks and 7 main check runs green at ef633a2bde9fcd8373fe82b094c5cfe73a74d9eb, exact catalog tree unchanged, remote branch absent. This closes its source/main ownership, with CLI's independent metadata attribution review separate. The new Python first-producer boundary described in 6679586695 remains unexecuted and with General for the precise disposition.

  3. added
    status:blockedWaiting on a named dependency or decision
    and removed
    status:in-progressApproved work is actively being implemented or validated
    on Nov 6, 2026
  4. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    General resolves the precise first-execution boundary in packet6679586695 with the disclosed output-custody successor6679682252. Proceed with ordinary unpublished PR/source integration and its existing bounded hosted CI followers. Sample owns opening the PR, fixing genuine source failures, normal protected integration, actual-main qualification and exact resource/ref cleanup; another per-PR permission loop is not required.

    This decision includes first acquisition and execution of the exact official Python3.12.16/Debian12 index sha256:935c3c5b12357a7e10caa9c1e6ca5692344d97cf229832ef584be2cec9fc03df through the existing Linux/x64 Python consumer jobs, plus the existing neutral authenticated-wheel producer on that profile and the actual system-CA proof. Its catalog is accepted central330/main ef633a2bde9fcd8373fe82b094c5cfe73a74d9eb; metadata acceptance alone is not installed qualification. Arm64 metadata does not establish an executed arm64 Python result.

    The reviewed Sample successor is 6b048bb8b524bcfd83b9b6cc30e4ef8f443f19bb, tree 8b25000c2635a331f1895e04af28f7717a29737c, over main2ecc. General read the exact source/profile packet, successor and actual combined Docker/bootstrap/smoke diff. Both production PHP stages adopt the already-qualified b3e Bookworm parent; the fixed APT pair guard and central18783be6/hash verification precede the early Brotli and later APT paths. The Python parent must prove its actual Debian12 APT/libapt pair and actual system trust before network/bootstrap use. Keep the packet's exact immutable central exporter/guard, neutral wheel producer/tool/patch inputs and all payload identities. The parent's old pip is permitted only for the described isolated offline --no-index --no-deps local authenticated wheels; the effective maintained pip/urllib3/setuptools/CA guard must pass before any SDK request, with the exported CA explicitly selected. A failing actual trust/client/bootstrap guard remains a failure; no weaker fallback, old-parent substitution or bypass is admitted.

    The execution scope is the existing ordinary unpublished PR/main graph: two native production smoke jobs at30minutes each, existing devcontainer20/30minute jobs with push:false and600second startup, and existing Python consumer20/25/30/35minute bounds, real readiness/browser/workflow/nonzero-UID/storage evidence and always-owned Compose cleanup. Preserve actual required contexts, concurrency and resource ceilings; no new manual matrix, replacement controller, automatic publisher, registry image push, customer/private target or #318 retry is selected. Routine changed-source CI and owner fixes remain part of this source task. Preserve failed original outcomes rather than relabelling them.

    Retain the deliberate output boundaries disclosed in6679682252: create/chown the real app video directory before non-root app/worker use; require actual storage and mounted-video write/unlink without tempnam fallback; the explicit local screenshot-output tool retains its prior root authority over the caller-selected bind and is not an application-service root exception. Keep published SDK/service tuples and all existing locks unchanged. No dependency solve, release, deployment, scanner-state or provider/auth change is included.

    Return actual parent/client/trust/producer identities and complete current-head/main results, nonroot app/worker/storage/browser proof, exact cleanup and any remaining gap. Do not borrow devcontainer evidence for production or metadata for an unexecuted architecture. The five hardening locations and22 contextual dispositions retain their individual attribution under central187; this is neither a claim of27 vulnerabilities nor a universal zero-report result. Existing operator stops and production/release boundaries remain intact.

  5. added
    status:in-progressApproved work is actively being implemented or validated
    and removed
    status:blockedWaiting on a named dependency or decision
    on Nov 6, 2026
  6. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    The exact first-execution prerequisite is resolved, and ordinary source qualification is now running on draft #326, exact head 52869663a24a733345efecaebfdc105833e08746, tree d25cbebae77d73c8ae68d0f72878263609c82cc2. This successor only adds explicit UID output/refusal for both app and worker to the already disclosed smoke checks. Main remains 2ecc.

    All existing PR workflows were allowed to start normally, including the selected first Python profile/producer execution and both native production builds. Image security source behavior and Public Boundary are already green; actual runtime results remain pending. The first concrete current-head failure is Central action policy preflight, which sample-app is diagnosing on the same source train. No failed result is relabeled or skipped. The manual publisher remains untouched and undispatched.

    Owner/next action: sample-app fixes genuine current-head failures, verifies actual trust/client/producer and non-root runtime evidence, integrates normally only after required checks pass, and owns actual-main acceptance and remote-branch cleanup. #325 remains open through that outcome.

  7. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    Delivered by #326 at e2c6bfa, tree d3e3487a46042c7331f4152b6a548229def9013d. The PR had 36 successful checks and one existing neutral CodeQL rollup. Actual main has 29/29 successful checks across all 16 original workflow runs, with no pending/failing result. The final timer result is 42187256617. Required checks and protected integration were preserved.

    Actual-main proof Result
    Native amd64 production job SUCCESS. Image revision equals e2c6bfa, app and worker UID 33, installed apt/libapt 2.6.2. Storage and mounted-video write/unlink, unchanged Brotli verifier, Node/PHP/Composer trust, browser launch and all deterministic embedded samples pass.
    Native arm64 production job SUCCESS with the same actual revision, UID, storage/video, guard, browser and workflow assertions. This is an executed native result.
    Python/polyglot job SUCCESS on amd64 using exact official index 935c3c5b12357a7e10caa9c1e6ca5692344d97cf229832ef584be2cec9fc03df. Actual loaded Python 3.12.16, pip 26.2.2+sample.1, urllib3 2.8.0 and setuptools 84.2.1. Actual apt/libapt 2.6.2; system bundle has 148 certificates, blocked=0/0, SHA256 e9c7b63ee2623386e9b0a3ee32f499d01a8ea23dc83b8383ddff9f8e749543b7. Authenticated local-wheel bootstrap and effective guards precede SDK requests; final CA checks and the documented example pass. Arm64 Python remains metadata coverage.
    Application and source CI SUCCESS for both PHP application and microservice versions, all 67 image/source-security tests, central action policy and aggregate qualification.
    Main Sonar analysis SUCCESS. Analysis dfdd0585-6543-4a79-ad0a-25960647093d at 08:23:14Z names exact e2c6bfa. Read-only exact-key lookup reports all five corrected locations CLOSED/FIXED and the 22 individually attributed contextual reports still OPEN.

    Both main production jobs removed app, worker, MySQL and Redis containers, their three project volumes and the project network. The main Python job removed its workflow/activity/Server/database containers and network. The remaining original main workflows are terminal SUCCESS with their normal cleanup. PR devcontainer startup qualified on both native architectures, and original PR activity recovery/external effects also passed. The owned remote branch fix/187-source-boundaries is deleted and its absence verified; local source candidates are preserved. No local runtime resource was created.

    The three reported curl downloads now enforce HTTPS for initial and redirect protocols, with the existing Redis checksum/version/time bounds and CLI selectors intact. The unchanged policy parser dependency is wheel-only. Production app/worker processes inherit www-data, with owned home/browser/video/application storage; the disclosed explicit screenshot-output tool retains its existing local host-bind authority. Both production PHP stages use the matching accepted b3e parent and immutable central preflight before all relevant APT/Brotli/Playwright edges. The new Python profile keeps old pip offline until authenticated local wheels and the effective-client/trust guards pass. Extracted build-only PHP sources are removed so the unchanged full runtime verifier can run as the application user.

    Published SDK/service tuple and dependency locks byte-match accepted 2ecc. The central guard/exporter, neutral producer/tool/patch inputs and effective-client/Brotli guards retain their selected bytes. The 27-key original disposition, first-execution decision, original failures and corrections, and corrected PR runtime receipt remain separately attributed. Source analysis closed the five fixed reports automatically; no finding-state/profile/exclusion change was made by this work, and no zero-report or 27-vulnerability claim is made.

    The manual publisher's latest run remains completed original 42129323146 on 2ecc. Source integration created no public image publication or production effect, and completed #318 was preserved. All #325 acceptance criteria are now met within the selected ordinary source/CI scope. Owner: sample-app; close completed and hand the exact-key/main receipt back to central #187.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions