denoland/deno · warning

Setting the NODE_DEBUG environment variable to '${StringProt

Error message

Setting the NODE_DEBUG environment variable to '${StringPrototypeToLowerCase(set)}' can expose sensitive data (such as passwords, tokens and authentication headers) in the resulting log.

What it means

node:util's debuglog initialization in Deno mirrors Node's warning for NODE_DEBUG=http/http2: enabling debug logging for the HTTP layers prints request/response internals, including URLs, headers, and potentially Authorization tokens (ext/node/polyfills/internal/util/debuglog.ts:57-66). It is a privacy/security heads-up, not a functional problem; the debug logging still happens if you keep the variable set.

Source

Thrown at ext/node/polyfills/internal/util/debuglog.ts:64

        "*",
        ".*",
      ),
      ",",
      "$|^",
    );
    const debugEnvRegex = new SafeRegExp(`^${debugEnv}$`, "i");
    testEnabled = (str) => RegExpPrototypeExec(debugEnvRegex, str) !== null;
  } else {
    testEnabled = () => false;
  }
}

// Emits warning when user sets
// NODE_DEBUG=http or NODE_DEBUG=http2.
function emitWarningIfNeeded(set: string) {
  if ("HTTP" === set || "HTTP2" === set) {
    // deno-lint-ignore no-console
    console.warn(
      "Setting the NODE_DEBUG environment variable " +
        "to '" + StringPrototypeToLowerCase(set) + "' can expose sensitive " +
        "data (such as passwords, tokens and authentication headers) " +
        "in the resulting log.",
    );
  }
}

const noop = () => {};

function debuglogImpl(
  enabled: boolean,
  set: string,
): (...args: unknown[]) => void {
  if (debugImpls[set] === undefined) {
    if (enabled) {
      emitWarningIfNeeded(set);
      debugImpls[set] = function debug(msg, ...args: unknown[]) {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Remove http and http2 from NODE_DEBUG and keep only what you need (e.g., NODE_DEBUG=net,stream)
  2. Scope NODE_DEBUG to a single debug invocation (NODE_DEBUG=http deno run app.js) instead of exporting it globally
  3. If HTTP tracing is genuinely required, redact Authorization/Cookie/set-cookie headers from logs before they are stored or shared
  4. Audit CI containers and env files for stale NODE_DEBUG values

Example fix

# before
export NODE_DEBUG=http,http2,net
deno run app.js   # warning: http/http2 debug can leak credentials

# after
NODE_DEBUG=net,stream deno run app.js   # non-header-dumping sections only
Defensive patterns

Strategy: validation

Validate before calling

// scrub http/http2 from NODE_DEBUG before node modules initialize debuglog
const parts = (Deno.env.get("NODE_DEBUG") ?? "")
  .split(",")
  .map((s) => s.trim())
  .filter((s) => s && s.toLowerCase() !== "http" && s.toLowerCase() !== "http2");
if (parts.length) Deno.env.set("NODE_DEBUG", parts.join(","));
else Deno.env.delete("NODE_DEBUG");

Prevention

When it happens

Trigger: The NODE_DEBUG environment variable contains http or http2 (matching is case-insensitive, including inside comma-separated lists like NODE_DEBUG=http,net), and node code initializes debuglog for those sections. The check is exact section matching: 'HTTP' === set || 'HTTP2' === set after uppercase normalization.

Common situations: NODE_DEBUG=http exported in .bashrc/.zshrc, Dockerfiles, or CI defaults to debug fetch/undici-style issues and never removed; CI logs captured and shared with embedded Authorization/Cookie headers; pairing NODE_DEBUG with token-authenticated internal services.

Understand the failure class

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/a12d553cd13252a6. Report an issue: GitHub.