Sensitive columns.

Mark the columns that hold personal or payment data and decide what happens to every query that reads them: block it, flag it or mask the value. This page says what each connection mode guarantees, and what it does not.

Summary

Blocking a destructive DELETE protects the data from the agent. It does nothing about the opposite risk: an agent that reads what it should not. SELECT email, card_number FROM customers is harmless to the database and still puts personal and payment data into an LLM's context.

With sensitive columns you mark columns per database from the dashboard, and Vericto decides on each query's AST, like any other rule: the same query always gets the same decision, results are never read and no latency is added. The audit trail says which column triggered each decision.

Availability. Team and Enterprise plans. Tags are stored, synced to your proxies and shown in the dashboard now; they are enforced once the Vericto TCP proxy and evaluator releases that support them are deployed. Until then, the dashboard says they are not enforced yet.

Policies

Each tagged column has a policy. When a query reads several tagged columns, the strictest wins: block > mask > flag. All are reported under rule VERICTO-085.

  • block: the query that reads the column is blocked.
  • flag: the query passes and is recorded, with an alert.
  • mask: the projection is rewritten to return the masked value. Postgres only for now; on MySQL and the other dialects a mask tag blocks the query.
StyleResultPostgres expression
full[redacted]'[redacted]'::text
last4**** and the last 4 characters'****' || "right"(col::text, 4)
emailThe first letter and the domain: a***@example.com. A value without @ is masked too: p***regexp_replace(col::text, '^(.)[^@]*(@.*)?$', E'\\1***\\2')
hashSHA-256 in hexadecimalencode(sha256(convert_to(col::text, 'UTF8')), 'hex')

A masked column comes back as text. A numeric or date column masked with last4 or hash changes type: the dashboard warns about it and proposes full for names that do not look like text. Any expression computed over a masked column (lower(email), substring(card, 1, 4)) is masked with full, whatever the style.

What counts as a read

Vericto follows which columns each projected expression derives from, at any level of subquery or CTE. An alias, a function, an aggregate or a CASE over the column are still a read of the column.

  • SELECT *, t.*, whole-row references (to_jsonb(t), row_to_json(t)) and COPY … TO over a table with tagged columns are blocked under mask and block, and flagged under flag. The message asks to list the columns.
  • A column that only appears in WHERE, JOIN, GROUP BY or ORDER BY is not a read: nothing is returned.
  • Copying the value elsewhere (INSERT … SELECT, CREATE TABLE … AS, UPDATE … SET x = email) counts as a read; under mask it is blocked, because masking would change stored data.
  • A table name without a schema that could be a tagged table is treated as the tagged one. When in doubt, the column is considered sensitive: a false positive is a blocked query with a clear message; a false negative is a leak.

The guarantee in each mode

The guarantee depends on who executes the query. Only the TCP proxy sits between the query and the database; in every other mode Vericto returns a decision and someone else executes.

ModeWho executesblockmaskflagEnforced?
TCP proxyThe proxy, inlineNative database error, as todayThe proxy sends the rewritten SQL; the database returns the value already maskedPasses, recordedYes: the client has no other path to the database
Runtime APIThe application, after askingBLOCKED, as todayThe response carries rewritten_query; the application must execute itPasses, flagged (FLAGGED)No: an application that ignores the response runs the original
MCPThe agent, with its own database toolBlocked with the reasonThe masked query is returned as the only approved oneWarningNo: depends on the agent following it
CLI / Validation APINobody (CI, migrations)Fails the pipelineNot applicable; the masked version is shown as a suggestionWarning in the reportNot needed: the control is that the change never reaches production

Masking is a control in the TCP proxy and a recommendation elsewhere. An agent "cannot" read a column only if it reaches the database through the proxy.

How to tag columns

In Databases, each database has a Sensitive columns section: the schema (optional), the table, the column, the policy and, for mask, the style. Names are compared case-insensitively. Tagging, changing and removing tags is for the owner and admins; the rest of the team sees them.

Suggestions. Vericto never connects to your database, so it does not know your schema. Suggestions come from recent traffic: columns your queries read whose names look like sensitive data (email, card, ssn, password, token, iban, phone…). One click tags them, but you decide.

Changes reach each proxy on its next rule sync, without a restart, and the API uses them on its next evaluation. With at least one block or mask tag, a query that cannot be parsed is blocked: it cannot be shown not to read a tagged column.

Audit trail

Every block, mask and flag is an audit-trail event with rule VERICTO-085, the database and the column that triggered it. When a query was masked, the event keeps both the original and the rewritten query, encrypted like any query.

Tagging or untagging a column changes what an agent can read, so every change is in the workspace audit log, with who made it and the policy before and after.

Recommended architecture for agents

For masking to be a control and not a recommendation:

  1. The agent calls a tool, an API you expose, preferably with business operations (get_order(id)) rather than "run this SQL". It never holds database credentials.
  2. That API reaches the database only through a Vericto proxy.
  3. The database accepts connections on that path only from the proxy (security group or firewall).
  4. A dedicated proxy for the agent path, registered as its own database with masking on. The policy is per database, so an application that must show real emails to people uses another instance.
  5. The agent has no other path to the data: no other database MCP server, no credentials in its environment.

Limits

  • It is defence in depth: your database's column privileges, views and row-level security remain the first line.
  • Vericto decides by the column's name, not its content: it does not look for sensitive data in values.
  • ORMs that SELECT * are blocked under mask until they list the columns.
  • If you rename a column, its tag stops applying: tag it again under the new name.