Unvalidated Executed Output is an AI code smell, a sign of trouble in LLM systems, in the Security group. Code, SQL, or commands generated by the model run directly, with no check or sandbox.
@pytest.fixture(autouse=True)def cleanup(): yield shutil.rmtree("tests/fixtures") # "clean up temporary files"
The test ran in the real repository directory, on the CI machine, with write access. The fixtures folder, used by every other test, was gone.
Signs of Unvalidated Executed Output:
Code, SQL, shell commands, or queries generated by the model run directly.
Execution happens in the real environment: the application server, the repository, the production database.
Nothing checks what was generated before it runs (parser, command allowlist, static analysis).
The executing process has access to network, secrets, or files it does not need.
There is no limit on time, memory, or file system.
flowchart LR
M(["1. Model generates code"]):::llm --> X["2. Runs directly"]:::tool
X --> R[("3. Repository, database, network, secrets")]:::store
The model generates something executable.
The code runs without passing any check.
It has access to everything the process that ran it has.
The model’s output carries everything that went into the context, including a comment planted in a file. Treat that output as untrusted input, the same way you would treat a form filled in by a stranger.
Reasons
Running it is how you check it. To know whether the test works, you have to run it. Isolation gets left for later.
Generated code looks harmless. Most of the time, it is.
Sandboxes take work. Containers, permissions, and limits need infrastructure the prototype did not have.
The CI environment seems disposable. Until it holds deploy secrets.
Cost of ignoring
Local damage: deleted files, altered data, crashed processes.
Leaks: generated code that reads environment variables and sends them out.
Injection: an instruction in a file the agent reads becomes code executed with the system’s access.
Resources: infinite loops or memory use bring the machine down.
Always. Check what was generated (parser, allowlist, static analysis) and run it in an isolated, disposable environment, with no network and no secrets, under limits. Targets: Output Validation and Repair and Code Execution Sandbox.
A denylist that blocks rm -rf misses shutil.rmtree, os.remove in a loop, or find . -delete. An allowlist says what may run; everything else is refused. And even allowed code still runs in an isolated environment, so what slips through cannot reach secrets or the real repository.
Payoff
The worst case of bad code is a destroyed container.
Commands outside the allowlist never run.
Secrets and network stay out of reach of generated code.
Validation errors become information the model can use to fix things.
When to ignore
An environment that is already isolated. A provider’s code execution service, or a network-less container created per session, is already the protection. Check what it allows.
Human review before each execution. A developer who reads and approves every command in the terminal.
Is it this smell?
Quick answers
What is Unvalidated Executed Output?
Unvalidated Executed Output is an AI code smell, a sign of trouble in LLM systems, in the Security group. Code, SQL, or commands generated by the model run directly, with no check or sandbox.
How do you fix Unvalidated Executed Output?
With Validate Before Execute. Each refactoring has safe step-by-step mechanics with an eval before and after.
Where does Unvalidated Executed Output show up in practice?