n8n-io/n8n · error · SecurityViolationError
String pattern accessing '{attr}' is disallowed, because it
Error message
String pattern accessing '{attr}' is disallowed, because it can be used to bypass security restrictions. What it means
Thrown by _validate_format_template in the Python task executor when a str.format, str.format_map, or f-string-equivalent template contains a field access pattern that the security scanner considers dangerous. The find_blocked_format_tokens generator scans the format template for attribute chains (e.g. {0.__class__.__init__}) that could be used to traverse the Python object model and bypass sandbox restrictions. This blocks format-string attacks at execution time.
Source
Thrown at packages/@n8n/task-runner-python/src/task_executor.py:93
):
replacement = ast.Call(
func=ast.Name(id=EXECUTOR_SAFE_FORMAT_KEY, ctx=ast.Load()),
args=[
ast.Constant(value=node.func.attr),
node.func.value,
*node.args,
],
keywords=node.keywords,
)
return ast.copy_location(replacement, node)
return node
def _validate_format_template(template: str) -> None:
token = next(find_blocked_format_tokens(template), None)
if token is not None:
raise SecurityViolationError(
description=ERROR_DANGEROUS_STRING_PATTERN.format(attr=token),
)
def _validate_field_expression(expr: str) -> None:
# Wrap as a complete template so the existing parser can scan it.
_validate_format_template("{" + expr + "}")
_TEMPLATE_METHODS = frozenset({"format", "format_map", "vformat"})
_FIELD_METHODS = frozenset({"get_field"})
def _resolve_template_arg(method_name: str, receiver, args):
"""Return ``(template, field)`` for the call: at most one element is
non-``None``. Normalises bound and unbound call forms so the same
validation runs for both ``"tpl".format(...)``, ``str.format("tpl", ...)``,
``Formatter().format("tpl", ...)``, and ``Formatter.format(f, "tpl", ...)``.View on GitHub (pinned to 5ac6606e81)
Solutions
- Avoid attribute access in format strings — use positional or named fields without dots: '{name}' instead of '{obj.name}'.
- Pre-compute any values you need and pass them as simple arguments rather than traversing objects in the template.
- If you need object attribute access, do it in regular Python code before formatting, not inside the template string.
- Review ERROR_DANGEROUS_STRING_PATTERN to understand which tokens are blocked.
Example fix
# before — blocked attribute traversal in format string
result = '{0.__class__.__name__}'.format(my_object)
# after — compute the value separately
result = type(my_object).__name__
template = '{}'.format(result) Defensive patterns
Strategy: validation
Validate before calling
import re
BLOCKED_PATTERN = re.compile(r'\{[^}]*\.__\w+')
def is_safe_format_template(template: str) -> bool:
return not BLOCKED_PATTERN.search(template)
# check before using
template = '{0.__class__}'
if not is_safe_format_template(template):
raise ValueError('Format template contains blocked attribute access') Try / catch
from task_executor import SecurityViolationError
try:
result = my_template.format(obj)
except SecurityViolationError as e:
# rewrite the template to avoid attribute access
name = type(obj).__name__
result = f'{name}' # use pre-computed values Prevention
- Never use attribute access (dots) in format string templates.
- Pre-compute values in regular code and pass them as simple arguments to format().
- Avoid user-controlled input in format string templates.
- Use f-strings or % formatting with simple values instead of complex format templates.
When it happens
Trigger: Python user code calls '{0.__class__}'.format(obj), '{0.__class__.__mro__}'.format(obj), obj.format('{x.__init__}', x=obj), or any string formatting that uses dot-access to reach dunder or internal attributes. The FormatGuardTransformer rewrites format calls to route through _validate_format_template, which scans the template and finds a blocked token.
Common situations: Using format strings with attribute access for legitimate introspection that happens to touch blocked attributes. Attempting format-string-based sandbox escape by walking __class__.__mro__.__subclasses__(). Dynamic template generation from user-controlled input that includes attribute paths.
Related errors
- Security violations detected
- Security violation detected
- Module '${moduleName}' is disallowed
- Wildcard '*' in {list_name} must be used alone, not with oth
- read-only
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/62cb8232b82d919b.
Report an issue: GitHub.