keepcalculator

06 Numbers and Powers

Safer LLM Code Starts With Layered Validation

Card No. 06·58179 · Updated · Standard formula, shown below

Yes: safer code produced by a large language model (LLM) starts with layered validation, not with rewriting its abstract syntax tree (AST) as a blanket safety measure. AST inspection or transformation can help in specific, well-defined cases, but it cannot establish that code is safe; validation should combine clear requirements, constrained execution, tests, and review.

Why AST rewriting is not a safety boundary

An AST represents source code as structured elements such as calls, names, expressions, and statements. That structure is useful: a tool can detect a call to a disallowed function or transform a supported expression without relying on fragile text matching. But inspecting or changing that representation does not, by itself, make arbitrary code safe.

There are several reasons. A rule may miss a behavior expressed through a different construct, a library, or a runtime feature. A rewrite may change what the program does, introduce a bug, or fail to handle a language feature correctly. And even code that passes a static check can consume excessive memory, run indefinitely, access files, or make network requests when executed.

AST controls are therefore best treated as one layer of a system, not as a substitute for isolation or evidence that the output meets its requirements. This applies especially when model-generated code is executed automatically or handles untrusted inputs.

What layered validation means

Layered validation checks different kinds of risk at different points. Each layer answers a narrower question; no single pass can answer all of them. A practical pipeline might include:

  • Specify the task: Define expected inputs, outputs, side effects, and failure behavior before asking for code. Clear constraints make checks more meaningful.
  • Check structure: Parse the code and reject syntax errors. Where appropriate, inspect the AST for prohibited constructs or require a limited subset of the language.
  • Check style and types: Run a formatter, linter, or type checker if the language and project support them. These tools catch certain inconsistencies, not every runtime or security defect.
  • Test behavior: Run unit tests and tests for edge cases, invalid inputs, and expected failures. Add integration tests when the code interacts with other components.
  • Execute under limits: Use an isolated environment with narrowly granted permissions, resource limits, and no unnecessary access to files, credentials, or network services.
  • Review the result: Inspect changes and test results before deployment, with closer scrutiny for code that changes permissions, handles sensitive data, or affects important systems.

The layers should be selected for the actual task. A small generated data transformation does not need the same review process as code that can modify production data.

Where AST checks help

AST-based checks are useful when the policy is specific and the language can be parsed reliably. For example, a tool might accept only arithmetic expressions and reject imports, function definitions, attribute access, or calls outside an explicit allowlist. Another tool might locate calls to a particular API so a reviewer can inspect them.

In these cases, the key is to define the permitted language precisely and fail closed when parsing or policy evaluation fails. Check the exact language and runtime version in use; syntax and semantics can differ across versions. If the goal is to accept a small expression, a purpose-built expression parser may be safer and easier to reason about than attempting to sanitize a complete programming language.

Rewriting an AST can also be appropriate for mechanical transformations, such as adding instrumentation or normalizing a known pattern. The transformed output still needs tests and review: a successful transformation shows that the tool performed its operation, not that the result is correct or safe in every context.

Execution isolation and permissions

When generated code must run, containment addresses risks that static checks cannot reliably rule out. Run it in a separate process or similarly isolated environment, restrict its filesystem view, avoid passing secrets into its environment, and grant only the network or system access the task requires. Set limits for runtime and resource use, and ensure the surrounding system can stop work that exceeds them.

Isolation is not a magic guarantee either. Its effectiveness depends on the operating system, runtime, configuration, and how access is granted. Keep the execution environment maintained, avoid treating a container or virtual machine as automatically secure, and consider whether the output needs to run at all. For many tasks, inspecting or testing generated code without granting it broad capabilities is the safer choice.

Tests, review, and failure handling

Tests should reflect the intended behavior, not merely confirm that one example works. Include boundary cases, malformed inputs, and cases likely to expose unintended side effects. Property-based or fuzz testing may help explore many inputs, but neither replaces a clear specification or targeted tests.

Make failures visible. A parser error, rejected policy check, timeout, or failed test should stop the pipeline or require an explicit decision; it should not silently trigger a weaker validation path. Record what was checked and which code version was checked so reviewers can connect evidence to the actual artifact. Review the final code after any automated rewrite, since tests run on an earlier version do not validate a later one.

A common misconception is that passing a linter or removing a suspicious syntax node proves safety. Such checks establish only that the code passed particular rules. Correctness depends on requirements and tests; security also depends on inputs, permissions, dependencies, runtime behavior, and the environment where the code runs.

Choosing the right validation mix

Choose controls according to what the code can do and the consequence of a mistake. Start by asking whether it is executed, what data and systems it can reach, whether its inputs are trusted, and how easily its effects can be reversed. Then select checks that address those risks directly.

  • For code that is only displayed as a suggestion, syntax checks and human review may be proportionate.
  • For code run against test data, add automated tests and a restricted environment.
  • For code with access to real services or sensitive information, use tighter permissions, isolated testing, change review, and explicit approval before deployment.

Do not rely on an AST rewrite merely because it is easy to automate. If a rule cannot be stated and tested clearly, the rewrite may create confidence without meaningful coverage. Prefer small, auditable controls and treat each validation result as evidence about one specific property.

Frequently Asked Questions

Can an AST validator make generated code safe?
An AST validator can enforce defined structural rules, such as rejecting selected syntax. It cannot prove general safety, correct behavior, or harmless runtime effects. Pair it with testing, isolation, and review.

Is AST rewriting ever useful?
Yes. It can support narrow, well-tested transformations or enforce a deliberately small language. Validate the transformed code and test the behavior afterward rather than treating the rewrite as a security boundary.

What is the difference between parsing and sandboxing?
Parsing checks whether code has a valid structure and may enable structural policy checks. Sandboxing restricts what running code can access or consume. They address different risks and are not interchangeable.

Should generated code be executed automatically?
Only when the workflow has a justified need and suitable controls. Consider whether static inspection or tests on non-sensitive data are enough; if execution is needed, restrict permissions and resources.

Do passing tests prove the code is secure?
No. Tests provide evidence for the cases and properties they cover. They may miss untested inputs, dependency risks, excessive resource use, or unintended access, so use additional controls.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →