DEV Community

Cover image for We stopped letting the AI write code. We let it write an AST instead.
Barnabas Olugbogi
Barnabas Olugbogi

Posted on

We stopped letting the AI write code. We let it write an AST instead.

Every AI coding tool has the same security model, and the model is "a human will read it."

The model writes source code. You skim it. You run it. Your only real defense is code review, and anyone who has reviewed generated code knows attention collapses somewhere around file four.

That works fine when the output is a React component. It works considerably less fine when the output is server-side code with database credentials in scope.

We took a different route, and I want to describe it because the idea generalizes beyond our product.

1. Constrain the output language, not the model

Hyperlambda is an executable AST. The model does not emit source code that we then parse and hope about. It emits nodes in a tree, and the runtime executes that tree directly.

The important property: only whitelisted node types exist.

There is no node that shells out. Not disabled, not sandboxed, not blocked by a policy layer that someone can misconfigure. The operation is absent from the language.

So the classic failure mode, where a model gets talked into generating something destructive, does not have a landing place. You cannot prompt-inject your way into rm -rf when the grammar has no concept of a shell.

2. Why this is different from sandboxing

Sandboxing is subtractive. You start with a general purpose runtime that can do everything, then you spend the rest of your life removing capabilities and patching the ones you missed. Every escape is a thing that was there by default and got overlooked.

Whitelisting is additive. You start with nothing and add operations deliberately. An escape requires a bug in something we explicitly built, not something we forgot to remove.

Both approaches have failure modes. The difference is what a mistake costs you. Forgetting to remove a capability is a breach. Forgetting to add one is a support ticket.

3. The validation step you get for free

Because the output is a tree rather than text, you can inspect it before execution. Not with a regex over source code, which is a losing game, but structurally.

Which nodes does this use. What does it touch. Does it read from a table it has no business reading from.

That check is deterministic and it runs in milliseconds. Try writing the equivalent for arbitrary generated Python.

4. What we built on top of it

The practical result is that you can describe an application in plain English and get a real backend without a review bottleneck. Database over SQLite, MySQL, PostgreSQL or SQL Server. Secured CRUD REST APIs. Auth including Google, GitHub, OAuth and OIDC. SPA hosting. Scheduled tasks.

Generated in minutes, and safe to execute because the language it generates into cannot express the dangerous things.

5. The test

Architectural claims deserve testing rather than trust, so there is a standing bounty for escaping the sandbox. It has not been claimed.

The runtime is MIT licensed if you want to read it or run it yourself: hyperlambda.dev

Happy to argue about the tradeoffs in the comments. The obvious cost of this approach is expressiveness, and I do not think that objection is wrong.

Top comments (1)

Collapse
 
polterguy profile image
Thomas Hansen

"Stop writing code" for an AI-based code generator ^_^