Engineering

A client-side code check runs before the diff exists.

Half the code that gets reviewed now arrives from a prompt, a snippet in a chat window, or a prototype with no repository behind it. A check that needs repo access, a token and a pipeline cannot help with any of that.

Why paste instead of push

Server-side scanning assumes a repository, a branch and a pipeline. That assumption holds for code that already lives somewhere your tooling can reach. It does not hold for a function pasted out of an assistant, a vendor's example file, a prompt fragment being evaluated, or a prototype that will never be committed in its current shape.

A client-side check closes that gap. The file is pasted into a page, the rules run on the text, and the answer arrives before you have decided whether the code is worth keeping.

It also removes a quiet friction. Nobody wants to add a dependency, request a token or open a pull request to find out whether a snippet is safe to run, so in practice nobody checks. Making the check free and instant is most of the value.

What the code rules actually look for

The rules are grouped around the ways assistant-written code fails in production rather than around language style.

  • Credentials in source: API keys, tokens, private key blocks and passwords assigned as literals, including the ones left in comments and example files that get copied into a real config.
  • Unsafe execution: eval, the Function constructor, document.write, HTML assigned to innerHTML, shell commands reachable from app code, and SQL strings assembled by concatenation.
  • Swallowed failure: empty catch blocks and bare handlers that turn an error into a default value, which is how generated code most often looks robust while doing nothing.
  • Debug residue: console statements, debugger lines, TODO, FIXME and placeholder markers that survived the prompting loop.
  • Structural problems: loose equality, brackets that do not balance, source that does not parse, duplicated line blocks, and a line longer than 260 characters.
  • HTML and markup: images without alt text, a root element with no lang attribute, no viewport meta tag, and links pointing at a bare hash.

How to read a finding without overreacting

Every finding carries a severity and the line that triggered it. Read the line before you read the advice, because a rule matches a pattern, not an intention: a key-shaped string in a test fixture is still worth knowing about, but it is a different conversation from one in application code.

Weight the category. A plausible secret is a rotation and a history rewrite. An unescaped interpolation is a vulnerability class. A console statement is a minute of cleanup. The report is ordered so the first group cannot hide behind the third.

Where you disagree with a rule, write down why. That is the beginning of your own house rule set, and it is also the material a reviewer needs when they look at the same file with more context.

Invented APIs and the version you actually have

The most expensive generated defect is not a syntax error. It is a call to a method that does not exist on the version of the library you are pinned to, written with total confidence and no autocomplete to contradict it.

A single-file check can catch the shape of the problem, such as imports that resolve to nothing inside the pasted file, and cannot check the rest because it has no notion of your installed versions.

That is a deliberate division of labour. Mechanical patterns run in the tab; dependency truth and runtime behaviour belong to your build, your type checker and your tests. The console is the first filter, not the last line of defence.

A routine that survives a busy week

Check the snippet before you paste it into the file. Thirty seconds at that moment beats discovering a committed key in review, and it costs nothing because there is no account in the way.

Check the diff before the pull request, and attach the report when the change touches authentication, payments, data deletion or anything a customer can reach. The reviewer then starts from the findings rather than from a blank page.

Check the whole file rather than the changed lines when the assistant rewrote it. Generated refactors tend to smuggle removed error handling into untouched-looking sections, and a diff-only view hides that by design.

Where the check has to become a person

The tab cannot see the rest of your system. It does not know whether the endpoint you call is idempotent, whether the null you guard against can occur, or whether the authorisation on the route above yours is correct.

For those changes the escalation is a named engineer who reads the file in the context of the codebase, requests fixes and signs the verdict. They start with your automated report, so the expensive hour goes to the part that needed judgement.

That is the boundary worth keeping: patterns are cheap and should be automated, judgement is expensive and should be attributed.

What to paste, and what to keep out

Paste the whole file when you can. A fragment loses the imports, the surrounding error handling and the context that decides whether a finding matters, and the report is correspondingly less useful. The console handles a long file comfortably; it truncates at 200,000 characters and says so when that happens.

Leave out production data. A check does not need the customer table to tell you the query string is concatenated, and pasting real records into any tool creates a problem that no finding will fix. Substitute an example row with the same shape.

Treat a real credential as already compromised. If a key appears in a generated file, rotate it, revoke it and clean the history; running the check is how you found out, not the remedy. The finding is the beginning of an incident, and the label the pattern matched tells you which system to rotate first.

Finally, paste the file the assistant produced, not your tidied version. The value of the check comes from measuring what actually exists in the branch, and a cleaned-up paste will report a file you do not have.

What this covers

  • Secrets and keys

    Literals in source and in comments, flagged with the label the pattern matched.

  • Rendering safety

    innerHTML, document.write and unescaped interpolation into markup.

  • Error handling

    Empty catch blocks that convert a failure into a plausible default.

  • Parse and structure

    Source that does not parse, unbalanced brackets, duplicated blocks.

  • Markup basics

    Missing alt text, lang, viewport and links that point at a bare hash.

Questions this page usually raises

Does the check need access to my repository?
No. You paste the file or function and the rules run on that text in the browser. Nothing is cloned and no token is requested.
Which languages does it understand?
The pattern rules are language-agnostic over text, with a JavaScript parse check. TypeScript, Python, SQL and HTML all get the pattern and markup rules; only JavaScript gets a syntax verdict.
Will it catch an invented library method?
It flags suspicious patterns and imports that cannot resolve within the pasted file. Confirming that a method exists on your pinned version needs your build, which knows your dependency tree.
Should every AI-assisted diff go through a human reviewer?
No. Route routine work through the deterministic pass and reserve human sign-off for changes where a wrong answer is expensive or public.
Is the report stored?
Only if you save it while signed in. The check itself runs locally and leaves no copy of the source with us.

Client-side code check

Run the checks, then decide who has to sign it.

The automated pass is free, needs no account and uploads nothing. Escalate to a named reviewer only where being wrong is expensive.