n8n-io/n8n · error · SecurityError

Security violation: '${name}' is not allowed

Error message

Security violation: '${name}' is not allowed

What it means

Thrown by validateIdentifier when an identifier name is in DANGEROUS_GLOBALS — the set derived from BUILDER_BLOCKED_GLOBALS (eval, Function, require, process, global, globalThis, window, document, setTimeout, console, Buffer, Promise, Date, Math, JSON-as-object, etc.). Referencing any of these as an identifier in SDK code is a security violation.

Source

Thrown at packages/@n8n/workflow-sdk/src/ast-interpreter/validators.ts:286

	}

	if (!ALLOWED_NODE_TYPES.has(node.type)) {
		throw new UnsupportedNodeError(node.type, node.loc ?? undefined, sourceCode);
	}
}

/**
 * Check if an identifier is a dangerous global.
 * @throws SecurityError if the identifier is dangerous
 */
export function validateIdentifier(
	name: string,
	_allowedVariables: Set<string>,
	node: Node,
	sourceCode: string,
): void {
	if (DANGEROUS_GLOBALS.has(name)) {
		throw new SecurityError(name, node.loc ?? undefined, sourceCode);
	}
}

/**
 * Validate a function call expression.
 * @throws SecurityError if the call is dangerous
 */
export function validateCallExpression(node: CallExpression, sourceCode: string): void {
	// Check for dangerous patterns like eval("...")
	if (node.callee.type === 'Identifier') {
		const name = node.callee.name;
		if (name === 'eval') {
			throw new SecurityError('eval()', node.loc ?? undefined, sourceCode);
		}
		if (name === 'Function') {
			throw new SecurityError('Function()', node.loc ?? undefined, sourceCode);
		}
		if (name === 'require') {

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Remove the blocked global reference — compute the value at runtime in a Code node or via an n8n expression ($json, $now, $today).
  2. For Date/now: use the $now or $today helpers inside expr() instead of `new Date()`.
  3. For JSON: only JSON.stringify is allowed; for parsing, do it in a Code node.
  4. For configuration: pass values as node parameters resolved at runtime, not via process.env in builder code.

Example fix

// before
const delay = setTimeout(() => {}, 100);
const env = process.env.MY_KEY;

// after (move to runtime Code node)
// In SDK builder: declare a parameter placeholder
export default workflow()
  .add(node('Set').parameters({ key: '={{ $env.MY_KEY }}' }));
Defensive patterns

Strategy: validation

Validate before calling

import { DANGEROUS_GLOBALS } from '@n8n/workflow-sdk/ast-interpreter/validators';

function findDangerousIdents(code: string): string[] {
  const found = new Set<string>();
  for (const name of DANGEROUS_GLOBALS) {
    const re = new RegExp(`\\b${name}\\b`);
    if (re.test(code)) found.add(name);
  }
  return [...found];
}

Type guard

import { DANGEROUS_GLOBALS } from '@n8n/workflow-sdk/ast-interpreter/validators';

function isDangerousGlobal(name: string): boolean {
  return DANGEROUS_GLOBALS.has(name);
}

Try / catch

import { interpretSDKCode } from '@n8n/workflow-sdk/ast-interpreter/interpreter';
import { SecurityError } from '@n8n/workflow-sdk/ast-interpreter/errors';

try {
  interpretSDKCode(code, sdkFunctions);
} catch (e) {
  if (e instanceof SecurityError && !/[()]/.test(e.pattern)) {
    // e.pattern is the bare identifier name; show BUILDER_BLOCKED_GLOBALS alternative
  }
  throw e;
}

Prevention

When it happens

Trigger: Referencing `process.env.X`, `console.log(...)`, `globalThis`, `require('...')`, `setTimeout(...)`, `new Date()`, `Math.random()`, `Buffer.from(...)`, `Promise.resolve()`, or any other blocked global as a bare identifier in SDK builder code.

Common situations: Pasting Node.js code that reads process.env; debugging with console.log; using Date/ Math/ JSON.parse (only JSON.stringify is whitelisted via getSafeJSONMethod); Promise-based code; accessing window/document in shared snippets.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/4c3540964e12773a. Report an issue: GitHub.