All posts
Security

How we scan your database without reading your data.

What a lumioguard database scan can read, what it can never read, and where that boundary is enforced.

Stacked database cylinders and a folder of documents behind a shield with a padlock, over papers showing database schema diagrams.

Giving any service access to a production database raises an obvious question: can it see the customer and business data stored inside? Can it change or delete the data, or the tables themselves?

lumioguard does not query or sample those records. The scan looks only at the information your database provides about its structure and health, such as schemas, indexes, security policies, settings, and performance statistics. This article explains exactly what the scan can read and where the boundary is enforced.

The short version

  • You create the database user we connect with, and you choose what it can see. The credential you paste is the entire grant.
  • Scans read system catalogs and statistics only: schema, indexes, policies, settings. Never rows, never documents.
  • Every query we run is drawn from a fixed allowlist of system objects. A query that references one of your tables is rejected before it executes, and the scan fails loudly rather than proceeding.
  • Your credentials are encrypted at rest with AES-256-GCM under keys unique to your workspace, and never shown or logged again.
  • Drop the database user on your side and access ends that instant. You hold the kill switch, not us.

What a scan actually reads

Everything useful for finding problems lives in your database's own metadata: table and column definitions, indexes and foreign keys, row-count estimates, row-level security policies, storage engines, and server settings. That is enough to catch a table with no RLS, a missing index behind a slow query, or a risky configuration, without ever looking at the data those tables hold.

What the scan reads
Schema: tables, columns, types
Indexes and foreign keys
Security policies and settings
Statistics: counts and sizes
What it never reads
Table rows
Documents
Raw query text
Secret values
Structure and statistics are read; rows, documents, query text, and secrets never are.

Query statistics deserve a specific mention. Where your database tracks query performance, we read normalized metrics only: timings and counts. We never select the raw SQL text of your queries, because real query text can embed real customer data.

The allowlist is the guard, not goodwill

The session we open is read-only, with a hard statement timeout and a minimal connection cap. But a read-only session prevents writes, not reads, so we do not rely on it for your privacy. The real boundary is stricter:

Every query the scanner issues
On the fixed allowlist: runs against system catalogs and statistics views
References anything else: rejected before execution, the scan fails loudly
Read-only prevents writes. The allowlist is what prevents reads of your data.

Every query is validated against a fixed list of system catalog objects before it runs. There is no branch that builds a SELECT against a user table, and if one ever appeared, the validator would kill the scan rather than let it through. The same model applies across engines: system catalogs on PostgreSQL, information_schema on MySQL, sys views on SQL Server, and collection and index metadata on MongoDB. Never your documents.

The sandbox

Each database scan runs in a private sandbox created for that scan alone. Your connection credential is sent encrypted and unlocked only inside a separate access broker. The scanner never receives it; it sees only the approved catalog and statistics results. When the scan ends, the sandbox, the broker, and the decrypted credential are destroyed.

For the full isolation and cleanup design, read how the scan sandbox works.

Being precise

Two things worth noting. First, the read-only user is created by you, so its privileges are whatever you grant; we validate the connection details immediately and verify them on your first scan, and we recommend granting catalog access only. Second, use a connection string that requires TLS, such as sslmode=require, and the session is encrypted in transit end to end; we honor whatever transport settings your string specifies.

Your controls

Disconnect the connector and the stored credential is deleted. Better still, the access itself lives in your database: revoke or drop the user and we are locked out immediately, no request to us required.

If your security team wants to go deeper than this page, ask us at hello@lumioguard.dev. This is the part of the product we are most comfortable being questioned about.

Get started

Structure and statistics, never your data.

Connect read-only in a couple of minutes and get your first stack health score, evidence attached. Start free, no card.