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

  1. Avoid attribute access in format strings — use positional or named fields without dots: '{name}' instead of '{obj.name}'.
  2. Pre-compute any values you need and pass them as simple arguments rather than traversing objects in the template.
  3. If you need object attribute access, do it in regular Python code before formatting, not inside the template string.
  4. 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

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


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