Skip to content

[APPS-2945] Add: warn on process.env reads in backend functions - #565

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 1 commit into
masterfrom
tiffany.trinh/apps-2945-warn-env-reads-v2
Oct 28, 2026
Merged

gh-worker-dd-mergequeue-cf854d[bot] merged 1 commit into
masterfrom
tiffany.trinh/apps-2945-warn-env-reads-v2

Conversation

@tyffical

@tyffical tyffical commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Architecture

flowchart TD
    T[".backend.* transform"] --> R["createBackendStaticChecks, one per plugin instance (app-local modules only)"]
    L["local run (module-graph walk)"] --> R
    V["vite build (nested backend build)"] --> R
    R --> M["rejectGlobalsMissingFromNode"]
    R --> W["warnAboutEnvReads"]
    W -->|"process.env.X, a destructure, an env import, a const alias"| K["warn: process.env.X"]
    W -->|"process.env[key], a rest destructure"| A["warn: process.env"]
    W -->|"writes, deletes, indirect forms"| N["no warning"]
Loading
  • The check warns once per file and use for each plugin instance.

Changes

7 changes across warn-env-reads.ts, ambient-global-access.ts, run-backend-static-checks.ts, the Vite call sites, README.md and tests
What changed File
Add warnAboutEnvReads, which warns on direct process.env reads, naming static keys, but not on a call of an inherited Object.prototype method such as process.env.hasOwnProperty('X').
Follow namespace imports, nested env destructures, destructured parameter defaults and process.env ?? {} fallbacks. warn-env-reads.ts
Export the static-name helpers it reuses. ambient-global-access.ts
Create the checks once per plugin instance, running the warning after the missing-global check. run-backend-static-checks.ts
Pass the plugin's checks to the transform, local-run, dev bundle and nested-build call sites. index.ts, dev-server.ts, dev-server-module-graph.ts, build-backend-functions.ts, backend-static-checks-plugin.ts
Document the forms it catches and the modules it skips. README.md
Test must-warn and must-not-warn forms, per-instance dedup, one warning across the transform and backend builds, and module skips. warn-env-reads.test.ts, dev-server-module-graph.test.ts, index.test.ts

QA Instructions

Check Result Evidence
vite build One warning line per file naming its uses; none for comments, strings, import.meta.env, hasOwnProperty, globalThis.process or a node_modules SDK; config.backend.ts warns on two lines Run 3
vite dev, each module requested twice, then edited One warning per file; the edit warns only the new key Run 3
Vite 8 local run One warning per fixture, none for useFetch; reads return null Run 1
STRIPE_KEY set, local and dev:verify Both warn and return null Run 2
yarn typecheck:all && yarn lint && yarn cli integrity && yarn build:all
# Expected: all exit 0, integrity leaves no file changes
TMPDIR=/private/tmp yarn test:unit packages/plugins/apps
# Expected: all suites pass
Runs 1 and 2: fixtures, run commands and output
  • src/useEnv.backend.ts:
export async function readStripeKey() { return process.env.STRIPE_KEY ?? null; }
  • src/useRestEnv.backend.ts:
export async function readRest() {
    const { env, ...rest } = process;
    return { region: env.REGION ?? null, restKey: rest.env?.STRIPE_KEY ?? null };
}
cd "$QA_DIR" && QA_APP=<vite 8 scaffold> ./install-plugin.sh 565 <build-plugins checkout of this branch>
QA_APP=<vite 8 scaffold> ./qa-run.sh development useEnv useRestEnv useFetch
# Output: one warning each, "useEnv.backend.ts uses process.env.STRIPE_KEY" and "useRestEnv.backend.ts uses process.env.REGION"; none for useFetch
# Output: 3 "in a child process" lines; readStripeKey null, readRest {"region":null,"restKey":null}
for m in development dev-verify; do
  QA_APP=<vite 8 scaffold> env STRIPE_KEY=qa-local-value ./qa-run.sh $m useEnv | grep -E "readStripeKey|uses process.env"
done
# Output: both runs return null and warn
Run 3: vite build and vite dev fixture and output
  • A Vite 6.4.3 app whose vite.config.mjs is export default { plugins: [datadogVitePlugin({ apps: { enable: true } })] }, importing the built plugin from this branch's packages/published/vite-plugin/dist/src/index.mjs; src/main.ts imports both functions, src/helper.ts is export const helperKey = () => process.env.HELPER_KEY ?? null;, and node_modules/fake-sdk/index.js is export const sdkKey = () => process.env.SDK_KEY ?? null;.
  • src/billing.backend.ts:
import { sdkKey } from 'fake-sdk';
import { helperKey } from './helper';

// process.env.IN_A_COMMENT should not warn
export async function readKeys() {
    return {
        ctor: String(process.env.constructor),
        stripe: process.env.STRIPE_KEY ?? null,
        hasRegion: process.env.hasOwnProperty('REGION'),
        mode: import.meta.env?.MODE ?? null,
        text: 'process.env.IN_A_STRING',
        viaGlobalThis: globalThis.process.env.GLOBAL_KEY ?? null,
        sdk: sdkKey(),
        helper: helperKey(),
    };
}
  • src/config.backend.ts:
import * as proc from 'node:process';

export async function readConfig({ TOKEN } = process.env) {
    const { env: { REGION } } = process;
    const { API_URL } = process.env ?? {};
    return { TOKEN, REGION, API_URL, debug: proc.env.DEBUG ?? null };
}
node <build-plugins>/node_modules/vite/bin/vite.js build
# Output, each line ending in the production explanation:
# [warn|vite|apps] <app>/src/config.backend.ts uses process.env.REGION, process.env.DEBUG.
# [warn|vite|apps] <app>/src/billing.backend.ts uses process.env.constructor, process.env.STRIPE_KEY.
# [warn|vite|apps] <app>/src/helper.ts uses process.env.HELPER_KEY.
# [warn|vite|apps] <app>/src/config.backend.ts uses process.env.TOKEN, process.env.API_URL.
# Output: dist/datadog-app-assets.zip holds backend/<hash>.readKeys.js and backend/<hash>.readConfig.js
node <build-plugins>/node_modules/vite/bin/vite.js --port 5287 --strictPort &
for u in billing.backend.ts "billing.backend.ts?t=1" config.backend.ts "config.backend.ts?t=2"; do curl -s -o /dev/null "http://localhost:5287/src/$u"; done
# Output: billing.backend.ts uses process.env.constructor, process.env.STRIPE_KEY.
# Output: config.backend.ts uses process.env.TOKEN, process.env.REGION, process.env.API_URL, process.env.DEBUG.
# Add `added: process.env.ADDED_KEY ?? null,` to readKeys, then request billing.backend.ts?t=3
# Output: billing.backend.ts uses process.env.ADDED_KEY.

Blast Radius

  • No feature flag. Low risk: warning only, builds never fail.
  • Apps whose backend modules read process.env directly (NODE_ENV included) get new warn-level log lines in builds and the dev server.

Out of Scope / Follow-ups

3 items deferred
Item Status Next step
Indirect forms don't warn, such as parameters, let aliases, dynamic imports, spreads and globalThis.process Accepted None
NODE_ENV and keys the file assigns itself still warn Accepted None: the runtime leaves NODE_ENV unset too
In vite build, Vite's define rewrites process.env before the transform-hook check, so a file mixing process.env.X with forms like proc.env.X warns on two lines Follow-up Skip the transform-hook warning in builds, since the backend build checks every file

Documentation

🤖 Generated with Claude Code

@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 2 times, most recently from 481364f to e574841 Compare October 8, 2026 03:44
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 1139d7b to 1c99e18 Compare October 8, 2026 04:29
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from e574841 to 34a9189 Compare October 13, 2026 00:52
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 1c99e18 to f47f7f2 Compare October 13, 2026 01:33
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from 34a9189 to abf34ad Compare October 13, 2026 20:08
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch 3 times, most recently from cd6a25a to cf3c8c3 Compare October 14, 2026 22:40
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from abf34ad to 892bda9 Compare October 15, 2026 01:04
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from cf3c8c3 to 47069c8 Compare October 15, 2026 02:18
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 2 times, most recently from bd21790 to 2352fe9 Compare October 15, 2026 15:37
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 47069c8 to 7c4b7c7 Compare October 15, 2026 17:08
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 2 times, most recently from e7d5434 to 1fa97d9 Compare October 15, 2026 22:20
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 7c4b7c7 to 2f3af66 Compare October 15, 2026 23:51
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 2 times, most recently from e44fe4a to 141d960 Compare October 16, 2026 00:47
@tyffical
tyffical marked this pull request as ready for review October 16, 2026 01:26
@tyffical
tyffical requested a review from a team as a code owner October 16, 2026 01:26
@tyffical
tyffical requested review from Chau-DDOG and removed request for a team October 16, 2026 01:26
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 2f3af66 to 10e3990 Compare October 16, 2026 02:55
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from 141d960 to 04671dd Compare October 16, 2026 04:18
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 10e3990 to 6941e61 Compare October 16, 2026 04:45
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from 04671dd to 696d422 Compare October 16, 2026 16:37
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 6941e61 to 7c83f70 Compare October 16, 2026 16:37
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from cd32453 to a779bfd Compare October 23, 2026 16:23
@tyffical
tyffical requested a balanced review from Copilot October 23, 2026 16:44
@tyffical

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T16:49:04.250227Z a779bfd Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Optional-chain deletes incorrectly emit environment-read warnings instead of being excluded like plain deletes.

1 open issue
What changed in this PR

Adds warning-only checks for backend process.env reads, extending the apps plugin’s Node runtime checks to flag values unavailable in production.

Changes:

  • Detects direct reads, destructuring, supported imports, and first-level const aliases, with per-file warning deduplication.
  • Integrates warnings into shared backend static checks.
  • Documents supported forms and adds unit and module-graph coverage.
File Description
packages/​plugins/​apps/​src/​vite/​dev-server-module-graph.test.ts Tests local-run warnings, deduplication, and dependency skips.
packages/​plugins/​apps/​src/​backend/​ast-parsing/​warn-env-reads.ts Implements environment-read detection and warning reporting.
packages/​plugins/​apps/​src/​backend/​ast-parsing/​warn-env-reads.test.ts Tests detection, exclusions, deduplication, and failure handling.
packages/​plugins/​apps/​src/​backend/​ast-parsing/​run-backend-static-checks.ts Invokes the new warning check.
packages/​plugins/​apps/​src/​backend/​ast-parsing/​run-backend-static-checks.test.ts Tests shared-check warning integration.
packages/​plugins/​apps/​src/​backend/​ast-parsing/​ambient-global-access.ts Exports helpers reused by the detector.
packages/​plugins/​apps/​README.md Documents warnings, supported forms, and module exclusions.

Review effort: Balanced

Comment thread packages/plugins/apps/src/backend/ast-parsing/warn-env-reads.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: a779bfd271

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from a779bfd to 9e703c8 Compare October 23, 2026 21:34
Comment thread packages/plugins/apps/src/backend/ast-parsing/warn-env-reads.ts Outdated
Comment thread packages/plugins/apps/src/backend/ast-parsing/warn-env-reads.ts
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 9e703c8 to e55c10f Compare October 26, 2026 23:48
@tyffical
tyffical requested a review from ksun154 October 27, 2026 00:09
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from b71e121 to 368c9ee Compare October 27, 2026 01:01
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from e55c10f to c6047fd Compare October 27, 2026 01:11
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from 368c9ee to 67fb3ed Compare October 27, 2026 03:08
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from c6047fd to c910814 Compare October 27, 2026 03:17
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from 67fb3ed to 539234b Compare October 27, 2026 20:16
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from c910814 to e02b793 Compare October 27, 2026 20:16
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from 539234b to 2c6b514 Compare October 28, 2026 05:40
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from e02b793 to 44d6ae4 Compare October 28, 2026 05:44
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from 2c6b514 to acb744e Compare October 28, 2026 16:13
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from 44d6ae4 to fe3b73b Compare October 28, 2026 16:13
The Node backend runtime doesn't pass the developer's environment
variables or Custom Credentials to backend functions, so a
process.env.X read finds nothing in production, and nothing flagged it
before upload.

The static checks now warn, never fail, on direct process.env reads in
app-local backend modules, once per file and use for each plugin
instance, naming the variable when the key is static: process.env.X
and process.env[key], destructures of process.env, env or default
process imports from process or node:process, and a const bound to
process.env or to an env destructured from process. Writes, including
destructuring and for...in/of targets, and deletes don't warn, and
neither does calling an inherited Object.prototype method such as
process.env.hasOwnProperty('X'); any other use of such a name, like
process.env.constructor, reads a variable and warns. Modules a backend
file imports from node_modules or from outside the Vite root are
skipped, so an SDK's own env reads don't warn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from acb744e to 2f4f385 Compare October 28, 2026 16:52
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-warn-env-reads-v2 branch from fe3b73b to fa8a098 Compare October 28, 2026 16:52
Base automatically changed from tiffany.trinh/apps-2945-follow-terrapin-flag to master October 28, 2026 17:03
@tyffical

Copy link
Copy Markdown
Contributor Author

/merge

@gh-worker-devflow-routing-ef8351

gh-worker-devflow-routing-ef8351 Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

View all feedbacks in Devflow UI.

2026-10-28 17:28:31 UTC ℹ️ Start processing command /merge


2026-10-28 17:28:35 UTC ℹ️ MergeQueue: pull request added to the queue

The expected merge time in master is approximately 2m (p90).


2026-10-28 17:29:57 UTC ℹ️ MergeQueue: This merge request was merged

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants