CodeGuards v1
// findings

Mass assignment, header injection, and the diff-visible bugs static scanners keep missing

Some bugs are obvious in the diff and almost invisible in a tree-walking AST. Here are the patterns that come up most often in real merge requests — and why a prompt-driven reviewer catches them where rule engines stall.

findings 2026-02-04 · ~7 min read

Why traditional scanners struggle here

Classic SAST works on rules: data-flow taint analysis, pattern matching against known sinks, configurable severities. That works well for clearly typed sinks (write to file, run shell command). It works badly for bugs that are about intent — was this user input ever expected to land in a header? Was this update($request->all()) protected by route-level auth?

A diff makes intent obvious in a way the AST does not. A reviewer who reads the change can see that a new public route landed, and that the controller behind it now mass-assigns from the request body. A rule engine sees two unrelated edits.

Pattern 1 — Mass assignment behind a public route

Classic Laravel example: User::find($id)->update($request->all()). By itself, the rule engine can flag the call. But to know whether it matters, you need to know whether the route is public, whether the model has a guarded list, and whether anything sanitised the payload upstream. The diff almost always tells you all three at once. The AST scan, working file-by-file, doesn't.

Pattern 2 — Header injection via raw email input

A common one: a feature for "send password reset to a different address" lands. The new line concatenates raw $request->input('email') into the Mail::raw() body. The taint reaches a sink, sure — but the more useful observation is that the diff added a public flow where it didn't exist before. That's a "this MR introduces a new attack surface" verdict, not a "this function might be tainted" finding.

Pattern 3 — CSRF re-validation accidentally removed

Refactors that "simplify" middleware are a classic source of removed CSRF checks. The change is small. The blast radius is large. A diff-aware reviewer can flag this as "this MR removes a security check; was that intentional?" — which is a much more useful question than the same finding wrapped in a CWE number from a yearly scan.

Pattern 4 — Secrets committed in test fixtures

Less exotic but extremely common: a test fixture commits a real-looking token. Most secret scanners catch the high-entropy strings; the harder part is telling a real key from a placeholder. CodeGuards treats this as something the repository can accept with a one-line policy note ("placeholder used in unit tests"), so the same scaffold doesn't trigger a finding on every future MR.

The shared shape

All four patterns have the same shape: the bug is obvious if you can read the change as a change, and obscure if you only see two ASTs side by side. That's the gap diff-only review fills — and it's exactly where a prompt-driven reviewer outperforms a fixed rule set.

Back to field notes