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

  1. Centralize: read process.env once in a config module (ideally validated with envalid/zod) and import typed values everywhere else
  2. Allowlist vetted names: "node/no-process-env": ["error", { "allowedVariables": ["NODE_ENV"] }]
  3. Pass configuration explicitly as function/constructor parameters so modules stay env-agnostic
  4. 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

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


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/2cdc4c231f7e18d7. Report an issue: GitHub.