Status: Accepted (amended in 1.4.11)
Date: 2026-03-01
Deciders: Project architect
TinyExpression supports embedding a full Java class directly inside a formula field using triple-backtick syntax:
formula:
```java:package.ClassName
// arbitrary Java code
```
At evaluation time, the embedded class is:
- Parsed from the formula body
- Compiled in-memory via
javax.tools.JavaCompiler - Loaded via
MemoryClassLoader(scoped to the formula's class loader) - Instantiated and invoked with the
CalculationContext
FormulaInfo output may contain generated bytecode for backward-compatible serialization and
inspection. That persisted value is not trusted or executed when the document is loaded; the
loader recompiles the formula text under the current policy. Runtime classes are discarded when
their class loader is garbage collected.
The embedded Java code runs with the same permissions as the host JVM process. There is no sandbox. The code can:
- Read and write the file system
- Make network connections
- Call
System.exit() - Access environment variables and system properties
- Instantiate any class visible on the classpath
- Spawn threads
This is intentional — the feature exists to allow advanced integrations with full Java expressiveness. However, it is only safe when the formula author is trusted.
The Java code block feature is retained behind a secure-by-default opt-in policy:
-
Trusted authors only: Java code blocks must only be enabled in environments where formula authors have equivalent trust to application developers.
-
No sandboxing by the engine: TinyExpression does not provide a sandbox. Sandboxing, if required, must be implemented at the JVM level (e.g.,
SecurityManagerreplacement, process isolation, container boundaries) by the host application. -
Explicit documentation: All user-facing documentation (README, language guide, getting-started) must carry an explicit security warning on Java code blocks.
-
Feature isolation: The Java code block compilation path (
TripleBackTickParser,CodeParser,MemoryClassLoader) is distinct from the standard formula path.JavaCodeBlockPolicydisables compilation by default; trusted hosts must explicitly callsetEnabled(true).
Every document that mentions Java code blocks must include this warning:
Warning: Java code blocks compile and execute arbitrary code on the JVM. Only use this feature when formula authors are fully trusted. Do not expose this capability to untrusted users.
- Advanced integrations remain possible — the feature is not removed
- The security model is explicit and documented rather than implied
- Host applications can audit their usage by searching for triple-backtick patterns in
formulaInfo.txtfiles
- A trusted host that opts in can still expose arbitrary JVM capabilities to formula authors
- There is no engine-level protection — all responsibility is on the host application
- The
MemoryClassLoaderscope means compiled classes are not permanently retained, reducing one class of risk (persistent backdoors via compiled classes survive only as long as the class loader)
Remove the feature entirely: Rejected. The feature enables legitimate advanced integrations and was an explicit design choice. Removing it would break existing users without an equivalent replacement.
Add an opt-in flag to enable code blocks: Accepted after the original decision. JavaCodeBlockPolicy was added in v1.4.11 and defaults to disabled. The VS Code DAP exposes the same decision as allowJavaCodeBlocks, also defaulting to false.
Provide a SecurityManager-based sandbox: Rejected. SecurityManager is deprecated and removed in recent Java versions. A meaningful sandbox would require process isolation, which is outside the scope of an embedded expression engine.
- docs/language-guide.md — Java Code Blocks
org.unlaxer.compiler.MemoryClassLoaderorg.unlaxer.tinyexpression.parser.javalang.TripleBackTickParserorg.unlaxer.tinyexpression.parser.javalang.CodeParser