Why we use fixed rules instead of asking an LLM to review your code
An LLM review gives a different answer every run. That is fine for advice and bad for a safety check. Here is why SixthWall uses deterministic rules, what that costs, and what we do about it.
If you ask a language model to review a file for security problems three times, you get three different lists. Usually good lists. But different. Sometimes the SQL injection is in all three. Sometimes it is in two. That is a fine property for a reviewer you argue with and a bad property for something you want to trust before you ship.
SixthWall does not ask a model to find vulnerabilities. It runs a fixed set of rules against your code. Same input, same result, every time. This post is about why we chose that and what it costs.
What a fixed rule is
A rule is a pattern plus an explanation. The pattern says what shape of code to flag, for example "a call to jwt.sign whose options do not include expiresIn". The explanation says what is wrong, what an attacker could do, and the smallest change that fixes it, written for someone who has never heard of a JWT.
The code is parsed into a syntax tree first, so the rule looks at structure, not just text. That is what lets it tell a real jwt.sign call from the same words in a comment.
Why this is the right tool for a safety check
It does not get tired or creative. The tenth file gets exactly the same attention as the first. The rule fires or it does not.
You can test it. Every rule ships with code that must trigger it and code that must not. When a rule is wrong, we fix the rule and the fix holds forever. You cannot unit-test a prompt in the same way.
It runs in milliseconds, offline, for free. No API call, no key, no waiting, no code leaving your machine. That makes it cheap enough to run on every save and every commit, which is where it does the most good.
The output is stable enough to build on. A score only means something if the same code gives the same score tomorrow. A pre-commit hook only helps if it blocks the same things every time.
What it costs
Fixed rules only find what someone wrote a rule for. They will not notice that your billing logic lets a user set their own price, because no pattern describes that. They also produce false alarms when code is correct but unusual, and we have work to do there: the current rules match one line at a time, which makes them trip on code formatted across several lines. That is being fixed.
An LLM review is better at exactly the things rules are bad at: reasoning about intent, spotting a novel mistake, reading a whole feature and noticing the part that is missing.
So use both
This is why SixthWall is built to complement Claude Code's built-in security review rather than replace it. Run the model's review when you want judgement. Run the rules all the time for the mistakes that are common enough to have a name. When the two disagree, the rule is usually right about the specific line and the model is usually right about the bigger picture.
Where the rules come from
Every rule targets a mistake we have seen AI-generated code make repeatedly: hardcoded keys, secrets in the browser bundle, routes that never check who is asking, queries built from user input, tokens that never expire. There are fifteen today for JavaScript and TypeScript, listed with examples on the rules page. The next batch targets the Supabase and Firebase patterns that show up in Lovable and Bolt projects, because that is where the most serious mistakes are right now.
If you want to see what the rules say about your project, it is one command and it runs locally:
npx @sixthwall/cli init