You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The KPI gate spawns scripts/check-kpi.mjs and scripts/evaluate-observability-alerts.mjs with an environment constructed as { ...process.env, ...(step.env ?? {}) }. That gives both scoring subprocesses every ambient workflow/model/provider/runner credential and configuration value even though their intended authority is local KPI evidence evaluation.
Fresh protected main remains c85d710804139c0697d7ef8fa47d02b1389e6d84. The same boundary is still present on currently moving PR #105 head 19b49cb6cc2e072eafa37fae2170d7d1f2ccdfa3, scripts/kpi-gate.mjs blob 8375211e393ad1ff8c67e848a92e015156cf63a3.
RCA
First failing boundary: spawnSync(step.command[0], ..., { env: { ...process.env, ...(step.env ?? {}) } }) in the parent KPI gate.
Immediate cause: ambient environment inheritance is explicitly copied into child authority.
Systemic cause: KPI subprocess inputs have no declared least-authority environment contract comparable to the repository's GitHub CLI/readiness subprocess hardening work.
Risk is unnecessary credential/configuration propagation rather than evidence that either current child intentionally reads a particular secret. A child dependency, preload/config hook, future code change or diagnostic path should not gain unrelated ambient authority by default.
Writer-safety defer
Do not start a parallel source branch while #105 is moving and owns scripts/kpi-gate.mjs plus its regression suite. #105's visible body is already stale relative to its live head, which is active-writer evidence. Revalidate after #105 settles or integrates, then repair on the surviving lineage rather than racing or duplicating that writer.
Add a realistic RED regression using a hostile synthetic parent environment containing GitHub/GITHUB tokens, NVIDIA/model credentials, Maintainer/Reviewer App material, Cloudflare/provider credentials, proxy values, HOME, NODE_OPTIONS, and unrelated NOEMA_* state.
Define the minimal child environment required by check-kpi.mjs and evaluate-observability-alerts.mjs; keep per-step NOEMA_KPI_REQUIRE_WINDOW_DAYS only where explicitly required.
Preserve executable resolution/runtime behavior without forwarding the complete parent environment.
Prove ambient NODE_OPTIONS/preload-style authority cannot silently cross this parent-child boundary unless an explicitly reviewed contract requires it.
Run focused RED -> GREEN, full exact-head release verification, current protected-base Security Scan, review/thread validation, and exact current-head coverage proof.
Do not weaken workflows, invent secrets/authority, or treat model/check/status evidence as formal approval.
Relationship to existing work
#107 narrows saleable-readiness subprocess authority and #109 narrows the hourly GitHub CLI subprocess environment. This issue is distinct: it covers the KPI gate's own child Node processes and must preserve #105's data-integrity work rather than overwriting it.
Problem
The KPI gate spawns
scripts/check-kpi.mjsandscripts/evaluate-observability-alerts.mjswith an environment constructed as{ ...process.env, ...(step.env ?? {}) }. That gives both scoring subprocesses every ambient workflow/model/provider/runner credential and configuration value even though their intended authority is local KPI evidence evaluation.Fresh protected
mainremainsc85d710804139c0697d7ef8fa47d02b1389e6d84. The same boundary is still present on currently moving PR #105 head19b49cb6cc2e072eafa37fae2170d7d1f2ccdfa3,scripts/kpi-gate.mjsblob8375211e393ad1ff8c67e848a92e015156cf63a3.RCA
First failing boundary:
spawnSync(step.command[0], ..., { env: { ...process.env, ...(step.env ?? {}) } })in the parent KPI gate.Immediate cause: ambient environment inheritance is explicitly copied into child authority.
Systemic cause: KPI subprocess inputs have no declared least-authority environment contract comparable to the repository's GitHub CLI/readiness subprocess hardening work.
Risk is unnecessary credential/configuration propagation rather than evidence that either current child intentionally reads a particular secret. A child dependency, preload/config hook, future code change or diagnostic path should not gain unrelated ambient authority by default.
Writer-safety defer
Do not start a parallel source branch while #105 is moving and owns
scripts/kpi-gate.mjsplus its regression suite. #105's visible body is already stale relative to its live head, which is active-writer evidence. Revalidate after #105 settles or integrates, then repair on the surviving lineage rather than racing or duplicating that writer.Acceptance criteria
mainand the surviving KPI lineage after fix(kpi): bind strict provenance to exact log bytes #105 settles.HOME,NODE_OPTIONS, and unrelatedNOEMA_*state.check-kpi.mjsandevaluate-observability-alerts.mjs; keep per-stepNOEMA_KPI_REQUIRE_WINDOW_DAYSonly where explicitly required.NODE_OPTIONS/preload-style authority cannot silently cross this parent-child boundary unless an explicitly reviewed contract requires it.Relationship to existing work
#107 narrows saleable-readiness subprocess authority and #109 narrows the hourly GitHub CLI subprocess environment. This issue is distinct: it covers the KPI gate's own child Node processes and must preserve #105's data-integrity work rather than overwriting it.
Related: #3, #27, #29, #104, #105, #107, #109