Skip to main content

Optional analyzers — what SQLens will run for you, and what it will not

SQLens is useful on its own. Some checks are sharper when another tool is installed, so it can call one — read-only, with its own session timeouts, and never as a requirement.

The rule for all of them is the same and it is the reason this page exists: a tool that is not there produces an undetermined finding with a named reason, never silence. A run that could not look and a database with nothing wrong must never produce the same report.

What is adopted

ToolWhat it addsState
SquawkMigration lint checks, mapped onto SQLens rule idsadopted
Postgres Language ServerSchema-level security checks (dblint)adopted

Both are installed as ordinary binaries, both are pinned to a measured version window, and both have a test lane that runs the real binary rather than a stand-in. That last part is not ceremony: a claim about what a tool reports is a claim about the tool, and a fake process runner can only confirm what somebody typed into the fake.

What is not adopted: plpgsql_check

plpgsql_check finds dynamic EXECUTE with interpolated values inside PL/pgSQL function bodies — the server-side sibling of the injection rules SQLens runs over your application code. It is a good tool and the capability is real.

SQLens does not call it, and the reason is not effort.

It is a server extension, not a binary. Adopting it would mean:

  • the extension compiled against your PostgreSQL's headers and installed on the server being audited — which for an audit is usually production;
  • SQLens executing plpgsql_check_function() there, which is a function call on the audited server rather than a catalog read.

The second point is the one that decides it. SQLens's standing promise is that it reads catalog and state views, takes no locks of its own, and writes nothing. Calling a checking routine inside the server is defensible and it is still a different kind of act, and it would need to be argued for on its own rather than arriving as an implementation detail of an adapter.

There is a practical half too, and it points the same way. A capability whose positive path can only be exercised on a server that has the extension is a capability whose adapter would ship with one branch ever run — the branch that says the extension is missing. This package holds itself to the opposite standard: tests/Squawk and tests/Pgls exist so that every claim about an outside tool is measured against that tool, and a skip that cannot name its reason is treated as a defect.

What you can do today instead. The routine surface is not unwatched:

  • SEC.PRIV.ROUTINE_DEFINER, SEC.PRIV.ROUTINE_DEFINER_MUTABLE_PATH and SEC.PRIV.ROUTINE_DEFINER_UNSAFE_PATH judge every SECURITY DEFINER routine and its search_path, which is the exposure that turns an interpolated EXECUTE from a bug into a privilege escalation;
  • the analyse suite reads your application code for raw SQL that assembles a runtime value into a statement, which is where most injection actually lives in a Laravel project.

If you run plpgsql_check yourself, its output is complementary to both and nothing here duplicates it.

The honest limit of every adapter

SQLens passes a foreign tool's verdict through and marks it as foreign. It does not re-derive the finding, and it does not promise taint analysis on either side of the boundary — its own or the tool's. When a tool and a SQLens rule report the same object, the duplicate is suppressed and shown as suppressed, with the rule that owns it named; a de-duplicated finding that vanished without trace would be indistinguishable from one nobody produced.