Skip to content

chore: clone config.env in genEnv to prevent shared-object mutation#2981

Open
joonas wants to merge 3 commits intodefenseunicorns:mainfrom
joonas:fix/environment-mutates-shared-config-env
Open

chore: clone config.env in genEnv to prevent shared-object mutation#2981
joonas wants to merge 3 commits intodefenseunicorns:mainfrom
joonas:fix/environment-mutates-shared-config-env

Conversation

@joonas
Copy link
Copy Markdown
Member

@joonas joonas commented Mar 1, 2026

Description

genEnv deleted config.env["PEPR_WATCH_MODE"] directly from the caller's ModuleConfig reference. Since the same config object is passed twice (once for the admission deployment and once for the watcher deployment) the first call permanently removed the key. Any code reading config.env after the first genEnv call would no longer see PEPR_WATCH_MODE.

Shallow-clone config.env into a local cfg object and delete the key from the clone instead. This preserves the original config while still preventing a user-supplied PEPR_WATCH_MODE from overriding the programmatic value controlled by the watchMode parameter.

Both regression tests assert config.env identity via snapshot comparison rather than checking genEnv return values. The def object always supplies PEPR_WATCH_MODE from the watchMode parameter, so output-based assertions pass even with the mutation bug present. Existing tests already cover output correctness for each mode.

End to End Test:
(See Pepr Excellent Examples)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Other (security config, docs update, etc)

Checklist before merging

@joonas joonas requested a review from a team as a code owner March 1, 2026 05:21
@github-project-automation github-project-automation Bot moved this to 👀 In review in Pepr Project Board Mar 2, 2026
@cmwylie19 cmwylie19 changed the title fix: clone config.env in genEnv to prevent shared-object mutation chore: clone config.env in genEnv to prevent shared-object mutation Mar 2, 2026
`genEnv` deleted `config.env["PEPR_WATCH_MODE"]` directly from the
caller's `ModuleConfig` reference. Since the same config object is
passed twice (once for the admission deployment and once for the
watcher deployment) the first call permanently removed the key.
Any code reading `config.env` after the first `genEnv` call would
no longer see `PEPR_WATCH_MODE`.

Shallow-clone `config.env` into a local `cfg` object and delete
the key from the clone instead. This preserves the original config
while still preventing a user-supplied `PEPR_WATCH_MODE` from
overriding the programmatic value controlled by the `watchMode`
parameter.

Both regression tests assert `config.env` identity via snapshot
comparison rather than checking `genEnv` return values. The `def`
object always supplies `PEPR_WATCH_MODE` from the `watchMode`
parameter, so output-based assertions pass even with the mutation
bug present. Existing tests already cover output correctness for each mode.

Signed-off-by: Joonas Bergius <joonas@defenseunicorns.com>
@samayer12 samayer12 force-pushed the fix/environment-mutates-shared-config-env branch from d9479f9 to bcdf37e Compare March 17, 2026 15:27
@samayer12
Copy link
Copy Markdown
Contributor

@greptileai

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 22, 2026

Greptile Summary

This PR fixes a shared-object mutation bug in genEnv where config.env["PEPR_WATCH_MODE"] was deleted directly from the caller's ModuleConfig reference, causing the second call (watcher deployment) to see a modified config. The fix is minimal and correct: shallow-clone config.env into a local cfg object before deleting the key, and two focused regression tests are added to lock in the behaviour.

Confidence Score: 5/5

Safe to merge — targeted one-liner fix with good regression coverage and no behaviour change for callers.

The change is tiny, well-understood, and correctly addresses the mutation bug. No P0/P1 findings; all remaining observations are P2 or lower.

No files require special attention.

Important Files Changed

Filename Overview
src/lib/assets/environment.ts Fixes shared-object mutation by shallow-cloning config.env before deleting PEPR_WATCH_MODE; logic is correct and minimal
src/lib/assets/environment.test.ts Adds two well-targeted regression tests: one for single-call non-mutation and one for the consecutive-call scenario that exposed the bug

Sequence Diagram

sequenceDiagram
    participant Caller
    participant genEnv

    Note over Caller: Build admission + watcher deployments<br/>using the same ModuleConfig

    Caller->>genEnv: genEnv(config, watchMode=false)
    Note over genEnv: cfg = { ...config.env }<br/>delete cfg.PEPR_WATCH_MODE<br/>(clone only, original untouched)
    genEnv-->>Caller: V1EnvVar[] (PEPR_WATCH_MODE="false")

    Note over Caller: config.env still intact ✅

    Caller->>genEnv: genEnv(config, watchMode=true)
    Note over genEnv: cfg = { ...config.env }<br/>delete cfg.PEPR_WATCH_MODE<br/>(clone only, original untouched)
    genEnv-->>Caller: V1EnvVar[] (PEPR_WATCH_MODE="true")

    Note over Caller: config.env still intact ✅
Loading

Reviews (1): Last reviewed commit: "Merge branch 'main' into fix/environment..." | Re-trigger Greptile

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

Labels

None yet

Projects

Status: 👀 In review

Development

Successfully merging this pull request may close these issues.

4 participants