Module

sandbox

Sandboxed template execution for untrusted templates.

Restricts attribute access, function calls, and imports to prevent untrusted templates from accessing sensitive data or executing arbitrary code.

Usage::

from kida import SandboxedEnvironment

env = SandboxedEnvironment()
# Templates cannot access __dunder__ attributes, call unsafe functions,
# or import modules.
env.from_string("{{ user.name }}").render(user=user)  # OK
env.from_string("{{ user.__class__ }}").render(user=user)  # blocked

Custom policy::

from kida.sandbox import SandboxPolicy, SandboxedEnvironment

policy = SandboxPolicy(
    allowed_attributes={"name", "title", "items", "keys", "values"},
    blocked_types={type, type(lambda: 0)},
)
env = SandboxedEnvironment(sandbox_policy=policy)

Classes

SandboxPolicy 8
Configuration for sandbox restrictions.

Configuration for sandbox restrictions.

Attributes

Name Type Description
allowed_attributes frozenset[str] | None

If set, only these attribute names are accessible (plus safe collection methods). If None, all non-blocked attributes are allowed.

blocked_attributes frozenset[str]

Additional attribute names to block (merged with the built-in blocked set).

blocked_types frozenset[type]

Object types that cannot be accessed at all. Default blocks function, type, and code objects.

allow_import bool

Whether__import__is available. Default: False.

allow_mutating_methods bool

Whether mutating collection methods (append, pop, clear, etc.) are accessible. Default: False.

allow_calling frozenset[str] | None

Set of type names whose instances may be called. If None (default), all callables obtained via attribute access are allowed. Pass an empty frozenset to block all calls.

max_output_size int | None

Maximum render output length in characters. None means unlimited.

max_range int

Maximum range() size. Default: 10000.

SecurityError 1
Raised when a sandbox policy violation is detected. Includes an error code and actionable suggesti…

Raised when a sandbox policy violation is detected.

Includes an error code and actionable suggestion for resolving the violation. All security errors inherit from TemplateError, so they are caught byexcept TemplateError.

Example::

SecurityError: Access to attribute '__class__' is blocked by sandbox policy
  Hint: Remove the attribute access, or add '__class__' to
        SandboxPolicy(allowed_attributes=...) if you trust this template.
  Docs: https://lbliii.github.io/kida/docs/errors/#k-sec-001

Methods

Internal Methods 1
__init__ 3
def __init__(self, message: str, *, code: ErrorCode | None = None, suggestion: str | None = None)
Parameters
Name Type Description
message
code Default:None
suggestion Default:None
SandboxedEnvironment 2
Environment subclass that enforces sandbox restrictions. All templates compiled by this environmen…

Environment subclass that enforces sandbox restrictions.

All templates compiled by this environment use sandboxed attribute access, restricted builtins, and policy-enforced limits.

The sandbox intercepts:

  • Attribute access (blocks dunder, unsafe types)
  • __import__(disabled by default)
  • range()(size-limited)
  • Template output (optional size limit)

Example::

env = SandboxedEnvironment()
tmpl = env.from_string("{{ user.name }}")
tmpl.render(user={"name": "Alice"})  # OK

tmpl = env.from_string("{{ user.__class__.__mro__ }}")
tmpl.render(user="hello")  # raises SecurityError

Custom policy::

from kida.sandbox import SandboxPolicy
policy = SandboxPolicy(allowed_attributes=frozenset({"name", "email"}))
env = SandboxedEnvironment(sandbox_policy=policy)

Attributes

Name Type Description
sandbox_policy SandboxPolicy | None

Methods

Internal Methods 1
__post_init__ 0
def __post_init__(self) -> None

Functions

_is_attr_blocked 2 bool
Check if an attribute name is blocked by the policy.
def _is_attr_blocked(name: str, policy: SandboxPolicy) -> bool
Parameters
Name Type Description
name str
policy SandboxPolicy
Returns
bool
_is_type_blocked 2 bool
Check if an object's type is blocked.
def _is_type_blocked(obj: object, policy: SandboxPolicy) -> bool
Parameters
Name Type Description
obj object
policy SandboxPolicy
Returns
bool
_make_sandboxed_getattr 1
Create a sandboxed version of safe_getattr.
def _make_sandboxed_getattr(policy: SandboxPolicy)
Parameters
Name Type Description
policy SandboxPolicy
_make_sandboxed_getattr_none 1
Create a sandboxed version of getattr_preserve_none.
def _make_sandboxed_getattr_none(policy: SandboxPolicy)
Parameters
Name Type Description
policy SandboxPolicy
_make_sandboxed_range 1
Create a range() that enforces max_range.
def _make_sandboxed_range(policy: SandboxPolicy)
Parameters
Name Type Description
policy SandboxPolicy
_make_sandboxed_call 1
Create a call interceptor that blocks unsafe callables. When ``policy.allow_ca…
def _make_sandboxed_call(policy: SandboxPolicy)

Create a call interceptor that blocks unsafe callables.

Whenpolicy.allow_callingis None, all callables are permitted (attribute-level checks are still enforced). When set to a frozenset of type names, only instances of those types may be called. Blocked types (function, type, code) are always denied.

Parameters
Name Type Description
policy SandboxPolicy
patch_template_namespace 2 None
Patch a template namespace dict to enforce sandbox restrictions. Called by Tem…
def patch_template_namespace(namespace: dict[str, Any], policy: SandboxPolicy) -> None

Patch a template namespace dict to enforce sandbox restrictions.

Called by Template.init when the environment is a SandboxedEnvironment. Replaces unsafe functions with sandboxed versions.

Parameters
Name Type Description
namespace dict[str, Any]
policy SandboxPolicy