twigphp/Twig · error · SecurityNotAllowedPropertyError
Calling " " property on a " " object is not allowed.
Error message
Calling "%s" property on a "%s" object is not allowed.
What it means
checkPropertyAllowed() throws SecurityNotAllowedPropertyError when sandboxed code accesses an object property that is not allowlisted for that object's class in $allowedProperties. The sandbox invokes this check before any property read on template objects.
Solutions
- Allow the property: $policy->setAllowedProperties([MyClass::class => ['prop', ...]]) or extend the constructor's $allowedProperties array.
- Catch SecurityNotAllowedPropertyError to report the class and property and update the allowlist.
- Pass only explicitly whitelisted view-models into sandboxed templates.
- Prefer allowed getter methods over raw property access if methods are already allowlisted.
Example fix
// before $policy = new SecurityPolicy($tags, $filters, [], [], []); // User::$name blocked // after $policy->setAllowedProperties([User::class => ['name', 'email']]);
Defensive patterns
Strategy: try-catch
Validate before calling
if (!isset($allowedProperties[$obj::class]) || !in_array($prop, $allowedProperties[$obj::class], true)) {
// access would throw; adjust policy
} Type guard
function propertyAllowed(object $obj, string $prop, array $allowedProperties): bool {
return in_array($prop, $allowedProperties[$obj::class] ?? [], true);
} Try / catch
try {
$html = $twig->render($tpl, ['user' => $userObj]);
} catch (\Twig\Sandbox\SecurityNotAllowedPropertyError $e) {
$logger->warning('Sandbox blocked property', ['class' => $e->getClassName(), 'property' => $e->getPropertyName()]);
} Prevention
- Whitelist only the exact properties templates read.
- Prefer allowlisted accessor methods over raw property access.
- Convert domain entities into DTO view-models for sandboxed rendering.
- Add a sandbox regression test per exposed class.
When it happens
Trigger: A sandboxed template accesses $obj->property (directly or via {{ obj.prop }} / attribute()) where the class/property pair is missing from the policy's $allowedProperties map.
Common situations: Exposing new entities/DTOs to sandboxed templates without extending the property whitelist; refactoring classes so a formerly public property is accessed differently; strict tenant isolation policies rejecting unexpected property access.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Tag " " is not allowed.
- Filter " " is not allowed.
- Function " " is not allowed.
- Test " " is not allowed.
- Calling " " method on a " " object is not allowed.
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/72c6076c446675cd.
Report an issue: GitHub.
Appendix: source
Thrown at src/Sandbox/SecurityPolicy.php:180
if (!$allowed) {
$class = $obj::class;
throw new SecurityNotAllowedMethodError(\sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method);
}
}
public function checkPropertyAllowed($obj, $property): void
{
$allowed = false;
foreach ($this->allowedProperties as $class => $properties) {
if ($obj instanceof $class && \in_array($property, \is_array($properties) ? $properties : [$properties], true)) {
$allowed = true;
break;
}
}
if (!$allowed) {
$class = $obj::class;
throw new SecurityNotAllowedPropertyError(\sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property);
}
}
}
View on GitHub (pinned to a414c3a491)