Skip to content

WEB-PRIVACY-001AB — Contain Netlify release child diagnostics #596

Closed

Description

@daliu

Outcome

Prevent Git, npm, tar, and frontend-build subprocesses from writing their own diagnostics into the temporary Netlify release builder's stdout or stderr. Preserve the fixed parent failure marker and the existing parent-owned success evidence. This is the dependency-ready privacy follow-up explicitly left by #582 and an atomic child of #105.

Defect

Exact released main 3ac4acee407220f34ef5ced1f43efe69279dfa09 contains two output paths that bypass #582's fixed outer catch:

  • run() executes child commands with stdio: 'inherit', so child stdout and stderr reach the retained build log before the parent can emit netlify_release_build_failed.
  • the git rev-parse and git show reads pipe required stdout but inherit stderr.

A child diagnostic can contain command detail, a path, URL, token-shaped value, source excerpt, or other private material. The builder already supplies a minimum credential-free environment, but that does not make arbitrary child output safe to retain.

Priority and dependency state

Security invariant

No child-owned byte reaches the executable builder's stdout or stderr.

  • Generic child commands receive ignored stdin, stdout, and stderr.
  • The two Git identity reads capture only the required stdout internally and discard stderr.
  • A child exit failure, signal, or invalid captured commit/tree produces empty parent stdout, exact stderr netlify_release_build_failed\n, and process status 1.
  • The parent never logs the child exception.
  • Existing parent-owned successful release evidence remains unchanged.

This does not claim that Netlify/platform logs outside this process are sanitized.

Allowed behavior and failure cases

  • Successful source fetch, identity verification, install, build, artifact verification, publication, cleanup, and final parent evidence keep their current semantics.
  • Child progress and diagnostics are intentionally silent.
  • rev-parse and show still return their captured stdout for exact commit/tree comparison.
  • Every synthetic child output canary is absent on failure.
  • Failure stays fail-closed.
  • The inactive manifest remains inactive.

Exact implementation scope

  1. scripts/netlify-release-build.js
    • change only child-process stdio projection: ignore generic command streams; capture required Git stdout and ignore Git stderr.
  2. tests/test-artifact-safety.test.js
    • add minimum fake-git/synthetic-PATH black-box fixtures and one separately named WEB-PRIVACY-001AB block;
    • cover a generic run() failure, rev-parse failure, and show failure after valid synthetic rev-parse;
    • assert no inherited stdio remains.
  3. OPERATIONS_RUNBOOK.md
  4. docs/officers/PUBLISH_AND_CHECK.md
    • extend the source-only backup-officer procedure with the child-output boundary, a small log-flow Mermaid diagram, and a one-sentence text alternative.

Explicit exclusions

No change to release policy, authorization, source pins, artifact rules, cleanup, manifest/configuration, tests/release-workflow.test.js, workflows, packages/locks, Netlify settings, Firebase, providers, website publication, production data, migration, or live behavior. No real credentials, member data, payment data, production provider call, or network call in tests.

Verification

  1. Record trustworthy test-only RED on untouched runtime using fake local executables that emit made-up stdout/stderr canaries.
  2. Prove each failure returns status 1, no signal, empty stdout, exact fixed stderr, and no canary.
  3. Prove required Git stdout capture and existing successful parent evidence remain compatible.
  4. Run the complete artifact-safety and unchanged release-workflow suites, then relevant repository gates.
  5. Review the exact diff for output flow, secrets/PII, authorization, cleanup, artifact compatibility, and production fallback.
  6. Obtain independent exact-head security/test and backup-officer reviews before merge.
  7. After merge, verify exact-main CI and record website, Firebase, Netlify/provider, data, and live states separately.

Compatibility and migration

No schema, API, dependency, configuration, workflow, artifact-format, data, or migration impact. Build progress and child error detail disappear intentionally. Troubleshooting uses safe local synthetic reproduction and bounded non-sensitive evidence. Exit detection, captured Git values, artifact behavior, cleanup, and the final Prepared … evidence line remain compatible.

Officer impact: Backup officers receive a clearer source-review boundary. On failure they may retain only the fixed parent code and bounded metadata, not raw child output.

Officer documentation: docs/officers/PUBLISH_AND_CHECK.md; engineering boundary in OPERATIONS_RUNBOOK.md.

Deployment evidence: None at issue creation. Source/tests/merge will not be described as website publication, runmprc.com verification, Firebase deployment, Netlify/provider configuration, production-data change, or live-behavior proof.

Activity

  1. self-assigned this
    on Aug 2, 2026
  2. added
    bugSomething isn't working
    priority:P1High-priority follow-up
    type:securitySecurity or privacy boundary
    area:webWeb application and hosting
    area:ciContinuous integration and deployment
    size:XSOwner decision or very narrow change
    status:in-progressClaimed and actively being implemented
    type:testingTest infrastructure and quality gates
    area:privacyPersonal data, consent, minimization, retention, and privacy operations
    on Aug 2, 2026
  3. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    CLAIMED by /root at 2026-08-02T03:41:22Z on branch codex/issue-596-netlify-child-output, exact released base 3ac4acee407220f34ef5ced1f43efe69279dfa09.

    Exact ownership:

    1. scripts/netlify-release-build.js
      • only subprocess stdio projection: generic commands ignore stdin/stdout/stderr; Git identity reads keep stdout piped and discard stderr.
    2. tests/test-artifact-safety.test.js
      • minimum fake-executable/PATH fixture support;
      • one separately named WEB-PRIVACY-001AB black-box block for generic-run, rev-parse, and show child output/failure;
      • one bounded no-inherited-stdio assertion.
    3. OPERATIONS_RUNBOOK.md
    4. docs/officers/PUBLISH_AND_CHECK.md

    Invariant: no child-owned byte reaches wrapper stdout or stderr. Every child failure remains unsuccessful with empty parent stdout and exact netlify_release_build_failed\n stderr. Required Git stdout stays internal. Existing parent-owned final Prepared … evidence remains unchanged.

    Immutable exclusions: release policy/authorization/source pins/artifact/cleanup semantics; manifest/configuration; config/netlify-production-release.json; tests/release-workflow.test.js; draft #462; workflows; packages/locks; Netlify/Firebase/provider settings; website publication; production data; migrations; live behavior; active #571 and every other claimed path.

    The empty remote branch was pushed from exact main before this marker. #582 is COMPLETE/CLOSED/CLAIM RELEASED. Exact issue/PR/branch/path searches and three read-only audits found no competing claim. No source, test, or documentation edit preceded this claim.

    Claim remains active through trustworthy RED, implementation, independent exact-head review, hosted CI, merge, exact-main/deployment truth audit, closure, and explicit release.

    Officer impact: source-review clarity only. A backup officer retains the fixed parent code and bounded metadata, not raw child diagnostics.

    Officer documentation: only the named section in docs/officers/PUBLISH_AND_CHECK.md; the subprocess-output data-flow change will include Mermaid and a text alternative.

    Deployment evidence: none at claim time. No website, runmprc.com, Firebase, Netlify/provider, production-data, or live-behavior state will be inferred from source or tests.

  4. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    TRUSTWORTHY RED — before runtime or documentation edits

    • Exact untouched runtime/base: 3ac4acee407220f34ef5ced1f43efe69279dfa09.
    • Only changed path: tests/test-artifact-safety.test.js.
    • Test-only binary diff SHA-256: 8d817f86e153f952a5514f99f45d44688076ff2ec11985d2ec9d948c48d16760.
    • Runtime: Node v20.20.2.
    • Focused command: node --test --test-name-pattern='WEB-PRIVACY-001AB' tests/test-artifact-safety.test.js.

    Expected RED observed: 5 intended nested subtest failures.

    1. A generic child exit wrote its made-up private-path stdout canary into wrapper stdout.
    2. A generic child terminated by signal wrote the same canary into wrapper stdout.
    3. A failing git rev-parse wrote its made-up token-shaped stderr canary before the fixed parent marker.
    4. A failing git show wrote its made-up token-shaped stderr canary before the fixed parent marker.
    5. The static source proof found the three inherited-stdio projections.

    The invalid captured-Git-value case already passed: required stdout stayed internal and the mismatch produced only the fixed parent marker. Every synthetic wrapper process exited unsuccessfully with no wrapper-level signal.

    The fake executable intercepted the first relevant local Git command. No network, Netlify, Firebase, provider, credential, production data, website, deployment, or live action occurred. Runtime and both documentation paths remained byte-identical.

  5. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    IMPLEMENTATION CANDIDATE — corrected exact clean head

    • Exact released base: 3ac4ace.
    • Corrected candidate head: 85a4f62.
    • Candidate tree: 7f121ac5fd9bf86ff69ce61bf07a46d97fa9bd19.
    • Exact four-file base-to-head binary patch SHA-256: d77b3ba3327c852a78d4d6aa45f625405ee5fe68069f21a3ba87126bf9657334.
    • Trustworthy test-only RED patch SHA-256: 8d817f86e153f952a5514f99f45d44688076ff2ec11985d2ec9d948c48d16760.
    • Worktree/index clean; diff check and Node syntax checks pass.

    Outcome: the executable Netlify release builder now discards generic child stdin/stdout/stderr and captures only required Git commit/tree stdout internally while discarding Git stderr. Child exit failure, signal termination, Git-read failure, and invalid captured identity produce empty parent stdout, exact fixed parent stderr, and status 1. Authorization, environment allowlist, source pins, artifact behavior, cleanup, and final parent Prepared evidence are unchanged.

    Trustworthy RED on exact old runtime produced five intended nested failures: generic stdout escaped on exit and signal; both Git reads leaked stderr; inherited stdio remained. The invalid captured-value path was already safely fixed. Fake local Git intercepted all exercised commands before network/provider work.

    Pinned Node 20 / Java 21 verification:

    • Focused WEB-PRIVACY-001AB: 6/6 nested cases passed.
    • Artifact-safety + unchanged release-workflow: 50/50.
    • Complete root static/security suite: 93/93.
    • Frontend Jest: 951/951.
    • Frontend lint: 118 files / 113 reviewed legacy errors / 6 reviewed legacy warnings.
    • Functions lint: passed.
    • Functions Jest: 69 suites passed / 2 intentionally skipped; 7,487 passed / 64 intentionally skipped.
    • SPA safety: 11/11.
    • Rules demo emulator: 418/418.
    • Commerce-journal demo emulator: 63/63.
    • TypeScript no-emit, direct diagnostic build, syntax checks, and diff check: passed.
    • Diagnostic audits unchanged by this no-package diff: root full 59; root production 4; Functions full/production 8 moderate.
    • Exact-head PR CI 30731525676: all five required jobs passed.

    Review:

    • Independent security/test review: GO.
    • Independent scope/compatibility review: GO.
    • Backup-officer review first stopped on an imprecise diagram and specialist wording.
    • Corrected head separates internal commit/tree values from discarded helper output and uses plain descriptions.
    • Corrective backup-officer re-review: GO.
    • All three reviewers reconfirmed the exact corrected head/tree/base/patch digest.

    Delivery truth:

    • Source changed: yes.
    • Tests passed: yes.
    • Code merged: no at this marker.
    • Exact-head GitHub deployments: [].
    • Netlify preview 6a6ec042f0810300083b82c6 is ready for exact head, deploy-preview only, published_at=null, HTTP 200, and noindex.
    • Website published: no.
    • runmprc.com verified as WEB-PRIVACY-001AB — Contain Netlify release child diagnostics #596: no.
    • Firebase deployed/read back: no.
    • Outside-provider configuration changed/verified: no.
    • Production data, migration, and live behavior: not accessed, changed, or verified.
    • Netlify platform output outside this builder remains a separate unclaimed boundary.

    Officer impact: source-review clarity only. A backup officer can distinguish internal commit/tree checks, discarded helper output, the fixed parent failure code, and outside-provider logging.

    Officer documentation: docs/officers/PUBLISH_AND_CHECK.md; engineering boundary in OPERATIONS_RUNBOOK.md.

  6. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    COMPLETE / CLOSED / CLAIM RELEASED

    PR #597 was admin-squash-merged only after ordinary merge failed solely on the repository's one-approval rule, the user's standing maintainer instruction to self-review and merge, a hosted self-review GO, three independent exact-head GO reviews, and all five required hosted checks.

    Exact identities:

    • Corrected reviewed head: 85a4f62
    • Exact main: d462ff6
    • Exact parent: 3ac4ace
    • Identical reviewed/merge tree: 7f121ac5fd9bf86ff69ce61bf07a46d97fa9bd19
    • Parent-to-main binary patch SHA-256: d77b3ba3327c852a78d4d6aa45f625405ee5fe68069f21a3ba87126bf9657334
    • Exact scope: OPERATIONS_RUNBOOK.md, docs/officers/PUBLISH_AND_CHECK.md, scripts/netlify-release-build.js, and tests/test-artifact-safety.test.js

    Verification:

    • Trustworthy RED: five intended nested failures on untouched runtime; test-only patch SHA-256 8d817f86e153f952a5514f99f45d44688076ff2ec11985d2ec9d948c48d16760.
    • Focused child-output block: 6/6 nested cases passed.
    • Artifact-safety + release-workflow: 50/50.
    • Complete root static/security suite: 93/93.
    • Frontend Jest: 951/951.
    • Frontend lint: 118 files / 113 reviewed legacy errors / 6 reviewed legacy warnings.
    • Functions lint: passed.
    • Functions Jest: 69 suites passed / 2 intentionally skipped; 7,487 passed / 64 intentionally skipped.
    • SPA safety: 11/11.
    • Rules demo emulator: 418/418.
    • Commerce-journal demo emulator: 63/63.
    • TypeScript no-emit, diagnostic build, syntax checks, and diff check: passed.
    • PR CI 30731525676: all five required jobs passed on the exact corrected head.
    • Exact-main CI 30731648519: all five required jobs passed.
    • Three independent reviewers reconfirmed the exact corrected head/tree/base/patch. One documentation STOP was corrected before merge; final backup-officer review is GO.

    Delivery truth:

    Officer impact: source-review clarity only. A backup officer can distinguish internal commit/tree values, discarded helper output, fixed parent failure, and outside-provider logging.

    Officer documentation: docs/officers/PUBLISH_AND_CHECK.md; engineering boundary in OPERATIONS_RUNBOOK.md.

    The assignee and status:in-progress label are being cleared. The remote work branch is absent, the local worktree is clean, and all four #596 path/hunk claims are RELEASED.

  7. removed their assignment
    on Aug 2, 2026
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

    area:ciContinuous integration and deploymentarea:privacyPersonal data, consent, minimization, retention, and privacy operationsarea:webWeb application and hostingbugSomething isn't workingpriority:P1High-priority follow-upsize:XSOwner decision or very narrow changetype:reliabilityReliability and recoverytype:securitySecurity or privacy boundarytype:testingTest infrastructure and quality gates

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions