Data Designer can run in two very different trust models:
That distinction matters for features that evaluate user-supplied configuration at runtime, such as Jinja template rendering. In a trusted local workflow, broader template flexibility may be acceptable. In a shared-service deployment, user-supplied Jinja becomes part of the engine’s remote code execution surface. A template sandbox escape would execute inside the process running Data Designer.
See Deployment Options: Library vs. Microservice for the architectures where that trust boundary changes.
Data Designer exposes the renderer choice through RunConfig:
SECURE is the default. Opt into NATIVE only when you are comfortable treating the config author and the engine operator as the same trust domain.
Treat untrusted Jinja as a security boundary
If many users can submit configs to one engine, or if configs are accepted over an API and executed elsewhere, keep JinjaRenderingEngine.SECURE. In that model, Jinja templates are no longer just prompt-formatting helpers. They are untrusted user programs being evaluated by your engine.
NATIVE is not an unrestricted Python template engine. The matrix below shows what each mode permits, restricts, or adds on top of Jinja2’s standard sandbox behavior.
SECURE Adds on Top of Standard Jinja SandboxThe SECURE renderer uses a hardened environment implemented in the renderer source file on GitHub. Compared with the standard Jinja sandbox, it adds several additional controls.
Before rendering, SECURE forces template context through a JSON-compatible serialization step. That means remote templates operate on plain data, not arbitrary Python objects.
In a remote execution setting, exposing rich Python objects increases the risk of attribute- and method-based sandbox escapes. Jinja’s sandbox security considerations note that the sandbox is not a complete security boundary, and past escapes have included str.format (CVE-2016-10745), str.format_map (CVE-2019-10906), indirect str.format references (CVE-2024-56326), and |attr-based access to format (CVE-2025-27516); PortSwigger’s server-side template injection research covers the broader object-traversal pattern.
SECURE keeps only a small approved subset of Jinja filters plus the Data Designer jsonpath filter. If a filter is not on that allowlist, the template is rejected. Common excluded filters are:
Some omitted convenience filters, such as the e alias for escape, are excluded because SECURE uses a small explicit allowlist. The current implementation does not assign each omitted filter its own separate security rationale.
Use NATIVE when full Jinja filter compatibility matters more than the additional restrictions used for untrusted template execution.
SECURE rejects import, macro, set, extends, and block.
Those features are useful in trusted authoring environments, but they also make user templates more expressive and stateful. In a remote execution model, SECURE intentionally narrows the language so templates stay closer to data interpolation than to a reusable programming layer.
SECURE rejects recursive loops and nested for loops.
Nested and recursive loops are especially risky in shared execution because they can amplify compute cost and output size in ways that are hard to reason about from the outside.
SECURE statically analyzes the parsed Jinja AST and rejects templates that exceed the current limits of 600 nodes or depth 10.
This is not about any one feature being unsafe by itself. It is about limiting how much control flow and composition untrusted templates can pack into a single server-side render operation, which helps prevent compute bombs in shared execution.
self References BlockedSECURE rejects references to self.
The point is to avoid exposing template internals back to the submitter. In a remote setting, even accidental access to those internals is unnecessary surface area.
SECURE validates rendered output after template execution. It rejects empty output, very large output, and strings that look like Python built-in or function representations.
These checks matter because not all bad outcomes come from parse-time behavior. Some templates are syntactically valid but still produce output that is clearly broken, oversized, or revealing internal implementation details.
At the engine boundary, SECURE normalizes most template failures into a generic invalid-template message.
That matters in remote execution because exception details can leak information about server-side implementation, supported objects, or internal execution paths that untrusted users do not need to see.
These controls exist because the standard sandbox is a good baseline, but shared-service deployments need a narrower and more defensive execution model.
The security posture changes as soon as config submission and execution are separated.
Examples:
In those environments, templates are no longer just local convenience syntax. They are untrusted input being evaluated by infrastructure the submitter does not control. In practice, that makes Jinja rendering a remote code execution concern, which is why SECURE exists and why it remains the default.
If you are deciding between local library usage and a shared service model, read Deployment Options: Library vs. Microservice. The library patterns are often still “trusted” deployments. The shared microservice pattern is not.
NATIVEUse NATIVE when all of the following are true:
SECURE allows.For example, this is often reasonable in a notebook, local script, or other single-user library workflow.