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.