n8n-io/n8n · error · SecurityViolationError

Security violations detected

Error message

Security violations detected

What it means

Thrown by TaskAnalyzer.validate when the AST-based static security scan of Python user code detects one or more security violations. The SecurityValidator walks the parsed AST and collects violation descriptions; if any are found, they are joined with newlines and passed as the description of a SecurityViolationError. This is a pre-execution static analysis pass that catches dangerous patterns before the code runs in the subprocess.

Source

Thrown at packages/@n8n/task-runner-python/src/task_analyzer.py:363

            self._cache.move_to_end(cache_key)

            if len(cached_violations) == 0:
                return

            self._raise_security_error(cached_violations)

        tree = ast.parse(code)

        security_validator = SecurityValidator(self._security_config)
        security_validator.visit(tree)

        self._set_in_cache(cache_key, security_validator.violations)

        if security_validator.violations:
            self._raise_security_error(security_validator.violations)

    def _raise_security_error(self, violations: CachedViolations) -> None:
        raise SecurityViolationError(
            message="Security violations detected", description="\n".join(violations)
        )

    def _to_cache_key(self, code: str) -> CacheKey:
        code_hash = hashlib.sha256(code.encode()).hexdigest()
        return (code_hash, self._allowlists)

    def _set_in_cache(self, cache_key: CacheKey, violations: CachedViolations) -> None:
        if len(self._cache) >= MAX_VALIDATION_CACHE_SIZE:
            self._cache.popitem(last=False)  # FIFO

        self._cache[cache_key] = violations.copy()
        self._cache.move_to_end(cache_key)

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Read the SecurityViolationError description to see which specific patterns were flagged.
  2. Remove or replace dangerous constructs: use direct imports instead of __import__, avoid eval/exec.
  3. If the flagged construct is legitimate, refactor to an explicitly allowed alternative.
  4. Adjust the security allowlist if the code is trusted and the pattern is a false positive (consult your security policy first).

Example fix

# before — flagged by analyzer
import os
os.system('rm -rf /tmp/test')
getattr(os, 'sys' + 'tem')('whoami')

# after — use allowed APIs
# Use the HTTP Request node or an allowed module instead
import json
result = json.dumps({'key': 'value'})
Defensive patterns

Strategy: validation

Validate before calling

import ast

def pre_validate_code(code: str) -> list[str]:
    """Check for obvious security violations before submission."""
    violations = []
    tree = ast.parse(code)
    for node in ast.walk(tree):
        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Name) and node.func.id in ('eval', 'exec', 'compile'):
                violations.append(f'Use of {node.func.id}() is not allowed')
        if isinstance(node, ast.Attribute) and node.attr.startswith('_'):
            violations.append(f'Access to {node.attr} is not allowed')
    return violations

issues = pre_validate_code(user_code)
if issues:
    raise ValueError('Security issues: ' + '; '.join(issues))

Try / catch

from task_analyzer import TaskAnalyzer
from _sandbox_callables import SecurityViolationError

try:
    analyzer.validate(code)
except SecurityViolationError as e:
    print(f'Security violations: {e.description}')
    # show violations to user for correction

Prevention

When it happens

Trigger: Python Code Node code is submitted for execution. TaskAnalyzer.validate parses it into an AST, runs SecurityValidator.visit(tree), and the validator flags constructs like dangerous attribute access, use of eval/exec, access to dunder attributes, or calls to forbidden functions. The violations list is non-empty, triggering _raise_security_error.

Common situations: User code accesses __import__, __builtins__, or other dunder attributes to bypass sandboxing. Code uses eval(), exec(), compile(), or getattr for dynamic attribute access on sensitive objects. AST patterns matching known escape vectors from the sandbox. The allowlist is restrictive and the code uses introspection or metaprogramming.

Related errors


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