oxc-project/oxc · warning · OxcDiagnostic
Disallowed usage of `process.env`.
Error message
Disallowed usage of `process.env`.
What it means
Diagnostic from oxlint rule node/no-process-env (restriction). It disallows direct reads of process.env so that environment configuration flows through one audited module instead of being scattered across the codebase — scattered reads are hard to inventory, easy to get wrong (undefined vs empty string), and impossible to type. The allowedVariables option allowlists specific variable names; the default configuration allows none.
Source
Thrown at crates/oxc_linter/src/rules/node/no_process_env.rs:19
use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::IsGlobalReference;
use oxc_span::{GetSpan, Span};
use oxc_str::CompactStr;
use oxc_str::static_ident;
use rustc_hash::FxHashSet;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
AstNode,
context::LintContext,
rule::{DefaultRuleConfig, Rule},
};
fn no_process_env_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Disallowed usage of `process.env`.")
.with_help("Remove usage of `process.env`.")
.with_label(span)
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
struct NoProcessEnvConfig {
/// Variable names which are allowed to be accessed on `process.env`.
allowed_variables: FxHashSet<CompactStr>,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct NoProcessEnv(Box<NoProcessEnvConfig>);
declare_oxc_lint!(
/// ### What it does
///
/// Disallows use of `process.env`.View on GitHub (pinned to e1e7af627c)
Solutions
- Centralize: read process.env once in a config module (ideally validated with envalid/zod) and import typed values everywhere else
- Allowlist vetted names: "node/no-process-env": ["error", { "allowedVariables": ["NODE_ENV"] }]
- Pass configuration explicitly as function/constructor parameters so modules stay env-agnostic
- In Next.js client code, prefer NEXT_PUBLIC_* build-time inlining instead of runtime process.env reads
Example fix
// before (scattered)
const port = process.env.PORT;
const key = process.env.API_KEY;
// after: single audited reader, e.g. config.js
// config.js
const env = (name) => {
const v = process.env[name]; // the one allowed place
if (!v) throw new Error(`Missing env var: ${name}`);
return v;
};
module.exports = { port: Number(env('PORT')), apiKey: env('API_KEY') }; Defensive patterns
Strategy: validation
Validate before calling
// .oxlintrc.json
"rules": {
"node/no-process-env": ["error", { "allowedVariables": ["NODE_ENV"] }]
}
npx oxlint -c .oxlintrc.json --deny-warning . Prevention
- Route every env read through one validated config module (envalid/zod) so this rule has exactly one sanctioned file
- Fail fast on missing variables at startup with clear messages instead of scattering process.env across modules
- Prefer explicit dependency injection into modules so business logic is testable without env trickery
When it happens
Trigger: Any member access on process.env — process.env.NODE_ENV, process.env['API_KEY'] — where the accessed variable name is not in the configured allowedVariables FxHashSet (camelCase JSON key). With default options the set is empty, so every process.env access in the file reports with the property's span labeled.
Common situations: 12-factor apps expected to read config in a single config.js; monorepos with shared oxlint configs banning scattered env reads; migrations from eslint-plugin-n where the allowedVariables lists must be re-entered; teams wanting typed config via zod/envalid at one boundary.
Related errors
- Expected error to be handled.
- Do not use @ts-{ts_comment_name} because it alters compilati
- `alert`, `confirm` and `prompt` functions are not allowed
- Expected return with your callback function.
- Unexpected access to `exports`.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/2cdc4c231f7e18d7.
Report an issue: GitHub.