What can this Postgres login actually see and do?

When you give an AI agent a database connection string, it inherits every

privilege that login has: whatever the role owns, whatever it can reach through

group roles, whatever PUBLIC was granted, and whatever default privileges will

grant on tables that don't exist yet. Most people never check what that adds up

to. agent-db-scan resolves it for you, so you can look before you hand the

credential over.

Prebuilt binaries for Linux, macOS and Windows (amd64 and arm64) are available

on the Releases page.

Download the archive for your platform, extract it, and put agent-db-scan on

your PATH. No Go toolchain needed.

With Go installed, you can instead run:

go install github.com/vaultkit-inc/agent-db-scan/cmd/agent-db-scan@latestIf agent-db-scan isn't found after installing, make sure $(go env GOPATH)/bin is on your PATH:

export PATH="$PATH:$(go env GOPATH)/bin"

Or from source:

git clone https://github.com/vaultkit-inc/agent-db-scan.git

cd agent-db-scan

make build # writes bin/agent-db-scanexport DATABASE_URL="postgres://app_service@localhost:5432/app"

agent-db-scan # reads $DATABASE_URL

agent-db-scan --dsn "$DATABASE_URL" --schema app

agent-db-scan --format json > report.jsonPrefer the DATABASE_URL environment variable over --dsn: a password passed

as a flag lands in your shell history and the process list.

There is no severity threshold yet, so the exit code does not reflect what the scan found.

Scanning a fixture login named app_service that inherits read and write from

two group roles (agent-db-scan --schema app):

agent-db-scan

TARGET

Login app_service

Scanned 2026-09-21 16:26:42 UTC

SUMMARY

Objects 1

Tables 1

Can read yes

Can write yes

Admin access no

Ownership none

Future access 2 rules

CURRENT ACCESS

OBJECT KIND LEVEL VIA

app.widgets table write app_reader (inherited), app_writer (inherited), +1 more

FUTURE ACCESS

New objects created by app_admin database-wide:

table SELECT via app_reader (inherited)

New objects created by app_admin in app:

table SELECT via app_reader (inherited)

The table view is a summary: at most two sources per row, sorted most

privileged first, and colored only when writing to a terminal (respects

NO_COLOR). Use --verbose for full detail or --format json for everything.

- Every query runs in a read-only transaction with a statement timeout, and the transaction is always rolled back, never committed.

- It reads catalog metadata only (roles, memberships, ACLs, default privileges, RLS state). It never reads table contents.

- Its only network connection is the database you point it at.

- Row-level security. It reports that a table has RLS enabled or forced and which policies exist, but it does not evaluate policy expressions, so it can't tell you which rows are actually visible. Treat access on an RLS table as an upper bound.

- SECURITY DEFINERfunctions. It does not analyze what functions run as, so privilege escalation through them is invisible. Functions are not scanned as objects yet.

- View owner rights. A view runs with its owner's privileges; that indirection is not traced.

- Column-level privileges. Only object-level ACLs are read.

An absence of findings is not proof of safety.

docker compose up -d # integration fixture, see testdata/schema.sql

make testMIT. See LICENSE.

Built by the team at VaultKit.