Skip to content

Sensitive data

VirtuAI scans every stored message for secrets and personal data, masks what it finds in the Conversations screen and in exports, and records who looks at it. This page goes into the detail. For finding and reading conversations, see Conversations.

Detection runs when a message is stored, on every channel that stores messages. It uses patterns and checksums, not a model, and it sends nothing to any outside service.

It controls what people see when they audit conversations. It doesn’t change the conversation itself:

  • The agent and the model provider receive the original text.
  • The person chatting sees what they typed.
  • The transcript is stored as written. What’s stored separately is a finding: the category and the position of the value, never a copy of it.

If a secret shows up in a conversation, treat it as exposed and rotate it.

Category Severity Default What’s detected Visible after masking
Credit card Critical On 13 to 19 digits, with or without spaces or dashes, that pass the card checksum (Luhn) Last 4 digits
API key Critical On Keys that start with sk-ant-, sk_live_, sk-, AIza, AKIA, ghp_ and the other GitHub token prefixes, xoxb- and the other Slack prefixes, glpat-, and JSON Web Tokens Nothing
Private key Critical On The -----BEGIN ... PRIVATE KEY----- line of a PEM key Nothing
Password Critical On The value after password, passwd, contraseña, clave or secret followed by : or = Nothing
Bank account (IBAN) High On IBANs that pass the mod-97 check Last 4 characters
National ID High Off Mexico CURP, Brazil CPF, Chile RUT, and Spain DNI with a valid check letter The last 1 to 4 characters, depending on the format
Phone number Medium Off Numbers in international format, starting with + Last 4 digits
Email address Low Off Email addresses Nothing
IP address Low Off IPv4 addresses Nothing

The optional categories are off because they’re specific to a country or match ordinary text too often. An IP address and a version number such as 1.2.3.4 look the same, for example.

When two patterns match the same text, the more severe one wins, so a card number isn’t also reported as a phone number.

Masking happens on the server, before the conversation is sent to your browser, so the real value isn’t in the page or the network response.

  • A masked value becomes dots. Where a tail is kept, you see it at the end: ••••••••••••1111.
  • It applies to everything built from the message, not only the transcript: the conversation title and the preview in the list.
  • Titles and previews are shortened copies of a message. If the cut falls in the middle of a card number or a key, the part that’s left is masked too.

A conversation with findings gets a badge for its most severe category, and the Sensitive data panel lists what was found by category. Filter the list with With sensitive data to see only those conversations.

To see a masked value in full:

  1. Open the conversation. This requires conversations.audit.
  2. In the Sensitive data panel, select Reveal next to a category. This requires conversations.pii_reveal.
  3. Confirm with Reveal and record.

You reveal one category at a time, and only in that conversation. Every reveal is written to the access log with your user, the time and the category. There’s no setting that turns masking off.

Exports are masked the same way as the screen.

Export Permission
Export CSV: the filtered conversation list conversations.manage
Export Markdown or Export JSON: one conversation conversations.manage and conversations.audit

Exports from the screen are always masked. An unmasked export is possible only through the API, only for people who also hold conversations.pii_reveal, and the access log records which categories were included.

Rules are set per workspace in the conversations.sensitive_rules setting: a JSON object that turns each category on or off. Categories you leave out keep their default.

{
"phone": true,
"email": true,
"national_id": true,
"password": false
}

The category names are credit_card, api_key, private_key, password, iban, national_id, phone, email and ip_address.

There’s no screen for this setting yet. A workspace admin with settings.manage can set it through the settings API, or ask support to set it.

Rules apply to messages stored after the change. To apply the current rules to a conversation stored earlier, open it and select Re-scan. This requires conversations.manage, replaces that conversation’s previous findings, and is recorded in the access log.

Access log, in the Monitor section, lists every time someone:

Action Meaning
Viewed Opened a transcript
Revealed Unmasked one or more categories. The categories appear under Details.
Exported Downloaded a conversation or the conversation list
Re-scanned Applied the current rules to a stored conversation

Each entry shows when, who, the action and the conversation. Filter by Action to narrow it down. Reading the log requires conversations.audit, because it shows who looked at which conversation.

Permission Allows Default roles
conversations.view Listing conversations admin, user, viewer
conversations.audit Opening any transcript, the findings report and the access log admin
conversations.pii_reveal Revealing masked values admin
conversations.manage Exporting, re-scanning and applying retention admin

See the Permissions reference and the Security overview.