# Velum > A local, offline tool that masks personal and sensitive data in prompts and > files before they reach a large language model, then restores the real values > in the model's reply. Detection and masking run on the user's own device. Velum exists for people who handle regulated data and want to use AI anyway: lawyers, accountants, gestores, clinicians, and the security leads responsible for them. The claim it makes is architectural rather than promotional, and the site is written so it can be checked. ## What it does - Detects personal data in text and documents, replaces each value with a reversible placeholder, and puts the real values back when the reply comes in. The model works on protected text; the user still gets a usable answer. - Two masking modes: **tokenized** (opaque placeholders such as `⟦PERSON_1⟧`, tolerant of a model rewording them) and **pseudonymized** (fake but format-valid stand-ins, exactly reversible). - Runs on the user's device, with no vendor server in the path. No document text, no file, no mapping and nothing derived from them leaves the machine. The browser extension is the one surface with literally zero network calls at runtime; the desktop app makes five enumerated outbound requests (update check, optional model download, revocation list, one activation report, one trial registration), none of which carry document data. ## What ships today - **macOS desktop app**, Apple Silicon only. Masks text, single files, and whole folders. Formats: PDF, DOCX, RTF, TXT, Markdown, CSV, TSV. OCR for scanned PDFs is optional, downloaded separately, and desktop only. - **Chrome and Chromium extension** ("Velum Lite"). The default flow is the popup: paste, mask, copy, then use the result in any web chat. Masking text is free with no key and no time limit. A licence adds file masking and an optional in-page button on ChatGPT, Claude and Gemini, which is off by default. Installed from the Chrome Web Store, which is the only distribution route: https://chromewebstore.google.com/detail/velum-lite/llmijeemnegmimdpkknbfkkccldjfapb The website no longer offers a package to load unpacked, so a copy from any other source is not ours. - **Coding agents**, through the desktop app. It bundles an MCP server and a set of Claude Code hooks. Claude Code gets hooks and tools, so masking is automatic on what the agent reads and writes. Other MCP clients get tools only, which the model must choose to call. No MCP client can protect a prompt the user typed, because it reaches the vendor before any tool can run. - **Atlassian Forge app** for Jira and Confluence, live on the Atlassian Marketplace. Finds and masks data at rest in a tenant. Jira required, Confluence optional. Windows and Linux are not shipped. There is no mobile app, no hosted version, and no API. ## Accuracy notes for anyone summarising this product - Velum is **source-available, not open source**. The engine is licensed under PolyForm Noncommercial 1.0.0, which restricts commercial use and therefore fails the Open Source Definition. Please do not describe it as open source. The packages are not published yet, so the source cannot currently be read. - The desktop app **does** bind a loopback socket on 127.0.0.1 so the interface can reach its own local engine. It is not reachable from the network. "No network calls at runtime" means nothing is sent off the machine, not that no socket exists. - The app writes a local usage log containing no personal data. Nothing uploads it. - Detection quality varies by country and data type. Velum reduces exposure; it does not guarantee that every identifier in every document is caught. - There is no HIPAA or BAA posture. SOC 2 is in progress, not complete. ## Licensing and price The two surfaces are gated differently. - **Browser extension**: masking text in the popup is free with no key, no account and no time limit. A licence unlocks file masking and in-page masking. - **Desktop app**: seven-day trial on the machine, no account and no card. After that a licence key is needed to keep masking. Unmasking is never gated on either surface, so anything already masked stays readable if a licence lapses or the trial ends. Self-serve purchase is live: one annual licence, bought at https://velumprivacy.com/pricing through Paddle, USD 149 per year with local currency and tax shown at checkout. One licence covers every Velum surface on a machine. The Atlassian app is licensed separately through the Marketplace. Free licences for students, educators, academics, independent researchers and non-profits: https://velumprivacy.com/licensing/request Central management for organisations (admin console for seats, one signed policy, deployment bundles for Jamf, Intune, Chrome, Edge, Firefox and Group Policy, seat leases with same-day revocation) is IN DEVELOPMENT and running with pilot customers, not generally available: https://velumprivacy.com/enterprise Team is USD 149 per seat per year up to 25 people; Business and Enterprise are priced on request. That console holds seats, devices, versions and policy hashes; it never receives document text, filenames, prompts, visited sites or mapping values. Volume, site, or invoiced licensing: licenses@velumprivacy.com. ## Free resources - **AI usage policy template**: a complete, adoptable AI usage policy for an organisation. Seventeen clauses, an approved tool register, a data classification table, an incident procedure, and a one-page card for staff. Free, no email or account required, downloadable as Word, PDF, or Markdown. https://velumprivacy.com/ai-usage-policy-template ## Links - Home: https://velumprivacy.com - Full site content in one file: https://velumprivacy.com/llms-full.txt - Desktop app for macOS: https://velumprivacy.com/desktop - Browser extension: https://velumprivacy.com/extension - Jira and Confluence app: https://velumprivacy.com/atlassian - For organisations, in development: https://velumprivacy.com/enterprise - Licensing terms: https://velumprivacy.com/licensing - Use cases: https://velumprivacy.com/use-cases - Use cases in depth: legal https://velumprivacy.com/use-cases/legal, healthcare https://velumprivacy.com/use-cases/healthcare, accounting https://velumprivacy.com/use-cases/accounting, research https://velumprivacy.com/use-cases/research - PII redaction, explained: https://velumprivacy.com/pii-redaction - AI usage policy template: https://velumprivacy.com/ai-usage-policy-template - Blog: https://velumprivacy.com/blog - How to check if a PDF is really redacted: https://velumprivacy.com/blog/check-pdf-redaction - Privacy policy: https://velumprivacy.com/privacy --- # Documentation Source: https://velumprivacy.com/docs Velum Privacy finds personal data in Jira and Confluence, masks it reversibly, and erases it on request. It runs entirely on Atlassian Forge, inside your own tenant. This page explains how to install, configure and operate it. ## Install Velum Privacy installs into **Jira** first, then optionally connects to **Confluence**. From the Atlassian Marketplace, choose Get it now and follow the prompts. Jira administrator permission is required to install and to open the dashboard. After installation, open the dashboard at **Settings, Apps, Velum Privacy** in Jira, or **Settings, Velum Privacy** in Confluence. ## Operating modes Velum has three modes, set on the Overview tab: - **Off.** All scanning is paused. No content is scanned or changed. - **Monitor.** Velum detects and reports personal data but never edits content. This is the default and the safe way to see what is in your instance before acting. - **Protect.** Velum detects and, per your remediation policy, auto-masks new high-severity findings as they appear. Masking is reversible. Start in Monitor. Move to Protect once you have reviewed what Velum finds and configured the remediation policy you want. ## What is detected Two tiers run together: - **Structured detectors** (regex, always on, high precision): payment cards, IBANs, national IDs for Spain, the US, the UK, France, Germany, Turkey and Italy, plus API keys and tokens (AWS, GitHub, OpenAI, Slack, JWT). - **AI detection** (an on-device multilingual model): names, organisations and locations. Broader coverage than the structured detectors, with more false positives. It can be turned off if you only care about structured data. Detection covers Jira issue summaries, descriptions, comments and attachments, and Confluence page bodies, comments and attachments. Attachments are scanned for PII but are never modified; they are reported only. ## Findings The Findings tab lists every detection with its type, severity, location and status. Filter by severity, then act on each finding in place: - **Mask** replaces the detected values with reversible tokens, preserving the document's structure, headings, tables and macros. - **Unmask** restores the original values from the stored reversal key. - **Dismiss** or **Reopen** manages a finding's status without editing content. Bulk actions apply the same operations across a selection. Actions on content in a product you do not administer are skipped and reported, not silently applied. ## Reversible masking Masking replaces a value such as `maria@example.es` with a token such as `⟦EMAIL_1⟧`, and stores an encrypted mapping so the original can be restored. The mapping is encrypted with AES-256-GCM at the application layer. Masking never flattens a document: only the text of the detected values changes, and unmasking returns the content byte for byte. ## GDPR Article 17 erasure The GDPR erasure tab implements the right to erasure. Search a data subject by name or email to find every match across Jira and Confluence, generate an audit-ready PDF report as evidence, then erase. Erasure is different from masking, and irreversible by design. It redacts the values in the content itself, deletes the copies Velum stored, and destroys the reversal keys for those locations. Once erased, the values cannot be recovered. ## Settings The Settings tab controls what is scanned and what happens automatically: - **Scan triggers.** Real-time scanning checks each issue and page as it is created or edited. A scheduled scan sweeps in-scope content on a cycle to cover the backlog that existed before Velum was installed. - **Scope.** Scan the whole instance, or restrict to specific Jira projects and Confluence spaces to reduce noise and usage. - **Detection.** Toggle the AI name detector, comment scanning and attachment scanning, and turn off individual detector types (for example, the location detector, which is the least precise). - **Remediation.** Enable auto-masking (Protect mode only), set the severity threshold at which it acts, and choose instant or deferred masking. You can also label high-severity Jira issues so your own Automation rules can react. ## Permissions Velum Privacy requests only the scopes its features need. Content read scopes are used to scan; content write scopes are used only when you or your policy remediate. Confluence administrator status is detected by reading a single admin-gated record, which is then discarded. App storage holds findings, the audit log, policy and the reversible token mappings, all inside your tenant. For the full per-scope justification and the security architecture, see the [Security](/security) page. ## Support Raise bugs, feature requests and support questions through our support portal at [su-engineering.atlassian.net](https://su-engineering.atlassian.net/servicedesk/customer/portal/1), or email **support@su.engineering**. ## Other Velum products Everything above documents Velum Privacy for Jira and Confluence, the app you reached this page from. Velum is one detection-and-masking engine delivered across several surfaces, so your people are covered wherever they touch AI. The rest are summarised here; full guides live with each product. ### Browser extension (Velum Lite) Masks and unmasks beside any web AI, including Claude, ChatGPT and Gemini, or from a Mask button placed in the page on sites you grant it. Drop a PDF, DOCX, TXT, RTF, CSV or Markdown file to get a masked copy back. It runs fully offline in the browser and can pair with the desktop app to borrow its stronger engine. It installs from the [Chrome Web Store](https://chromewebstore.google.com/detail/velum-lite/llmijeemnegmimdpkknbfkkccldjfapb), [Firefox Add-ons](https://addons.mozilla.org/addon/velumprivacy/) and the [Edge Add-ons store](https://microsoftedge.microsoft.com/addons/detail/velum-lite-mask-pii-in-a/kkcjfadcmbacaagkikanmikgemkegmed), which are the only routes we distribute it through. ### Desktop app (macOS and Linux) A native app for staff who work with sensitive files all day. It masks pasted text, dropped files and whole folders at the highest detection tier, and keeps an encrypted local mapping so masking is reversible across sessions. A Protection page states the app's own network behaviour and exports a one-page protection receipt for a DPO. It names all five requests the app makes: an update check and a licence revocation list on launch, the optional one-time model download, and one-time activation and trial calls. None of them carries document data. Free for seven days with no account, then one licence key keeps masking on. ### CLI and library Drop-in `velum mask` and `velum unmask` for scripts, data pipelines and developer workflows. The same engine as every other surface, callable from the terminal or imported as a library, with no network calls at runtime. ### Embedded loopback service A local HTTP endpoint any internal application can call to run its own AI pipeline through Velum. Send text to `POST /mask` before it reaches a model and `POST /unmask` on the reply. The service binds to `127.0.0.1`, and its mappings are held in memory only and expire, so nothing sensitive is written to disk. This is how you protect the AI you build, not just the AI you buy. For the whole picture across every surface, see the product brief at [velumprivacy.com](https://velumprivacy.com). --- # Security Source: https://velumprivacy.com/security Velum Privacy for Jira and Confluence is a security product, so the smallest attack surface we can ship is the one that never holds your data. The app runs entirely on Atlassian Forge. There is no vendor-operated server, database, or backup that contains customer content. Detection, masking and erasure all run inside your own Atlassian tenant. A compromise of Velum cannot expose your Jira or Confluence data, because we never hold it. To report a vulnerability, email **security@su.engineering**. ## Architecture Velum Privacy is Forge-native. There is no Forge Remote, no vendor backend, and no third-party AI service in the request path. - PII detection runs in-process: a regular-expression engine plus an on-device NER model executing under `onnxruntime-web` (WASM) inside the Forge function. - All persistence uses Forge app storage, scoped to your installation. App data is deleted when you uninstall. - The only outbound request is a one-time download of the public, static AI model file from the Hugging Face CDN at cold start. It carries no customer content, and the two permitted hosts are declared in the app manifest. Forge blocks everything else at the platform level. Your content never leaves your Atlassian instance. ## Data protection - **Encryption at rest.** Atlassian platform encryption on all Forge storage. - **Reversal keys.** The token-to-value mapping that makes masking reversible is additionally encrypted with AES-256-GCM at the application layer, keyed by a Forge encrypted variable, on top of platform encryption. - **Encryption in transit.** TLS 1.2 or above on all requests. - **Tenant isolation.** Storage is scoped per installation. No cross-tenant data path exists. - **Credentials.** The app collects no Atlassian or third-party credentials and holds no secrets of its own. Forge issues its runtime authentication. ## Access control Authorization is evaluated per product and per method. Every backend method that reads or changes findings, audit records, reversal keys or configuration verifies that the caller administers the Atlassian product the content belongs to: a Jira administrator manages Jira findings, a Confluence administrator manages Confluence findings, and neither sees the other's. Changing detection policy, which governs scanning in both products, requires administrator rights in both. UI placement is not treated as an authorization boundary. The checks live in the backend, where they cannot be bypassed by calling the app directly. Admin-initiated content changes execute as the requesting user, so the app's effective access never exceeds that administrator's own permissions. De-anonymization, the highest-risk operation, is admin-gated and audit-logged without exception. ## Logging and audit - The app maintains an in-tenant, append-only audit log of scans, masking, de-anonymization, configuration changes and administrative actions. - Audit entries are scoped to the product they concern and visible only to an administrator of that product. Entries reference a data subject by salted hash, never by name or email. - Detected values, credentials and access tokens are never written to platform logs. This is enforced by review on every change. ## GDPR Velum Privacy includes GDPR Article 17 tooling. Locate every occurrence of a data subject across Jira and Confluence, export an audit-ready report, then erase them. Erasure redacts the values in the content itself, deletes the copies Velum stored, and destroys the reversal keys for those locations, so the removal cannot be undone. Because all data stays in your Atlassian instance, you remain the data controller. ## Secure development - Source is held in a private repository; access requires multi-factor authentication. - Dependencies are reviewed against published advisories; the tree is almost entirely Atlassian's own Forge SDK, and upstream advisories are tracked and shipped when Atlassian releases a fix. - The app requests the narrowest scopes its functionality allows. Every new scope requires written justification before release. - The OWASP Top 10 is the reference for security review of application changes. ## Vulnerability disclosure If you believe you have found a security vulnerability, report it to **security@su.engineering** with enough detail to reproduce it. We acknowledge reports within two business days and keep you updated until the issue is resolved. Please give us reasonable time to ship a fix before public disclosure. We will not pursue legal action against researchers who report in good faith and avoid privacy violations, data destruction or service disruption while testing. Vulnerabilities may also be reported through Atlassian's Marketplace Security channel. Remediation follows the Atlassian Marketplace security bug fix policy timelines. ## Incident response We maintain a documented incident response plan covering triage, severity classification, containment, remediation and notification. If an incident affects your data, we notify affected installations within 72 hours of confirming impact, using Atlassian's partner notification templates, and notify Atlassian in parallel. Where facts are still uncertain, we say so rather than issue reassurance the evidence does not support. ## Compliance su.engineering does not currently hold ISO 27001, SOC 2 or PCI certification. We would rather state that plainly than imply otherwise. The app's security posture rests on architecture, no vendor-side data, and on the controls described above, and is reviewed at least annually. ## Other Velum products Everything above concerns Velum Privacy for Jira and Confluence. Velum ships the same engine across other surfaces, each with its own posture. They share one principle with the Atlassian app: your content never reaches a vendor server. ### Endpoint apps (browser extension, desktop, CLI) - **No network in the masking path.** Models are bundled or cached locally, remote model loading is disabled, and this is enforced in the build by a static scan and a runtime network-block test. The desktop app makes five outbound requests and none of them carries document text: an update check on launch, a signed licence revocation list on launch, the optional one-time model download, a single activation report at the moment a licence key is entered, and a single trial registration on first run. The app enumerates all five on its own Protection page and in the protection receipt it exports. - **Mappings stay on the device.** They are encrypted at rest with AES-256-GCM, the key held in the OS keychain, or kept in memory only and discarded on quit, at the user's choice. - **Unmasking is never gated,** not even by licensing, so nothing already masked is ever locked away. Licence keys are signed offline and verified locally against an Ed25519 public key, so masking keeps working with no network. Two of the five requests concern licensing: the activation report, whose result the app ignores, and the trial registration, which is what stops a free trial being restarted by deleting local files. Each is sent once, and each carries a one-way hash rather than an identifier: the activation report a hash of the install's random id, the trial registration a salted hash of the machine's platform UUID. Neither carries document text, an email address or a licence key. ### Embedded loopback service Runs as a local sidecar bound to `127.0.0.1`. Internal applications call `POST /mask` and `POST /unmask`. Mappings are held in memory only, loopback-bound and expiring, and are never persisted, so the "no sensitive data at rest" property holds for the AI features you build on it. ### Source-available engine The detection-and-masking core is licensed under PolyForm Noncommercial rather than a closed licence, so it can be read rather than taken on trust. It is not published yet. The packages are prepared for release to npm as `@velumprivacy/*` and are not on the registry today, so the auditability that licence buys is a commitment and not yet a fact. The licensing page states this the same way. Diagnostics and usage logs contain counts and timings only, never document text. To report a vulnerability in any Velum product, email **security@su.engineering**. --- # PII redaction, explained Source: https://velumprivacy.com/pii-redaction PII redaction is the removal or masking of personally identifiable information from text before that text goes somewhere you do not fully control. The term comes from document redaction, the black bars on a released government file. Applied to AI, it means one specific thing: the names, numbers and identifiers in your prompt are replaced before the prompt reaches the model, so the model can do its work without ever seeing who the text is about. This page explains how that works, where the common approaches differ, and what to check before trusting any tool with the job. ## What counts as PII in a prompt PII is broader than most people assume. The obvious items are names, email addresses, phone numbers and government identifiers. But a prompt pasted from real work usually carries more than that: account numbers, case references, addresses, dates of birth, medical details, salary figures, IP addresses, and the kind of contextual detail that identifies a person even with the name removed. A date of birth plus a job title plus a town is often enough to identify someone. Regulators treat it that way, and so should a redaction tool. The practical test is not "is there a name in this text" but "could a person be identified from what remains". That is why serious tools detect dozens of entity types rather than three, and why detection quality is measurable rather than a matter of opinion. ## One-way redaction and its problem The oldest approach deletes or blacks out the sensitive spans and leaves the rest. That works for publishing a document. It works badly for AI, because the reply comes back full of holes. Ask a model to draft a letter about a redacted contract and it will produce a letter about `[REDACTED]`, which you then repair by hand. The tool protected the data by destroying the usefulness of the answer. One-way redaction still has a place when text will be stored or published and never needs to be read in full again. For working with an assistant, it is the wrong shape. ## Reversible masking: tokenized and pseudonymized The alternative is masking that can be undone after the reply comes back. The sensitive span is replaced with a stand-in, the model works on the stand-in, and the stand-in is swapped back for the original in the answer. Two families exist, and they trade off differently. **Tokenized masking** replaces each entity with an opaque token such as `⟦PERSON_1⟧`. The same person becomes the same token everywhere, so the model can still reason about who did what. Tokens are visibly artificial, which is a feature: you can see at a glance that the text is protected, and the reverse step can tolerate a model that rephrases or reorders the token. **Pseudonymized masking** replaces each entity with a fake but format-valid value: a different name, a plausible IBAN, a date shifted consistently. The text stays natural, which some models handle better, and the output is safe to show to someone who should not know the text was masked at all. The cost is that reversal must be exact, and a reader cannot tell protected text from raw text by looking. Neither is simply better. Tokenized is more robust and more visible; pseudonymized is more natural and more discreet. A good tool offers both and lets the situation decide. ## Where the redaction runs decides what it protects Every property above is secondary to one question: does the raw text leave your machine before the masking happens? A redaction service that runs in a vendor's cloud must receive your unredacted text to redact it. Whatever it strips afterwards, the vendor's infrastructure saw the original. That can be an acceptable trade inside a data processing agreement, but it is not the same promise as the text never leaving. If the point of redaction is that third parties never see the raw data, a third-party server in the redaction path defeats the point. On-device redaction closes that gap structurally. The detection and masking run locally, and only masked text ever crosses the network. The claim is testable rather than contractual: cut the network connection and see whether masking still works, or watch the process with a connection monitor. A tool that keeps working offline was never sending your text anywhere. ## How to evaluate a PII redaction tool Six questions separate the field quickly. 1. **Where does processing happen?** On your device, or on the vendor's servers? If the answer is unclear in the documentation, assume the server. 2. **Is the masking reversible?** Can the tool restore the original details in the model's reply, or does it only delete? 3. **What does it detect, and how well?** Entity types, languages, and ideally published numbers. Detection quality varies enormously and is measurable; a vendor that publishes precision and recall is inviting you to check. 4. **Does it work offline?** The sharpest single test of every privacy claim in this list. 5. **What is retained?** Mappings between originals and stand-ins are sensitive in themselves. Where are they stored, and who can read them? 6. **Can the claims be inspected?** Source availability, enumerated network behaviour, and reproducible benchmarks all beat a policy page. For how these criteria play out across real tools, see the honest surveys on the blog: [the browser extension field](/blog/pii-redaction-extensions-for-ai-chat), [Velum against Microsoft Presidio](/blog/velum-vs-microsoft-presidio) for engineering teams, and [cloud DLP APIs against on-device masking](/blog/cloud-dlp-apis-vs-on-device-masking). The trade-offs between the two masking styles get their own piece in [tokenized vs pseudonymized masking](/blog/tokenized-vs-pseudonymized-masking). ## Looking for a local PII anonymizer? "PII anonymizer" is the phrase most people type for a tool that strips or replaces personal information before data reaches an LLM. It usually means the job described above, but the word carries a specific meaning that is worth separating from the marketing use. Anonymisation in the regulatory sense is irreversible. Once text is anonymised, nobody can recover the original values, including you. Reversible masking is pseudonymisation, and pseudonymised data is still personal data under the GDPR. Any tool that promises both perfect reversal and true anonymisation is describing two different things with one word. Both are useful, for different jobs. When you are working with an assistant and need the answer to make sense, reversible masking is what you want: values are replaced on your device before the prompt leaves, and restored in the reply. When a document has to be sanitised for good, before it is filed, shared or published, permanent redaction is the irreversible option, with no mapping kept anywhere. Velum does both. It masks reversibly for AI work, and redacts permanently for documents that should never carry the values again. Detection and replacement run on your own machine in both cases, which is the part that matters most: a service that anonymises your text on someone else's server has already received the text it was meant to protect. ## How Velum does it Velum is a PII masking tool built around the on-device answer to question one. Detection and masking run entirely on your machine: a regex floor that needs no model, plus an optional on-device NER model with country-specific packs for Spain, the US, UK, France, Germany, Turkey and Italy. Both masking modes described above are supported, tokenized and pseudonymized, and both are reversible, so the model's reply comes back with the real details restored. The browser extension does the whole round trip with no network access at all. The desktop app makes a short list of enumerated outbound calls, none carrying document content, and lists them in its own interface so the behaviour can be checked rather than believed. Detection quality is measured and published on the [benchmarks page](/benchmarks), including what gets through. --- # Artificial Intelligence Usage Policy Source: https://velumprivacy.com/ai-usage-policy-template **Document owner:** [ROLE, e.g. Data Protection Officer] **Approved by:** [APPROVING BODY] **Effective date:** [DATE] **Version:** 1.0 **Next review:** [DATE, suggested 12 months] > This is a template, not legal advice. It is written to be a sound starting point across sectors and jurisdictions. Have your data protection officer or counsel review it before adoption. Three clauses are marked **[CHECK LOCAL LAW]** because the correct answer genuinely depends on where you operate. ## 1. Purpose and scope This policy sets out how artificial intelligence tools may be used at [ORGANISATION], what may be entered into them, and what may not. It applies to all employees, contractors, temporary staff, interns, and volunteers, on any device, whether or not the device is owned by [ORGANISATION], when the work being done is [ORGANISATION] work. It covers any tool that sends text, files, images, audio, or code to a system that generates or analyses content. That includes general assistants, coding assistants, meeting transcription services, translation tools, and AI features built into software [ORGANISATION] already licenses. The last category is the one policies usually miss. An AI summarisation feature inside an existing product is in scope even though nobody ever made a decision to adopt an AI tool. ## 2. Definitions **AI tool.** Any software that processes an input to generate content, a summary, a classification, a translation, or code, using a machine learning model. Includes standalone products and features embedded in other products. **Public AI tool.** An AI tool where inputs are transmitted to a provider outside [ORGANISATION]'s control, under that provider's own terms. **Prompt.** Anything submitted to an AI tool: typed text, pasted text, uploaded files, images, screen shares, audio, or code. **Output.** Anything an AI tool returns. **Confidential information.** As defined in [EXISTING CONFIDENTIALITY OR INFORMATION SECURITY POLICY]. This policy does not create a second definition. **Personal data.** Any information relating to an identified or identifiable person, as defined by [APPLICABLE LAW, e.g. UK GDPR, EU GDPR, or your local equivalent]. ## 3. Roles and responsibilities **[ROLE, e.g. the Data Protection Officer or Head of Information Security]** owns this policy, maintains the approved tool register in Annex A, and decides exception requests. **Line managers** are responsible for their team knowing that this policy applies to them, and for raising a request rather than allowing a quiet workaround. **All staff** are responsible for what they put into a prompt and for what they do with an output. Using an AI tool does not transfer responsibility for the work to the tool. **[ROLE, e.g. IT]** maintains the technical controls that support this policy and reports on tool usage to the policy owner [FREQUENCY]. Exception requests go to [ROLE OR MAILBOX]. A decision is given within [NUMBER] working days. ## 4. Approved tools Only tools listed in Annex A may be used for [ORGANISATION] work. Tools are listed in one of three tiers. **Tier 1, approved.** Use freely, within the data rules in section 5. These are tools where [ORGANISATION] holds a contract with terms we have reviewed, covering training, retention, and where data is processed. **Tier 2, conditional.** Use only for the purposes and data tiers listed against the tool in Annex A. These are tools with an acceptable use case and a limitation, for example a provider that processes data outside [JURISDICTION], or a free tier whose terms permit training on inputs. **Tier 3, prohibited.** Do not use for any [ORGANISATION] work. This tier exists so that specific tools can be named, because "not approved" and "banned" are read differently. A tool that is not in Annex A is not approved. Section 12 explains how to ask for one to be added. Do not assume that a tool being widely used elsewhere in the industry means it has been assessed here. Personal accounts on approved tools are not approved. Use the account [ORGANISATION] provides. A personal account puts the work outside our contract, outside our retention terms, and outside our ability to retrieve or delete anything. ## 5. What may be entered into an AI tool This is the operative clause of the policy. Everything else supports it. Data is classified in the tiers defined in [EXISTING DATA CLASSIFICATION POLICY], or in Annex B if [ORGANISATION] has no existing scheme. | Data tier | Public AI tools | Tier 1 approved tools | What this covers | | --- | --- | --- | --- | | Public | Permitted | Permitted | Already published or approved for publication | | Internal | Not permitted | Permitted | Ordinary business information, not sensitive | | Confidential | Not permitted | Permitted with masking or written approval | Client work, commercial terms, unpublished plans, source code | | Restricted | Never | Never | Personal data of clients, staff, or patients. Special category data. Regulated records. Credentials. Privileged material | Adjust these tiers to match the classification scheme [ORGANISATION] already uses rather than introducing a parallel one. Two schemes means neither gets used. The rule staff need to remember is short: **if the tool does not need to know who the person is in order to do the task, the person's identity does not belong in the prompt.** ## 6. Prohibited uses The following are prohibited regardless of tool tier. 1. Entering personal data of clients, customers, patients, or staff into any AI tool not approved for that data tier. 2. Entering special category data, including health, biometric, genetic, racial or ethnic origin, political opinions, religious beliefs, trade union membership, sex life, or sexual orientation data, into any public AI tool. 3. Entering credentials, API keys, access tokens, or security configuration into any AI tool. 4. Entering material covered by legal professional privilege into any tool not explicitly approved for it. 5. Entering third-party confidential information where our contract with that third party does not permit disclosure to a subprocessor. See section 9. 6. Using AI output as the sole basis for a decision that materially affects a person, including decisions on employment, credit, benefits, admission, discipline, or care. See section 7. 7. Presenting AI-generated work as though it were produced without AI where a client, a court, a regulator, or a publisher requires disclosure. 8. Using AI tools to generate content that would breach [ORGANISATION]'s existing policies on conduct, discrimination, or harassment if a person had written it. 9. Circumventing a technical control that implements this policy. ## 7. Human review and accountability for output A person is accountable for every output used in [ORGANISATION] work. The tool is not. Before output is sent to a client, filed, published, or committed, the person using it must: - Verify every factual claim, figure, citation, and legal reference against a source. AI tools produce confident, well-formatted, wrong answers, and citations to material that does not exist are a known and recurring failure. - Confirm the output does not reproduce someone else's protected material. - Confirm the output is appropriate for the audience and consistent with [ORGANISATION]'s standards. For decisions with a material effect on a person, a qualified human makes the decision. AI output may inform it. **[CHECK LOCAL LAW: rules on automated decision-making vary, and requirements covering AI in employment, credit, and healthcare decisions are changing quickly.]** ## 8. Transparency and disclosure [ORGANISATION] discloses its use of AI where a client, regulator, court, publisher, or counterparty requires it, and where a reasonable person would expect to be told. Disclose when: - A client contract or a professional body rule requires it. - Output is submitted to a court, a regulator, or a public body with rules on AI-assisted submissions. - A person is interacting with an AI system and might reasonably believe they are interacting with a person. - [ADD YOUR OWN CATEGORIES] Routine internal assistance with drafting, summarising, and formatting does not require disclosure unless the above applies. ## 9. Client and third-party data Where [ORGANISATION] holds data belonging to a client or another organisation, our contract with them governs what we may do with it. That contract usually predates AI tools and rarely mentions them. Before entering third-party data into any AI tool, confirm that: 1. The contract permits disclosure to subprocessors, and the AI provider fits within that permission. 2. Any subprocessor notification or approval requirement has been met. 3. The client has not issued a specific instruction about AI use. Some have. Check. Where the position is unclear, treat the data as Restricted until [ROLE] confirms otherwise. In most cases the practical alternative is to remove the identifying and confidential content before the prompt leaves, so that no third-party data is disclosed at all. Section 16 covers this. ## 10. Data protection Entering personal data into an AI tool is a processing operation and requires a lawful basis. Where the provider processes data outside [JURISDICTION], it may also be a restricted international transfer requiring safeguards. **[CHECK LOCAL LAW: transfer rules and adequacy findings differ by jurisdiction and change over time.]** Accordingly: - A new AI tool that will process personal data requires a data protection impact assessment before approval, or a documented assessment that one is not required. - The record of processing activities is updated when an AI tool is approved for personal data. - Data subject rights, including access, rectification, and erasure, apply to data held by an AI provider on our behalf. Confirm before approval that we can meet those requests. - Data minimisation applies to prompts exactly as it applies everywhere else. A prompt carrying a whole record in order to answer a narrow question is not minimised. ## 11. Intellectual property and confidentiality Output from AI tools may not be protectable by copyright in every jurisdiction, and may resemble material the model was trained on. Consult [ROLE] before relying on output as [ORGANISATION] intellectual property. Inputs to a public AI tool may be retained by the provider and may be used to improve its models, depending on that provider's terms. Entering unpublished confidential material into such a tool risks the confidentiality of that material and may breach an obligation we owe to someone else. Source code is confidential information. Code containing credentials, proprietary algorithms, or client-specific logic follows the same rules as any other confidential material. ## 12. Requesting a new tool To request that a tool be added to Annex A, send [ROLE OR MAILBOX]: 1. The tool, the vendor, and the plan or tier. 2. What you want to use it for, specifically. 3. What data would go into it. 4. Whether a free tier or a personal account is involved. [ROLE] assesses the request against the provider's terms on training and retention, where processing happens, security posture and certifications, the subprocessor list, deletion and export capability, the contractual terms available to us, and whether an approved tool already covers the need. Do not start using a tool while a request is pending. ## 13. Records and monitoring [ORGANISATION] [DOES / DOES NOT] monitor AI tool usage on managed devices and networks. Where monitoring occurs it is carried out under [EXISTING MONITORING POLICY] and staff are informed of it. **[CHECK LOCAL LAW: workplace monitoring rules and works council consultation requirements vary significantly, and getting this wrong is itself a compliance failure.]** [ROLE] maintains the approved tool register and a record of exception decisions. ## 14. Incidents If confidential or personal data has been entered into an AI tool in breach of this policy, report it to [ROLE OR MAILBOX] within [NUMBER] hours of realising. Report it even if you are not sure. Report it even if it was you. Do not delete the conversation before reporting, because the record may be needed for the assessment. Handling follows [EXISTING INCIDENT RESPONSE PROCEDURE]. The assessment considers what was disclosed, to whom, under what terms, whether it can be retrieved or deleted, and whether the event is notifiable to a regulator or to affected individuals under [APPLICABLE LAW]. Reporting in good faith will not result in disciplinary action. Concealing an incident may. This wording is deliberate. A policy people are afraid of produces silence, and silence turns a small disclosure into an undetected one. ## 15. Training All staff complete AI usage training at induction and [FREQUENCY] thereafter. Staff handling [REGULATED DATA CATEGORY] complete the additional module covering [SPECIFICS]. Training covers what this policy permits, how to recognise data that must not be entered, how to check output, and how to report an incident. ## 16. Reducing exposure at the boundary A policy controls behaviour only as far as people follow it, and prompt-by-prompt judgement is the weakest control in any information security programme. Where possible, [ORGANISATION] prefers controls that make a breach of section 5 difficult rather than merely forbidden. That includes: - Removing or masking personal and confidential data from text before it reaches an AI tool. - Providing approved tools good enough that workarounds are not tempting. - Making the approved path faster than the unapproved one. [DESCRIBE THE CONTROLS YOU ACTUALLY HAVE. Delete this section if you have none, rather than describing an intention as though it were a control.] ## 17. Review This policy is reviewed [FREQUENCY] by [ROLE], and additionally when a significant new tool is adopted, when the regulatory position changes, or after any incident under section 14. ## Annex A: Approved tool register | Tool | Vendor | Tier | Approved for | Data tiers permitted | Account type | Reviewed | | --- | --- | --- | --- | --- | --- | --- | | [Tool] | [Vendor] | 1 | [Purposes] | Public, Internal, Confidential | [ORGANISATION] SSO | [DATE] | | [Tool] | [Vendor] | 2 | [Named purposes only] | Public, Internal | [ORGANISATION] SSO | [DATE] | | [Tool] | [Vendor] | 3 | Prohibited | None | None | [DATE] | Keep this register somewhere staff can find in under ten seconds. A register nobody can locate is a register nobody consults. ## Annex B: Data classification, short version Use this only if [ORGANISATION] has no existing classification scheme. If one exists, delete this annex and reference the real one. **Public.** Published, or approved for publication. Marketing material, public filings, the website. **Internal.** Ordinary business information whose disclosure would be unwelcome but not harmful. Internal process documents, routine team communication. **Confidential.** Disclosure would cause harm to [ORGANISATION], a client, or a partner. Client deliverables, commercial terms, unpublished plans, source code, security documentation. **Restricted.** Disclosure would cause serious harm, or the data is regulated. Personal data, special category data, financial records, medical records, privileged material, credentials, and anything covered by a specific confidentiality undertaking. ## Annex C: Incident report form | Field | Entry | | --- | --- | | Reported by | | | Date and time of the event | | | Date and time noticed | | | Tool involved | | | Account used (organisation or personal) | | | What was entered | | | Data tier | | | Number of people whose data was involved | | | Whose data (clients, staff, patients, third party) | | | Conversation deleted or retained | | | Any output shared onward | | | Immediate action taken | | Send to [ROLE OR MAILBOX]. Do not include the affected data itself in this form. Describe it. ## Annex D: One-page card for staff Circulate this on its own. It is the part people will read. ### Using AI at [ORGANISATION] **Use these tools:** [LIST]. Sign in with your [ORGANISATION] account, never a personal one. **Never put these into any AI tool:** - Names, contact details, or anything identifying a client, customer, patient, or colleague - Health, financial, or other regulated records - Passwords, API keys, access tokens - Anything a client has told us to keep confidential - Unpublished contracts, commercial terms, or source code, unless the tool is approved for it **Safe to use it for:** drafting, rewriting, summarising your own notes, explaining a concept, generating code that contains nothing specific to a client, formatting, and translating public material. **Before the output goes anywhere:** check every fact, figure, name, and citation. The tool will be confidently wrong sometimes, and it is your name on the work. **If you paste something you should not have:** tell [ROLE OR MAILBOX] straight away. Do not delete the chat first. Nobody is in trouble for reporting. **Not sure?** Ask [ROLE OR MAILBOX] before you paste, not after. --- # Use AI on case files. Keep the file privileged. Source: https://velumprivacy.com/use-cases/legal Draft, summarise and compare on the real file, with the client, the counterparty and the matter masked before anything leaves your machine. Before: Instruct counsel for Marina Folch Moros, NIF 48023306L, in matter M-204817. Balance of EUR 200,000 payable to ES91 2100 0418 4502 0005 1332. After: Instruct counsel for ⟦PERSON_1⟧, NIF ⟦DNI_NIF_1⟧, in matter ⟦INTERNAL_ID_1⟧. Balance of EUR 200,000 payable to ⟦IBAN_1⟧. - **What gets masked.** Client and counterparty names, national identifiers, matter and case references, addresses, contact details and bank details. Amounts stay, because the amount is usually the question. - **The privilege question.** A cloud redaction service has to receive the raw file first, which puts one more third party in the chain. With on-device masking the identifying details never reach anyone, so your confidentiality analysis starts from what was actually disclosed. - **Consistent parties.** Each person keeps the same stand-in through the document, so the assistant can tell the parties apart and the restored draft puts every name back where it belongs. A modern practice has every reason to use AI and one good reason not to: the text of the work is the confidential part. Banning the tools moves the work to personal phones; allowing them accepts the exposure. Masking is the fourth option. The assistant reasons about the structure of the matter without seeing whose matter it is. --- # AI help with the paperwork. Nothing about the patient leaves. Source: https://velumprivacy.com/use-cases/healthcare Draft the letter and tidy the summary with names, dates of birth and record numbers replaced on the device, never sent. Before: Discharge summary for Tomas Keller, born 14/03/1961, NHS 943 476 5919, of 12 Rowan Court, Leeds. After: Discharge summary for ⟦PERSON_1⟧, born ⟦DATE_1⟧, NHS ⟦NHS_NUMBER_1⟧, of ⟦ADDRESS_1⟧. - **What gets masked.** Names, dates of birth, addresses, contact details and identification numbers. In pseudonymised mode a shifted date stays a plausible date, so the note still reads as a note. - **Where it runs.** The browser extension does the whole round trip with no network access, which you can test by pulling the connection. A cloud de-identification API has to receive the identifiable text before it can remove anything. - **Measured, not promised.** Precision, recall and what still slips through are published per language, along with the honest part: no detector catches everything, so read the numbers before relying on them. Clinical work generates exactly the text an assistant is good at, and exactly the text with the least room for error in handling. A patient note is identifying almost by definition. The pasting already happens. The choice is not whether AI touches clinical text, but whether anything identifying is still in it when it does. --- # Let AI read the numbers. Not the names on them. Source: https://velumprivacy.com/use-cases/accounting Summarise the ledger, draft the client letter and check the rule, with tax identifiers and bank details replaced before anything is sent. Before: Payroll query for Ines Duarte, NIF 48023306L, salary paid to ES91 2100 0418 4502 0005 1332, mobile 612 345 678. After: Payroll query for ⟦PERSON_1⟧, NIF ⟦DNI_NIF_1⟧, salary paid to ⟦IBAN_1⟧, mobile ⟦PHONE_1⟧. - **Built for the formats.** Country packs for Spain, the US, the UK, France, Germany, Turkey and Italy recognise national identifiers as identifiers rather than as digits. Spain shipped first, so NIF and NIE are first-class. - **The numbers survive.** What gets masked is who the figures belong to. Amounts stay usable, so a ledger summary comes back structurally correct and the real details are restored on your side. - **Format-valid when you need it.** Pseudonymised mode substitutes a plausible NIF for a real one, so the model treats the text as ordinary. Tokenised mode makes the veil visible, so you can check it before sending. A practice runs on identifying data: tax identifiers, bank details, payroll figures, home addresses. The files are made of exactly what should never be pasted into a chatbot. The free tier of the extension needs no key and no account, so trying this on a real ledger costs two minutes. --- # Analyse the material. Protect the people in it. Source: https://velumprivacy.com/use-cases/research Code and compare transcripts with participants masked consistently across the whole folder, and the mapping never leaving your machine. Before: P07, Yolanda Martinez Jarque, teacher at Institut Balmes, Barcelona, interviewed 12/05/2026. After: P07, ⟦PERSON_1⟧, teacher at ⟦ORG_1⟧, ⟦LOCATION_1⟧, interviewed ⟦DATE_1⟧. - **Consistent across files.** The same participant keeps the same stand-in through a folder of transcripts, so coding and thematic analysis still track who said what. - **Pseudonymisation, stated plainly.** Identifiers are replaced and a local mapping can restore them. Whether that meets your board's anonymisation standard is their call; what is factual is that the mapping never leaves the researcher's machine. - **Testable for an ethics application.** The extension's round trip runs with no network access at all, which is worth a sentence in a protocol precisely because a reviewer can test it rather than take it on trust. Qualitative material is personal by nature. The value is in what people said, and the risk is that they can be identified as having said it. Ethics approval usually assumes the data stays inside the research team, which pasting a transcript into a chatbot quietly breaks. --- # How to check if a PDF is really redacted (2026-09-14) Source: https://velumprivacy.com/blog/check-pdf-redaction **To check a redacted PDF, reopen the exact file you plan to send, inspect every page, try searching and copying the removed text, and review hidden content such as metadata and attachments.** If a private value is still visible or recoverable, the file fails. If those checks find nothing, they are useful evidence, but they are not a guarantee that the document contains no sensitive information. That last distinction matters. A PDF can have correctly removed one name and still expose the same person in a signature, a filename or the description of an unusual event. Reviewing the redaction operation and reviewing the remaining disclosure are two separate jobs. ## Start with the exported file Do the review on a saved output copy, after closing the editing view. Open it from the folder you will attach it from, preferably in a second local PDF reader as well. The editor may be showing marks that have not yet been applied. Adobe's [redaction instructions](https://helpx.adobe.com/acrobat/desktop/protect-documents/redact-pdfs/redact.html) distinguish marking an area, applying the redaction, choosing whether to sanitize hidden information, and saving the result. A screenshot of the marks does not establish what was saved. Give the output a neutral filename such as `contract-review-redacted.pdf`. Keep the original separately. Avoid placing the client's name, account number or matter description in the attachment name after removing it from the pages. ## Review the whole document, including what was left visible Open every page at a readable size. Check the margins, repeated headers, footers, tables, handwritten notes and signature areas. Compare the original and output locally when necessary to confirm that each intended removal was applied. Make a short list of information that must not travel with this particular document. For a fictional contract review, that might include the parties' names, home addresses, account details, signatures and a case reference that identifies the matter. The exact list depends on the recipient and purpose; a generic detector cannot decide all of it for you. Then read the remaining text as a recipient would. If the only local employee with a particular title is described alongside a salary and a specific incident, replacing the name may still leave the person identifiable. Our guide to [personal data in an AI prompt](/blog/what-is-personal-data-in-ai-prompt) explains why combinations of facts matter. ## Search for values you intended to remove Use the reader's search function for a few known values from the original. Include a full name, an email address and a distinctive part of a longer identifier. Try variants when the original breaks a value over two lines or uses spaces inside an account number. Finding a supposedly removed value is a clear failure. Finding nothing has several possible explanations: - The value was removed correctly. - The page is an image with no searchable text. - The text encoding or OCR output differs from the value you searched for. - The sensitive information is present in another form, such as a signature image. Search is therefore a useful attempt to disprove the redaction. It is not a completeness test. ## Try selecting and copying around the redaction Select the area around a removed value, copy it, and paste into a local plain-text editor. Also try copying the whole page. If the original value appears, a visible covering has left recoverable text behind. Keep this check local. Pasting the extracted text into an online checker or an AI chat would disclose the material you are trying to inspect. An empty clipboard is not proof of a safe PDF. Image-only pages and copying restrictions can both make this test uninformative. Conversely, selectable text elsewhere is not automatically a redaction failure: some tools remove selected content while preserving accessible text in the rest of the document. The question is whether the content intended for removal survived. ## Inspect hidden content and the sharing package Review document properties, comments and attachments using your PDF tool's inspection or sanitization features. Redaction on a visible page does not, by itself, tell you what happened to those other parts of the file. Adobe offers a separate [PDF sanitization workflow](https://helpx.adobe.com/acrobat/desktop/protect-documents/redact-pdfs/sanitize.html) for hidden information. Use the equivalent documented feature in your chosen tool and inspect the saved result again afterward. The sharing package deserves a check too. A clean output can be sent alongside the original by mistake, or placed in a shared folder whose other files disclose the same details. Review the attachment list and destination immediately before sending. ## What Velum's permanent-redaction mode changes Velum's desktop **Redact permanently** mode renders each PDF page as an image, paints opaque bars into the selected regions and builds a new PDF from those page images. The output does not carry the original text layer or source document metadata. This is different from adding a movable rectangle over a page. The implementation has a deliberate cost: the output loses searchable and selectable text, including the text a screen reader would normally use. Files can also become larger. The original remains separate, and the redacted output has no restoration mapping. The [permanent-redaction release note](/blog/velum-0-9-0-permanent-redaction) explains the approach and its tradeoffs. That mechanism addresses removal at the marked locations. It does not prove that every sensitive location was found. A missed name remains visible in the new page image. A missed signature or identifying sentence remains available to the recipient. Detection and human review still determine what should be removed. For an AI task where you need names restored in the answer afterward, [reversible file masking](/blog/masking-files-not-just-text) may fit the workflow better. It also needs review: placeholders do not automatically make the remaining context anonymous. ## A review record you can reuse For a repeated sharing workflow, keep a brief record beside the private original: | Check | What to record | | --- | --- | | Purpose and recipient | Why this copy is being shared and what they need | | Output identity | The exact filename and version reviewed | | Visible content | Pages reviewed and categories intentionally removed | | Recovery checks | Search and copy checks performed, including their limitations | | Hidden content | Inspection or sanitization performed on the saved file | | Final review | Reviewer, date and any unresolved issue | This is a suggested working record, not a certification. It helps the next person understand which copy was reviewed and what that review covered. If a check exposes a value, regenerate the output and review it again instead of treating the earlier result as still applicable. ## Can I just flatten the PDF? Do not rely on the word "flatten" without understanding what the tool does. Flattening annotations, printing to another PDF and rebuilding pages from redacted pixels are different operations. Judge the saved output and the tool's documented removal behaviour, not the menu label. ## Does a black bar mean the information is gone? Only if the underlying content was actually removed or replaced in the output. A black bar is an appearance. The search, copy, hidden-content and page checks above help you test the file behind that appearance. Velum's detection and redaction run on your device. To use its permanent-redaction workflow, [download the desktop app](/desktop), review the output locally, and send only the copy you checked. --- # Where personal data hides in a repository (2026-09-09) Source: https://velumprivacy.com/blog/where-personal-data-hides-in-a-repository Ask a team whether their repository contains personal data and the answer is almost always no, said quickly. Ask instead where their test fixtures came from and the answer slows down. Personal data does not get committed on purpose. It arrives as a side effect of trying to make something realistic, or of debugging something at two in the morning. It then sits there, in a place nobody thinks of as a data store, until a laptop is stolen, a repository is made public, a contractor is onboarded, or an AI coding agent reads the file to answer a question about something else entirely. That last one changed the exposure. A colleague reads the files they open. An agent reads the files it decides it needs, and you find out which ones afterwards. We wrote about [what Claude Code actually sends](/blog/does-claude-code-send-my-code-to-anthropic) if you want the specifics for one tool. Here is where to look. ## 1. Test fixtures The most common one, and the most defensible in the moment. A fixture built from a production export has the right shape, the right edge cases, the accented names and the addresses that break the parser. That is exactly why someone made it that way, and why it is real. ## 2. Seed and migration scripts A seed file that populates a dev database with "a few real accounts so it looks like something". A data migration written to backfill a column, with a handful of production rows pasted in as a worked example in a comment. Migrations are especially sticky: they are append-only by convention, so nobody ever deletes one. ## 3. Recorded HTTP traffic VCR cassettes, snapshot tests, `.har` files, saved API responses. These are dumps of real requests and responses, complete with the bearer token in the header and the customer object in the body. They are usually large, machine-generated, and never read by a human after the day they were recorded. ## 4. Logs and error payloads committed for debugging Someone pastes a stack trace with a full request payload into an issue, then into a file, then commits it because the branch was about fixing that error. Log fixtures used to test a parser are the same thing with a better excuse. ## 5. Sample uploads A CSV in `fixtures/`, a PDF in `test/files/`, an image in the README. Sample documents are almost always a real document from a real customer, because generating a convincing one is work and the real one is right there. ## 6. Comments "Per the call with Maria at Acme, the cutoff is the 15th." "Workaround for ticket 4412, customer's IBAN has a trailing space." Comments carry names, ticket detail and the occasional identifier, and no scanner built for code looks at them closely. ## 7. Local configuration that escaped `.env` is usually ignored. `.env.example` is usually not, and it is usually populated by copying `.env` and forgetting one line. The same goes for `docker-compose.override.yml`, a Postman collection, an editor workspace file with a connection string. ## 8. Binary and database files A committed `dev.sqlite`, a `.dump`, a spreadsheet used for a one-off calculation. Text search misses them entirely, which is also why nobody has ever audited them. ## 9. Git history Deleting the file fixes the working tree, not the repository. The old contents are still in history, still in every clone, and still fetched by CI. This is the one that turns "we removed that years ago" into a false statement. ## How to actually look Start with structure, not with grep: ```sh # Files that were deleted at some point, with their old contents still in history git log --all --diff-filter=D --name-only --pretty=format:'%h %ad' --date=short # Everything a text search will never open git ls-files | grep -Ei '\.(csv|xlsx?|pdf|sqlite3?|db|dump|har|png|jpe?g)$' # The usual suspects by name git ls-files | grep -Ei 'fixture|seed|sample|cassette|snapshot|\.env' ``` Then search content, and be honest about what that finds. Patterns are excellent at structured identifiers: email addresses, IBANs, card numbers, national IDs, API keys. They are useless at the single most common category of personal data, which is a person's name. There is no regular expression for "Maria Öztürk" that does not also match half your variable names. We measured this on our own benchmark corpus while building the masking path for coding agents: a pattern-only tier misses **37% of the values that must not leak**, averaged over nine labelled sets. Not because the patterns are bad, but because names, and the sentences around them, are not patterned. Every result you get from `grep` is real, and the number you did not get is the one that matters. ## What to do about it In rough order of how well it works: 1. **Delete what should not be there and stop the source.** A fixture generator with fake data is a day of work and it ends the problem permanently. 2. **If it was ever public or ever on a laptop you no longer control, treat it as disclosed**, and handle it as a data incident under your own policy rather than as a cleanup task. 3. **Rewriting history is possible and expensive.** `git filter-repo` rewrites every commit hash, which breaks open branches, tags, signed commits and anything referencing a SHA. Worth it for a leaked key. Rarely worth it for a fixture. 4. **Assume the rest exists**, because the audit above finds what you thought to look for, and put a boundary between it and anything that leaves the machine. ## The boundary we build That last point is what Velum does. It runs on your machine and masks personal data at the moment a file is read by an AI coding agent, so the model works on `⟦PERSON_1⟧` and `⟦IBAN_2⟧` instead of the values. When the agent writes back, the real values go in first, so the file on disk is unchanged. Some files are withheld rather than masked: `.env`, private keys, certificates. If detection fails, the content is withheld too, because a mask that silently falls back to the real thing is worse than no mask. Two limits worth stating in the same breath. A prompt you type yourself reaches the model before any file is read, so masking a repository does not protect you from typing a client's name into the chat box. And this is a boundary, not a cleanup: the data is still in the repository afterwards, and points 1 through 3 above are still yours to do. Detection runs locally. No file content, and no identifier derived from one, is uploaded to us or to anyone else. [Get Velum for macOS or Linux](/desktop) *Seven-day trial, no key and no account.* --- # The AppImage that launched and rendered nothing (2026-09-09) Source: https://velumprivacy.com/blog/appimage-that-rendered-nothing Velum's Linux build shipped on 19 August as an AppImage and a .deb, verified on a real desktop the same day. Two weeks later it turned out to be broken on a machine we had not tested: current Arch, Hyprland, AMD graphics. The app launched. A window appeared. The window was empty, and stayed empty. This is the worst shape a bug can take. There was no crash dialog, no log line in the user's face, nothing to search for. From the outside it looked like the app had started and decided to do nothing. ## What the terminal said Launching the same AppImage from a terminal produced the line that the GUI never showed: ``` Could not create default EGL display: EGL_BAD_PARAMETER. Aborting... ``` "Aborting" is literal. Velum's desktop app is a Tauri app, so its UI is a WebKit web process. That process calls `abort()` and dies. GTK, meanwhile, has already mapped the window. So the frame is real, it is on your screen, and there is nothing behind it. ## Why a bundled library broke the host's graphics An AppImage is one file that carries the app and its dependencies, mounted at runtime. The point is that it runs on distributions the build machine has never heard of. The catch is that a small set of libraries must not travel with it, because they are the ones that talk to hardware and to the running compositor. Ship your own copy of those and you force the host's drivers to work with a stranger. AppImageKit publishes an excludelist for exactly this, and `libwayland-client`, `libwayland-cursor`, `libwayland-egl` and `libwayland-server` are on it. Our build tool, `linuxdeploy-plugin-gtk`, deployed all four into the AppDir anyway. On Ubuntu 24.04, where the image is built, nothing happens: the bundled copies match the host closely enough. On a host whose Wayland and Mesa are newer, the bundled copies win the lookup and shadow the host's. Mesa's `libEGL` then fails to initialise against a Wayland client library older than the compositor it is speaking to, and gives up. The failure is therefore invisible to CI and invisible to any test on the build platform. It only appears on the distributions that update fastest, which is a good description of the Linux desktop audience for a developer tool. ## Narrowing it The AppDir can be unpacked, edited and repacked, which makes this testable by hand: - Remove the four libraries. The app renders. - Put them back. The window is empty again. - Remove them again. The app renders. Present, absent, present. Deleting exactly those four files is both necessary and sufficient. No environment variable was a substitute: `WEBKIT_DISABLE_DMABUF_RENDERER`, `WEBKIT_DISABLE_COMPOSITING_MODE` and `LIBGL_ALWAYS_SOFTWARE` all still abort, because the process dies inside EGL initialisation, before any of those switches change a decision. ## The fix that would have been worse Stripping the files is easy. Putting the AppImage back together is where the trap is. The obvious move is to repack with `appimagetool`. That produces a working file, and it quietly replaces the AppImage runtime, the small executable header that mounts the payload when you run it. The runtime `linuxdeploy` ships is a static-pie build that mounts through `fusermount3`. The one `appimagetool` bundles is the old FUSE 2 runtime, and Ubuntu has not shipped `libfuse2` by default since 22.04. Every user on a modern Ubuntu would double-click the file and get nothing. Trading a blank window on Arch for a dead download on Ubuntu is not a fix. So the repack splices the original runtime back on instead: ```sh offset=$(./Velum.AppImage --appimage-offset) params=$(unsquashfs -o "$offset" -s ./Velum.AppImage) comp=$(awk '/^Compression/ {print $2}' <<<"$params") bs=$(awk '/^Block size/ {print $3}' <<<"$params") head -c "$offset" ./Velum.AppImage > runtime.bin mksquashfs Velum.AppDir payload.sqfs -root-owned -noappend -comp "$comp" -b "$bs" cat runtime.bin payload.sqfs > repacked ``` Compression and block size are read back off the original build rather than assumed, so the artifact is otherwise equivalent to what Tauri produced. The build step then re-extracts the result and fails if any `libwayland` file survived, and it also fails if it finds none to remove in the first place, because that would mean the tool's behaviour changed and the step is now protecting nothing. ## We republished 0.14.0 rather than bumping it The fixed build went out as 0.14.0 again, same version number, same filenames. That looks sloppy and it was deliberate. Our update manifest carries a single top-level version, so publishing Linux as 0.14.1 would have set the manifest to 0.14.1 and dropped the macOS entry, taking macOS updates dark until a matching Mac build shipped. Republishing in place keeps every platform's entry alive. The cost is that existing Linux 0.14.0 installs get no update prompt, since the manifest version equals theirs. That is acceptable here only because the broken installs render nothing and could not have used an update prompt anyway. It is not a habit, and a version number is normally the one thing you do not reuse. The rebuild also picked up a change that had landed on `main` in the meantime: the bundle no longer stages the four foreign-platform ONNX Runtime binaries it never loads. The AppImage went from 401 MB to 336 MB in a release that was supposed to change nothing. A republish is not a rebuild of the same tree, which is worth knowing before you tell someone the bytes are identical. ## If you ship a GTK or WebKit app as an AppImage Three things carry over from this: 1. **Test on a distribution newer than your build image.** Ubuntu LTS building for Ubuntu LTS proves very little. The bug lives in the gap between the build image's system libraries and the host's, so a current Arch or Fedora box is the test that matters. 2. **Check what your packaging tool actually deployed.** `find` your AppDir for anything on the AppImageKit excludelist. Being on the list is not enforcement. 3. **Treat a mapped window with no content as a dead subprocess, not a rendering bug.** Run from a terminal first. The message is usually there, addressed to nobody. Velum for Linux is a single AppImage, no install, no account, and a seven-day trial with no key. [Get it here](/desktop). If you run Ubuntu 22.04 or Debian 12 it will not start: the build has a glibc floor of Ubuntu 24.04, which is a different post. --- # The case for local AI processing (2026-08-17) Source: https://velumprivacy.com/blog/future-of-local-ai The dominant story in AI has been that bigger is better: more parameters, more data centres, capability that necessarily lives somewhere else. That story is still mostly right about frontier models, and increasingly wrong about everything else. ## What centralised AI costs Cloud inference has delivered genuinely remarkable capability. It also carries costs that are hard to design around. Latency that makes interactive work feel sluggish. Data residency rules that rule out whole sectors. And a structural tension: the more capable the service, the more of your context it wants, and the less say you have in where that context ends up. For regulated work, that last point is not a preference. A solicitor pasting a contract into a hosted model has disclosed personal data to a processor they may never have assessed. ## Local is a different shape, not a smaller one On-device inference is not cloud inference with the numbers turned down. It is a different set of trade-offs. A model on your laptop already has your context without uploading it. It answers without a round trip. It works on a plane, in a secure facility, and on a network you do not trust. The hardware moved. Apple Silicon in particular made quantised transformer inference practical on a machine someone already owns, which is why Velum's desktop app ships for Apple Silicon and bundles its default model rather than calling out to anything. Not everything belongs on-device. A frontier model answering a hard question is doing something a laptop cannot. The useful division is not cloud versus local, it is deciding which half of the work touches data that should not travel. Detection and masking are exactly that half. ## What it changes for builders Bundling a model instead of calling an API changes the shape of the problem. You trade rate limits and per-request pricing for install size and memory. Velum's macOS download is around 318MB, and most of that is the detection model sitting inside it. That is the honest cost of not phoning home, and we would rather pay it in bytes than in disclosures. It also changes what you can promise. "We do not send your text anywhere" is a claim someone can verify with a network monitor in about a minute. Very few cloud products can offer a customer a test that decisive. ## Where Velum actually is **Update, August 2026: Velum for Linux has since shipped, and the extension is now on Firefox as well as Chrome. Windows is still in development. The paragraph below reflects the product when this piece was published.** The macOS app runs on Apple Silicon. The browser extension works on Chrome and Chromium, through a popup you paste into, with an optional in-page button for ChatGPT, Claude and Gemini. The Atlassian app for Jira and Confluence is live on the Marketplace. Windows and Linux are not shipped, and we are not going to pretend otherwise while people are deciding whether to wait. Both shipping apps run for seven days with no account and no card. The next generation of tools handling sensitive work will not ask you to trust a remote server. They will show you there is nothing to trust. [Download Velum](/#downloads), or [see where it fits](/use-cases). --- # How Velum detects personal data without a cloud (2026-08-13) Source: https://velumprivacy.com/blog/pii-detection-techniques Personal data detection is normally a cloud service. You post your text to an API, it returns labelled entities, and you hope the provider's retention policy matches what you told your clients. That model is the thing we are trying to avoid, so everything below runs on the machine in front of you. ## Three levels, and the trade each one makes Velum ships three detection intensities. They are not marketing tiers; they are genuinely different machinery, and the app lets you switch between them because the right answer depends on the document. **Pattern rules only.** Regular expressions with checksum validation, no model at all. This catches structured identifiers: emails, phone numbers, card numbers, IBANs, national ID numbers. Where a format carries a check digit, we validate it rather than just matching the shape, which is the difference between finding a Spanish NIF and finding any nine characters that look like one. Instant, deterministic, and auditable in the sense that you can read the rule and see why it fired. **Regex plus on-device AI.** This is the default. It adds a quantised BERT NER model that ships inside the app, so it works the moment you install it with no download and no network. The bundled model is around 173MB on disk, which is most of why the macOS download is as large as it is. This level catches what patterns cannot: names, addresses, organisations, and the ambiguous cases in mixed-language text. **Maximum.** A GLiNER model, roughly 1.1GB, which is not bundled. You download it from Settings when you want it. It is the strongest protection we offer and it is slower on long documents, which is the honest trade rather than a hidden one. ## The number we can stand behind At the default level, we measure roughly **2% residual leak on Spanish and Catalan text**. That is the figure the app itself shows you when you hover the intensity setting, and it is why Maximum exists. Two percent is not zero. We publish it because a privacy tool that implies zero is either lying or has not measured. If you are working with a document where a single missed identifier is unacceptable, use Maximum, and read the masked output before you send it. We are not publishing latency benchmarks yet. We could quote a number from one machine on one document and it would tell you nothing useful about yours. What we can say is that the pattern layer is effectively instantaneous, the default level is fast enough that people leave it on, and Maximum is noticeably slower on long files. ## Why the model runs here and not there Because the model runs on your device, it never sees anyone else's data, and yours never joins a training set. There is no fine-tuning on your domain, no cross-contamination between organisations, and no provider retention window to reason about. The privacy property comes from the architecture, not from a policy document that can be revised. It also means the tool works on a plane, in a secure facility, and on a network you do not trust. ## What this cannot do Detection quality varies by language, by document type, and by how unusual the data is. Names that look like ordinary words, identifiers in formats we do not have a pack for, and text extracted badly from a scanned PDF are all harder. Velum reduces exposure substantially. It is not a guarantee, and anyone selling you one is describing a product that does not exist. See the detection levels for yourself: [download Velum](/#downloads), or [read the licensing terms](/licensing). --- # Does Claude Code send my code to Anthropic? (2026-08-13) Source: https://velumprivacy.com/blog/does-claude-code-send-my-code-to-anthropic Yes. Claude Code runs on your machine, but it is a client for a model that does not. Anthropic's own documentation is direct about it: Claude Code "sends data over the network. This data includes all user prompts and model outputs, encrypted in transit via TLS 1.2+." That is the easy half of the answer. The half that decides whether you can use it on a client's repository is narrower: which parts of your machine reach the API, how long they are kept, whether they train a model, and which of those you can turn off. Below is what the [data usage documentation](https://code.claude.com/docs/en/data-usage) states as of August 2026, followed by what you can do about it. If you want the version of this argument that applies to pasted text rather than agent traffic, we [measured how much slips past a detector](/benchmarks) on 1,800 labelled spans. ## What actually leaves Not "your repository". Claude Code does not upload a project. It sends what the model needs to answer, one turn at a time: - **Your prompts.** Every word you type. - **The contents of every file the agent reads.** A tool result is just more text in the request. If the agent opens a fixture with real customer names in it, those names are in the request. - **Command output.** `git log`, a failing test, `cat customers.csv`. Same path. - **Web fetches.** Whatever the page returned. The practical consequence is that the boundary is not "files I chose to share". It is "files the agent decided it needed", and you find out which ones after the fact. Two things are stated as not leaving. Usage metrics "never include your code, prompts, or file paths". Error reports carry stack traces from Claude Code's internals, with known patterns of secrets, file paths, email addresses and other personal information redacted before anything is sent. Both have switches: `DISABLE_TELEMETRY=1` and `DISABLE_ERROR_REPORTING=1`. ## Training and retention, by plan This is where the answer splits, and where most of the confusion lives. **Free, Pro and Max.** Anthropic trains new models on data from these accounts when the setting is on, and that explicitly includes Claude Code used from them. Retention follows the same switch: five years if you allow training, thirty days if you do not. The control is at `claude.ai/settings/data-privacy-controls`. **Team, Enterprise, API and third-party platforms.** Anthropic does not train generative models on code or prompts sent under commercial terms unless the customer opts in, for example through the Development Partner Program. Standard retention is thirty days. Zero data retention exists for Claude Code on Claude for Enterprise, but it is not part of the standard Enterprise plan: it is enabled per organisation after an eligibility check. So a developer on a personal Max subscription and a developer on their employer's Enterprise account are running the same binary under materially different terms. The plan is the policy. ## The three paths that send code you did not mean to send All three are opt-in. All three are easy to trigger without thinking about it. **`/feedback`, `/bug` and `/share`.** These submit a copy of your conversation history, including code, and they are retained for five years. You choose how much history goes: the current session by default, or other sessions from the same project over the last 24 hours or 7 days. `DISABLE_FEEDBACK_COMMAND=1` removes the command. **The session quality survey follow-up.** The star rating itself records nothing but the rating. The question after it, asking whether Anthropic can look at your session transcript, is a different thing: answering yes uploads the conversation, subagent transcripts and the raw session log from disk. Known API key and token patterns are redacted first. Source code and file contents are uploaded as they are. Retained up to six months. `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1` stops being asked. **Cloud sessions.** Claude Code on the web clones your repository into an Anthropic-managed VM by default. Retention and usage follow your account type, which returns you to the table above. `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` covers the whole non-essential group at once. One thing it does not cover: before fetching a URL, the WebFetch tool sends the hostname to `api.anthropic.com` to check it against a blocklist. Hostname only, no path and no page contents, and it runs whichever provider you use. ## The copy on your own disk Worth knowing because it has nothing to do with Anthropic. Claude Code writes session transcripts to `~/.claude/projects/` in plaintext and keeps them for thirty days by default, so you can resume a session. Adjust it with `cleanupPeriodDays`. If a client's name went into a prompt three weeks ago, it is sitting on your laptop in a readable file right now. Backups pick it up. So does anyone with your unlocked machine. For a lot of people this is the larger exposure, and it is entirely yours to fix. ## When this is fine, and when it is not For most work it is fine, and saying otherwise would be dishonest. Thirty-day retention under commercial terms with no training is an ordinary processor arrangement, and it is the same shape as the CI system and the error tracker you already trust with the same code. It stops being fine at a specific boundary: when the data in the repository is not yours to place with a processor of your choosing. Client records in a fixture. Patient identifiers in a seed script. Employee data in a migration. Then the question is not whether Anthropic is trustworthy. It is whether your contract with the person that data belongs to permits a subprocessor you did not name, and a retention window you did not negotiate. No vendor setting answers that for you. The second boundary is deletion. Retention policies describe what a company intends to keep. They do not describe what a court can later require it to produce. That is not a hypothetical about AI vendors any more, and it is the reason "we do not train on it" and "nobody will ever read it" are different sentences. ## Sending less In rough order of how much they cost you: 1. Set `DISABLE_TELEMETRY=1`, `DISABLE_ERROR_REPORTING=1` and `DISABLE_FEEDBACK_COMMAND=1`, or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` for the group. Free, no change to how you work. 2. Turn the training setting off if you are on a consumer plan. Also drops retention from five years to thirty days. 3. Lower `cleanupPeriodDays` so the plaintext transcripts on your disk expire sooner. 4. Move to commercial terms, and ask your account team about zero data retention if you qualify. 5. Keep regulated data out of the repository. Correct, and rarely available: the fixture with real names in it usually exists because someone needed it to be realistic. 6. Mask at the read boundary, so the agent works on tokens instead of values. ## What we do about the last one That last item is what Velum is. The desktop app ships a set of Claude Code hooks and an MCP server. When the agent reads a file, the hook masks it before the model sees it: names, emails, national IDs, IBANs, cards and credentials become tokens like `⟦PERSON_1⟧`. When the agent writes back, the real values go in first, so the file on disk keeps its actual contents. The model never held the values, so what reaches the API does not contain them. Detection runs on your machine and no file content is uploaded to anyone, us included. The limits, stated plainly, because a privacy tool that oversells is worse than none: **A prompt you type yourself is not protected.** If you type a client's name into the prompt, it reaches the model provider before any tool call happens. True of every MCP server, ours included. There is an optional guard that catches it and puts a masked copy on your clipboard, and it is off by default, because it is the only part that interrupts you. **Outside Claude Code, masking is a tool the assistant chooses to call.** Other MCP clients get the same local engine, but they expose no interception point, so it is not unconditional there. **Filenames are not masked, only contents.** A path is something the agent has to be able to use again. **If masking fails, the content is withheld rather than passed through.** A mask that quietly falls back to sending the real thing is worse than no mask, because you would believe you were covered. [Get Velum for macOS](/desktop) *Seven-day trial, no key and no account. The Claude Code hooks are in Settings, AI coding tools.* --- # Why privacy-first architecture wins (2026-08-10) Source: https://velumprivacy.com/blog/privacy-first-architecture For a decade, software architecture optimised for scale, speed and acquisition. Privacy arrived later, usually in response to a regulator or a bad week in the press. That order of operations is expensive, and it shows in the results. ## The cost of retrofitting Adding privacy controls to a finished system produces contradictions. Data minimisation policies that fight the analytics pipeline. Encryption layers that break search. Consent flows bolted onto collection that was never questioned. The architecture was not designed for any of it, so every new feature pays a tax. The pattern repeats. Companies collect by default, store indefinitely, then discover that deletion requests are an engineering project. They train models on user data and then cannot answer basic questions about provenance. Hoarded data compounds like debt. ## Inverting the default A privacy-first architecture asks a different opening question. Not "what can we collect?" but "what is the least we need to make this work?" Not "where do we centralise this?" but "can this stay on the user's machine?" The engineering benefits are concrete: - **Reduced liability.** Data you never hold cannot be breached, subpoenaed or misused. - **Simpler compliance.** Obligations that are architectural become checklists rather than rebuilds. - **Better latency for sensitive work.** Local processing has no round trip. - **Trust you can demonstrate.** A claim that can be checked is worth more than one that must be believed. ## What the constraint did to Velum When we started Velum we set a rule that sounded like a handicap: no accounts, no cloud processing of your content, nothing sent off the device at runtime. It forced better engineering. We could not lean on a server-side model, so we had to make on-device detection genuinely good, which meant quantised models small enough to bundle and a pattern layer strong enough to stand alone. We could not personalise from behavioural data, so the interface had to work without knowing anything about you. We could not fall back on a support team reading your documents, so error states had to explain themselves. The result is a tool that works offline, starts instantly, and has a much smaller surface for anything to go wrong on. ## Being precise about "no telemetry" We are not going to claim we collect nothing, because that is not quite what happens, and a privacy company rounding in its own favour is exactly the failure mode we are arguing against. The desktop app writes a usage log to your own disk. It records that operations happened and how long they took, with no personal data in it. Nothing uploads it, we never see it, and you can delete it whenever you like. It exists so you can debug your own installation, and so a tester can send us something useful if they choose to. This site runs a self-hosted analytics tool that counts page views without cookies and without following you anywhere. That is disclosed in our [privacy policy](/privacy), and it is a different thing from the app, which sends nothing. ## The business case, without the invented statistic You have read the paragraph that quotes an average breach cost. We are leaving it out, because the number gets copied between blog posts until nobody can say what it measured or where it came from. The argument stands without it. If your staff are pasting client records into an AI tool today, that is a disclosure to a third party you have not assessed, and it is happening whether or not you have a policy about it. Reducing what leaves the building is a risk decision that does not require a headline figure to justify. See the principle in the product: [download Velum](/#downloads), or [read the terms](/licensing). --- # Velum vs Microsoft Presidio: a framework and a product are different answers (2026-08-09) Source: https://velumprivacy.com/blog/velum-vs-microsoft-presidio If you search for PII de-identification you will meet Microsoft Presidio quickly, and you should. It is the most established open-source project in this space: an MIT-licensed Python SDK that detects and anonymises personal data in text and images, maintained since 2018, with detection built from NER models, regex, checksums and pluggable custom recognisers. People sometimes ask how Velum compares to it. The honest answer is that they are different kinds of thing, and the comparison is worth walking through because it clarifies what you actually need. ## What Presidio is Presidio is a toolkit for engineers. You install it with pip, wire it into your own code or deploy it as a container, choose and tune the recognisers, and decide what happens to each entity type: mask it, hash it, replace it, encrypt it. It scales from a script to a PySpark job. If your organisation is building a data pipeline that must scrub millions of records, or a product that needs de-identification inside it, Presidio is a serious and proven foundation, and its price is zero. That flexibility is the point, and it is also the cost. Presidio does nothing until someone builds with it. There is no app, no extension, no interface for the person who just needs to paste a contract into a chatbot safely. The person operating it is a developer by definition. ## What Velum is Velum is a finished product for the person doing the pasting. The browser extension and desktop app are the interface: paste or open text, see the personal data masked, send it to whatever AI you use, and get the reply back with the real details restored. Nobody writes code, deploys a container, or tunes a recogniser. Detection ships with country packs for Spain, the US, UK, France, Germany, Turkey and Italy, and the measured accuracy per language is published on the [benchmarks page](/benchmarks). Both run locally. Presidio because you self-host it inside your own infrastructure, Velum because on-device is the design: the extension does its whole round trip with no network access at all. ## The reversibility difference One technical distinction matters beyond audience. Restoring masked data in the model's reply is central to how Velum works: both masking modes, tokenized and pseudonymized, are built to be undone locally, because a reply about `⟦PERSON_1⟧` is only useful once `⟦PERSON_1⟧` becomes the client again. Presidio treats reversal as one option among several. Its anonymizer's default operators, replace, mask, redact, are one-way; reversal exists through its encrypt operator, where a `DeanonymizerEngine` can decrypt entities if you kept the key. That is a reasonable design for pipelines, where destruction is often the goal. It means reversible round-trip chat use is something you build on Presidio rather than something it does. ## Which one you actually need Choose Presidio when you have an engineering team, a pipeline or product to build de-identification into, and the time to select models and tune recognisers for your data. It is free, open, and battle-tested, and for that job we would recommend it too. Choose Velum when the people handling sensitive text are lawyers, accountants, clinicians, researchers or anyone else whose job is not maintaining a Python service, and what they need is to use ChatGPT or Claude on real work today without the identifying details leaving the machine. There is no version of this article where one tool wins both jobs. If you are still unsure which side you are on, the test is one question: who will operate it? If the answer is "a developer", look at Presidio. If the answer is "me, this afternoon", the [extension is free to try](/extension) and needs no account. --- # PII redaction extensions for AI chat: the field, honestly surveyed (2026-08-09) Source: https://velumprivacy.com/blog/pii-redaction-extensions-for-ai-chat If you go looking for a browser extension that masks personal data before it reaches ChatGPT or Claude, you will find a small and young field. We should say immediately: Velum Lite is ours. This survey exists because the comparison pages that rank for these searches rarely disclose anything, and because every claim below is checkable against the tools' own listings and sites, which is exactly what we suggest you do. All facts were checked on 2026-08-09. ## What to compare on Four properties separate these tools more than any feature list. **Where the processing runs.** Every tool below claims local processing except where noted. The claim matters because a redaction service that receives your raw text has seen your raw text. The test is whether masking works with the network disconnected. **Whether masking is reversible.** One-way tools delete or block sensitive text before it is sent; the AI's reply then talks about placeholders or gaps. Two-way tools restore the original details in the reply, locally, which keeps the answer usable. **Whether the claim is auditable.** "100% local" is easy to write. It is verifiable when the source is readable or the network behaviour is observable, and a matter of trust otherwise. **What it costs and where it works.** Free tiers, supported browsers, supported chat sites. ## The field **Caviard** ([caviard.ai](https://www.caviard.ai)) masks in the page and restores in replies with a local reveal shortcut. Two-way, states that everything runs locally in the browser. Chrome only, and it supports ChatGPT and DeepSeek specifically. Source is not public, so the local claim rests on their word or your own traffic inspection. **PrivacyScrubber** ([privacyscrubber.com](https://www.privacyscrubber.com)) uses deterministic tokens with one-click local restore, and extends beyond chat with OCR on images, PDFs, and an MCP server for IDE assistants. Two-way. States that data never leaves your machine; source is not public. Free tier with character limits, paid from $15 a month. **Private Prompt** ([safeyourprompt.com](https://safeyourprompt.com)) replaces data with placeholders before sending and restores originals in the reply, on ChatGPT, Claude, Gemini, Grok and Perplexity, in Chrome and Firefox. Two-way, states 100% local processing; source is not public. Free tier of five anonymisations a day, paid from $9.99 a month. Notably strong on Polish identifiers. **Paste Redactor** (redactor.negativestarinnovators.com) is one-way: it inserts safe placeholders at paste time using an on-device model, across Chromium browsers, Firefox, and a Windows app. No restore. The detection model is openly published, the extension code is not. Their listing includes an honesty note that the detector will sometimes miss real PII and flag harmless text; more vendors should write that sentence. Free for 100 redactions a month, then $9 a year. **Redact** by Clearform Labs ([github.com/Clearform-Labs/Redact](https://github.com/Clearform-Labs/Redact)) takes a guard-rail approach: it warns or blocks before sensitive text is pasted into eight major chat sites, using a small on-device model, and makes no network calls. One-way by design, no restore. It is the one extension in this list whose source you can actually read, under a source-available licence. Free. **Velum Lite** ([ours](/extension)) is two-way with both masking styles: opaque tokens like `⟦PERSON_1⟧`, or format-valid stand-ins, restored locally in the reply either way. It works as a popup, so it is not limited to particular chat sites, and it runs in Chrome and Firefox with no network access at all, which you can verify by using it offline. Detection uses a regex floor plus an optional on-device NER model with country packs for seven countries, and the measured accuracy, including what slips through, is published on the [benchmarks page](/benchmarks). The core masking is free with no account; a licence adds the desktop app. Two adjacent things are worth knowing about even though they are not extensions: Microsoft Presidio, an open-source Python framework for teams building their own de-identification (we compared it to Velum [here](/blog/velum-vs-microsoft-presidio)), and OpenAI's privacy-filter, an openly licensed detection model that developers can run locally, detection only, no restore. ## Reading the field Three patterns stand out. First, reversibility splits the field cleanly: Caviard, PrivacyScrubber, Private Prompt and Velum restore; Paste Redactor and Redact are deliberate one-way guards. Which you want depends on whether you need the AI's answer to come back usable or need pasting policed. Second, nearly everyone says "100% local", but only a minority can be audited: Redact publishes its extension source, Paste Redactor its model, Velum its measured benchmarks and offline-testable behaviour. For the rest, the claim may well be true, and you cannot currently check it from the outside. Third, everything here is young and small, ourselves included; treat every tool, again ourselves included, as something to verify against your own material before you rely on it. The verification costs nothing: install one, cut your network, and see what still works. Then paste a real document from your work, the messy kind, and look at what was caught and what was not. Ten minutes of that is worth more than this or any other survey. --- # Cloud DLP APIs vs on-device masking: what the architecture decides for you (2026-08-09) Source: https://velumprivacy.com/blog/cloud-dlp-apis-vs-on-device-masking The big clouds both offer mature services for finding and masking personal data. Google Cloud Sensitive Data Protection, which most people still call Cloud DLP, inspects and de-identifies text through its API, priced per gigabyte processed. AWS Comprehend detects and redacts PII priced per hundred characters. These are not the dubious middlemen we wrote about in [the cloud scrubber piece](/blog/cloud-pii-scrubbers-risk); they are professional infrastructure with contracts, certifications and real engineering behind them. They are also, architecturally, the same shape: your unredacted text is sent to the provider's cloud, processed there, and returned. Everything that follows comes from that one fact. ## When a cloud DLP API is the right call Be fair to these services first. If your data already lives in that cloud, a DLP API adds no new party: text sitting in BigQuery that Google's DLP inspects was already on Google's infrastructure, under the same data processing agreement. For batch de-identification of large stores, for scanning your own warehouses for stray personal data, for pipelines that run where the data is, these services are built for the job and priced for it. Google's API even supports reversible tokenization, with the mapping handled server-side. The contractual position is real protection. It is also the operative word. ## What changes when the text was never theirs Now take the case this blog cares about: a person about to paste client or patient text into an AI assistant. Routing that text through a DLP API before it reaches the model means the raw, identifying text makes one extra network hop, to one extra processor, before the protection is applied. You have added a second company that handles the original, and your privacy analysis now covers both. That can be an acceptable, documented trade. But notice what kind of protection it is: a promise about conduct, backed by a contract. The provider processes your raw text and commits to handling it properly. On-device masking makes a different kind of promise, one about architecture: the raw text is not sent to anyone, because the masking already happened on the machine where the text lives. The first promise you audit; the second you can test, by cutting the network and watching the masking still work. There are practical differences too. A per-gigabyte or per-request API bill scales with usage and requires integration work, an account, credentials and quota. It is infrastructure, with infrastructure's overheads. A local tool has none of that surface: nothing to integrate, no request leaving, nothing metered per paste. ## The question that sorts every option Where does the raw text go before it is protected? Every de-identification product, ours included, should answer that in one sentence. For Google and AWS the answer is "to our cloud, under contract", and for data already resident there, that answer is fine. For text that starts on a person's machine and did not need to leave, "nowhere" is available, and it is the stronger answer precisely because it does not depend on anyone keeping a promise. Velum's answer is "nowhere": detection and masking run on the device, the reply is restored on the device, and the [benchmarks page](/benchmarks) publishes what the detection catches and what slips through, per language, so the quality of the local answer is measured rather than assumed. If your sensitive text starts on your machine, [start there too](/extension). --- # Introducing Velum: masking before the model, not after (2026-08-06) Source: https://velumprivacy.com/blog/introducing-velum Every time you paste a client record into ChatGPT or Claude, you make a trade. You get the answer, and you hand over data that was never yours to give away. Names, addresses, ID numbers, medical notes. Once it is sent, it is sent. We built Velum because that trade is avoidable. ## The problem is architectural Most privacy tooling in this space is a wrapper. It puts access controls or a scrubbing API in front of a system that was still designed to move your data somewhere else. You end up trusting a second vendor to protect you from the first. Velum does the work before anything is sent. It runs on your machine, finds the personal data in your text or your file, and replaces each value with a placeholder. The masked version is what reaches the model. When the reply comes back, Velum puts the real values in. That is the whole idea, and it is deliberately unglamorous. The model still gets a coherent prompt, because the structure of the sentence is untouched. You still get a usable answer, because the placeholders come back out. ## Reversible, not destructive Redaction tools blank things out. That protects the data and ruins the answer: you get back a draft full of holes to fill in by hand, so people stop using the tool and paste the raw version instead. Velum's placeholders are reversible. `⟦PERSON_1⟧` maps back to the real name, consistently, throughout the document. You can also choose pseudonymised masking, where the stand-in is fake but format-valid, which suits documents that have to keep looking like documents. ## What "local" means here, precisely The masking runs on your device and nothing you mask is sent anywhere. That claim is worth stating carefully, because vague versions of it are exactly what we are asking you to distrust in other tools: - Detection and masking happen on your machine. There is no vendor server in the path, and no account to create. - The desktop app does open a socket on `127.0.0.1`, because the interface talks to the local engine that does the work. It is bound to your machine and cannot be reached from the network. "No network calls at runtime" means nothing leaves the device, not that no socket exists. - The app writes a usage log to your own disk, with no personal data in it. Nothing uploads it. You can delete it. We would rather be this specific and be checked than round it up to something cleaner. ## What it does not do It does not make you compliant. GDPR cares about what you do with personal data, and masking before disclosure to a third party is a genuine and useful control, but it is one control among many. We have no HIPAA or BAA posture today. SOC 2 is in progress and not finished. If a vendor tells you their tool makes compliance automatic, check what they mean. It also does not catch everything. Detection is very good on structured identifiers and good on names and addresses, and it varies by language and document. Velum reduces exposure. It does not eliminate it. ## Where to start The macOS app and the browser extension both run for seven days with no account and no card. After that a licence key keeps masking on, and unmasking is never gated, so anything you have already masked stays readable either way. Try it on your own documents: [download Velum](/#downloads), or [see where it fits](/use-cases). --- # Can I paste client data into ChatGPT? (2026-08-05) Source: https://velumprivacy.com/blog/can-i-paste-client-data-into-chatgpt The short answer: if the information belongs to a client and you are signed in to a personal ChatGPT account, no. If your organisation is on a business tier with a signed data processing agreement, sometimes, for some categories, and you need to be able to say which. The rest of this is how to tell which case you are in, and what to do when the answer is no but the work still has to get done. ## "Does it train on my data" is the wrong first question It is the question everyone asks, because it is the one with a switch attached. As of August 2026, OpenAI states that it does not use business data from ChatGPT Enterprise, Business, Edu or the API to train its models, and that consumer accounts can be opted out through data controls. Those statements are real and they matter. They also answer a narrower question than the one you are actually asking. Turning training off changes what a future model learns. It does not change whether your text was stored, for how long, who inside the vendor can read it during that window, or what happens if a third party later obtains lawful access to the store. That last item stopped being hypothetical. In the copyright litigation against OpenAI in the Southern District of New York, a preservation order in May 2025 required the company to retain consumer ChatGPT output logs, including conversations users had deleted. The forward-looking part of that obligation was lifted on 26 September 2025, but data already preserved stayed preserved. Then a magistrate judge ordered production of a sample of user logs, and on 5 January 2026 the district judge [affirmed it](https://natlawreview.com/article/when-chats-become-evidence-court-affirms-order-requiring-openai-produce-20-million): twenty million de-identified conversations, prompts and model outputs, handed to opposing parties under a protective order. De-identified, sampled, and covered by court-ordered safeguards. Also: twenty million private conversations that their authors believed were between themselves and a chatbot. No vendor setting could have prevented that, because it was not the vendor's decision. This is the gap between "we will not train on it" and "nobody will ever read it". A company can promise the first. Nobody can promise the second about text that still exists somewhere. ## The four questions that actually decide it ### 1. Is the data yours to send at all? If the information was entrusted to you by a client, a patient, or a candidate, you are usually holding it under a duty of confidentiality that exists independently of data protection law. Legal privilege, medical confidentiality, the secrecy obligations that apply to accountants, auditors and tax advisers in most jurisdictions: these are owed to the person, not to a regulator. The important property of that duty is that disclosure itself is the breach. There is no incident to wait for and no harm threshold to cross. If you sent a client's contract to a third party without a basis for doing so, the exposure exists whether or not anything bad ever happens to the file. Data protection obligations sit on top of that, not instead of it. We covered where a prompt crosses the GDPR line in [a separate post](/blog/gdpr-ai-chatbots-line). ### 2. What does the account promise, in writing? Not the marketing page. The agreement your organisation actually signed. A personal account operating under consumer terms gives you no data processing agreement, no defined controller and processor relationship, no contractual retention commitment and no transfer safeguards you can point to. Business tiers change that, and the change is real: training off by default, administrator control over retention, contractual terms a compliance function can review. The failure mode is not choosing the wrong tier. It is a firm that bought a business tier and has staff still pasting into personal logins on the same laptops, which is the ordinary state of most organisations that have not checked. ### 3. What happens to the text after you get your answer? The default for API traffic is retention for up to thirty days for abuse monitoring, after which it is deleted unless a legal obligation requires otherwise. Zero data retention exists, applies only to eligible endpoints, and is granted on approval for qualifying enterprise agreements. It is not a checkbox on a normal account. So for most people, most of the time, the honest description is: the text sits with a third party for a period you did not choose, in a jurisdiction that may not be yours, and "delete" removes it from your view before it removes it from theirs. ### 4. Could you show, a year from now, what was sent? Accountability under Article 5(2) is a demonstration requirement. If your position is that staff exercised judgement, the follow-up question is which data reached which tool on which date. Chat interfaces produce no record you control. "We were careful" is a claim, not evidence. ## The ten second version | What you want to paste | Personal account | Business tier with DPA | After masking | | --- | --- | --- | --- | | Client contract naming real parties | No | Only with a lawful basis and a record of it | Yes | | CV or candidate notes | No | Only with a lawful basis and a record of it | Yes | | Patient notes, health details | No | Rarely, and not without a DPIA | Yes | | Customer support email thread | No | Usually, with a record | Yes | | Source file carrying credentials or customer rows | No | No | Yes, once the identifiers and secrets are out | | Internal draft with no people in it | Yes | Yes | Not needed | The right-hand column is the one worth noticing. It does not depend on the tier, the vendor, the jurisdiction or the year, because there is nothing in the text for any of those to apply to. ## Four beliefs that do not survive contact **"Training is off, so it is private."** Training is one use of your data among several. Storage, abuse monitoring, human review of flagged content and legal process are the others, and the training switch touches none of them. **"I deleted the chat."** Deletion starts a removal process on the vendor's side, subject to their stated window. A preservation obligation overrides it, as the 2025 order demonstrated for conversations users had already deleted. **"I took the name out, so it is anonymous."** A job title plus an employer plus a city identifies one person. So does a birth date plus a postcode. Removing the direct identifier while leaving the context is the most common way people convince themselves a prompt is safe. We wrote about [what actually counts as personal data in a prompt](/blog/what-is-personal-data-in-ai-prompt). **"IT approved ChatGPT."** Approving a tool is not the same as approving a data class for it. Most approvals were granted for general productivity use and were never scoped to client files, and staff reasonably read the approval as covering whatever they type. **"My client consented."** Consent to your engagement is not consent to transfer their file to a third-party processor abroad. If consent is your basis, it has to be consent to that, and you have to be able to produce it. ## The version that is always allowed Every question above exists because identifiable personal data leaves your control. Remove that premise and the questions do not need better answers, they stop applying. That is what masking before send does. Names, contact details, identifiers, account numbers and the sensitive details that slipped in for context get replaced before the text reaches the model. The model works on the structure of the problem, which is what made the answer good in the first place. The identities stay on your machine, and the reply comes back with the real values restored so the output is usable rather than full of gaps. The word doing the work is reversible. One-way redaction produces a draft somebody has to reassemble by hand, and people who have to do that twice go back to pasting the raw version. We compared the two masking styles, opaque tokens and format-valid stand-ins, [here](/blog/tokenized-vs-pseudonymized-masking). [Velum](/#downloads) does this locally. The browser extension makes no network calls at all. The desktop app makes five enumerated outbound requests, listed inside the app itself, and none of them carry your document text. If you want the version that becomes a written rule for staff, the [AI usage policy template](/ai-usage-policy-template) is free and has a data classification table you can adopt as it stands. ## Common questions ### Can lawyers use ChatGPT with client information? Not on a personal account. On a business tier with a data processing agreement, the professional conduct rules in your jurisdiction still govern disclosure of client confidences to a third party, and those rules sit outside data protection law entirely. The American Bar Association's [Formal Opinion 512](https://www.americanbar.org/news/abanews/aba-news-archives/2024/07/aba-issues-first-ethics-guidance-ai-tools/), issued 29 July 2024, reads Model Rule 1.6 as requiring a client's informed consent before information relating to the representation goes into a self-learning generative AI tool, and states that boilerplate consent buried in an engagement letter does not do the job. Bar and law society guidance elsewhere has landed in similar territory. Masking the client's identifying details before the prompt leaves is the route that does not depend on any of it. ### Is ChatGPT Enterprise GDPR compliant? A product cannot be compliant on your behalf. The tier gives you the contractual pieces compliance requires: a processing agreement, training off, retention controls, transfer terms. Your lawful basis, your minimisation, your records and your DPIA where one is needed remain yours to establish. ### Does turning off chat history stop the data being stored? No. It changes what appears in your sidebar and what feeds model improvement. Retention for safety and abuse purposes runs on its own schedule, and legal preservation obligations override both. ### Is it enough to remove names before pasting? Rarely. Direct identifiers are the easiest part to catch and the least likely to be the only thing identifying someone. Combinations of ordinary details do the identifying, which is why manual redaction under time pressure has a poor record. ### Can I paste client data if the client agreed? Only if what they agreed to was this. Consent has to be specific, informed and demonstrable, which means consent to the transfer of their information to a named third party for this purpose, not a general clause about using technology in your practice. ### What if I only need help with the shape of the problem? That is the usual case, and it is the whole argument. If the model does not need to know who the person is in order to do the task, the person has no reason to be in the prompt. If you want to see where this lands across legal, recruitment, healthcare, finance and support work, [see the use cases](/use-cases). --- # Velum 0.12.0: the right model for the file in front of it (2026-08-04) Source: https://velumprivacy.com/blog/velum-0-12-0-two-models Velum 0.12.0 is out. It adds a second detection model and, more usefully, stops pretending one model is right for everything. ## Maximum is a budget, not an engine Until now, picking Maximum picked a model. Now it picks a ceiling, and Velum chooses the engine from what it is actually looking at. Source files go to [OpenAI's Privacy Filter](https://huggingface.co/openai/privacy-filter). Everything else goes to the full span model Velum already used. The reason is a difference in how the two read. The older model re-runs itself with a prompt every thousand characters, so it slows down as a file grows. Privacy Filter reads the whole file in one pass. On a short fragment the older model is quicker. On a 5 KB source file, which is the size a coding agent actually opens, Privacy Filter is **3.4 times faster** and finds the same amount: both leak nothing on our source-code corpus. Documents stay on the older model, because there it is genuinely better. On prose it leaks 0.04% where Privacy Filter leaks 3.28%, mostly on Catalan and Spanish names. Neither model is better. They are better at different things, which is why the setting now routes instead of choosing. We wrote up the full comparison, including a result that reversed on us when we changed corpus, in [a separate post](/blog/openai-privacy-filter-benchmark). ## Dates of birth were about to leak Privacy Filter has no date-of-birth category. It reports birth dates as a generic private date, and Velum keeps generic dates by default, because masking every date in a contract destroys the document for no privacy gain. Put those two behaviours together and every date of birth walks straight through. The model finds 99.7% of them and the policy then waves them past. They now route to a type that is always masked. If you are wiring Privacy Filter into something yourself, this is the trap: the model is doing its job, the policy is doing its job, and the combination leaks. ## Form headings are no longer treated as names "T.C. Kimlik", "Vergi", "IBAN", "Póliza". The heading printed next to an identifier, not the identifier itself. These were being masked as if they were people's names. Fixing it improved the tier most people actually run: at the High setting, over-masking dropped from 1.04% to 0.31%, with no change to what leaks. Less of your document destroyed for the same protection. ## Also in 0.12.0 - Two detection models loading at the same time could each overwrite a shared path and then read back the other's directory, failing the mask on a cold start. Fixed. - Windows support landed in the codebase. It is not built or signed yet, so there is no Windows download, but the platform-specific work is done. - The benchmark page now publishes results from a corpus we did not write, alongside our own. The numbers are worse and the licence is permissive, so you can check them. ## What it costs The Maximum download is now about 2.9 GB across two models, up from 1.1 GB. The Privacy Filter half is optional: if that download fails, Maximum keeps using the older model for source files, which is what 0.11.0 did. High is unchanged, still bundled, still offline, still the default. Privacy Filter is a roughly 2 GB resident engine and has no business in the tier that has to stay light. ## Getting it 0.12.0 runs on macOS on Apple silicon. If you already have Velum it will offer the update on next launch. [Download Velum 0.12.0](https://downloads.velumprivacy.com/Velum_0.12.0_aarch64.dmg) --- # Our PII model comparison reversed when we changed the dataset (2026-08-04) Source: https://velumprivacy.com/blog/pii-benchmark-reversed-changing-dataset We build a tool that finds personal data in text and masks it before it reaches a model. In April, OpenAI released [Privacy Filter](https://huggingface.co/openai/privacy-filter), an open-weight model that does the detection half of that job. We already run [GLiNER](https://huggingface.co/onnx-community/gliner_multi_pii-v1) for the same purpose, so we measured one against the other. The first answer we got was clear and wrong. This is how it went wrong, because the mistake is easy to make and we came within about a day of publishing it. ## The setup Two token-level detectors, same harness, same machine, same metric. The metric matters, so: we score **surface leak**. Run the whole pipeline end to end, then ask whether each thing that should have been masked is still sitting in the output as a literal substring. Not span F1, not per-token accuracy. The reason is that our pipeline merges overlapping detections into one span, and span-level scoring undercounts that: when a merged span covers two adjacent expected spans it can only be credited with one, so the other reads as a miss even though the text is fully masked. Span scoring told us one configuration was leaking 2.9% on a corpus where nothing leaked at all. We tune on span F1 because it is more sensitive; we report surface leak because it is what a user could check. ## The first result Our own evaluation corpus is 1,800 examples across nine languages, generated by our own builder and validated by our own oracle. On it, our existing setup leaks 0.04% and swapping in Privacy Filter made things worse, 3.28%, concentrated in Catalan and Spanish person names. That is a home-field result and we knew it, so we needed a corpus we had not written. We picked the obvious one: **PII-Masking-300k**, the standard reference in this space. On that corpus the ordering flipped hard. Privacy Filter alone beat our existing setup by roughly three to one. Same code, same harness, same metric, opposite conclusion. We drafted that up. A model from a large lab, beating what we ship, on a neutral dataset. It is a good story and it was nearly a public one. ## Why it was wrong PII-Masking-300k is the corpus OpenAI reports Privacy Filter against. That is not an accusation of anything. Nobody outside OpenAI can say whether it is in the training data, and we are not claiming it is. The point is narrower and it does not require contamination: **a corpus that a model's authors selected as their reference is a corpus that model was steered toward**, through architecture choices, label taxonomy, threshold calibration and everything else that gets tuned while looking at a benchmark. It was Privacy Filter's home field in precisely the way our corpus is ours. We had swapped one biased corpus for another and called the second one neutral. So we picked a third: [Gretel's synthetic PII corpus](https://huggingface.co/datasets/gretelai/synthetic_pii_finance_multilingual). Nine hundred contracts and statements across six languages, averaging about 1.2k characters, chosen by neither party. On that corpus, Privacy Filter alone is **worse** than what we already ran: 26.6% against 23.5%. The three-to-one win did not survive the dataset change. Nothing else changed. ## The licence problem, which we should have hit first There is a second reason not to use PII-Masking-300k, and it is the one we should have checked before running anything. Its licence grants access "exclusively for academic research and non-commercial purposes," requires written permission for redistribution or derivative works, and states that no licence is available to companies without prior discussion. We are a commercial product. Benchmark figures derived from it, published on a company blog, are not ours to publish. That is why this post describes the reversal in prose and gives you exact numbers only from the Apache-2.0 corpus. It is an awkward shape for an article and it is the correct one. If you are evaluating PII models, check this before you build an argument on a dataset. The permissively licensed options we found usable were the Gretel corpus above and [beki/privy](https://huggingface.co/datasets/beki/privy) under MIT. ## What our own corpus was hiding The uncomfortable part is not what the third corpus said about Privacy Filter. It is what it said about our benchmark. On our corpus, every configuration we ship scores between 0.0% and 1.1% leak. That reads like a strong result. It is closer to a measurement failure: the corpus cannot distinguish our configurations from each other. On the Gretel corpus the same three score 51.2%, 23.5% and 15.1%. Both are real numbers. The first describes clean text in languages we have specifically tuned for, the second describes document formats nobody tuned for. But only one of them can tell you whether a change you just made was an improvement, and it is not the one we had been using alone. ## Two bugs that needed a second model to surface Running two detectors over the same corpora exposed problems one detector had been hiding. **A policy interaction that leaked every date of birth.** Privacy Filter has no date-of-birth category; it reports birth dates as a generic private date. Our policy keeps generic dates by default, because masking every date destroys a contract for no privacy gain. Compose those two correct behaviours and every date of birth passes through in plaintext. The model finds 99.7% of them and the policy waves them through. Neither component is wrong on its own. We only caught it because the new corpus labels dates of birth as a distinct type and ours does not. **Form headings masked as people.** "T.C. Kimlik", "Vergi", "IBAN", "Póliza": the label printed next to an identifier rather than the identifier. Twelve distinct surfaces accounted for 84% of one model's over-masking. Fixing it improved our existing shipped tier too, whose over-masking fell from 1.04% to 0.31% with no change in leak. That fix had been available the whole time and needed a second model to become visible. ## Where the two models actually differ They fail in different places, which is the only interesting result here. On source files both leak nothing on our code corpus, but Privacy Filter is **3.4 times faster** on real files: 562 ms against 1,919 ms at the median, on 47 files averaging 5 KB. The mechanism is chunking. GLiNER is a zero-shot span model: it takes a label list as a prompt and re-runs a forward pass per chunk. Privacy Filter uses banded attention with a 128-token band and reads the whole file in one pass. **The obvious objection is that we handicapped GLiNER with a small chunk size, and it is worth answering directly.** Our chunk is 1,000 characters. That is not a tuning oversight, it is the model's context window: GLiNER here has a 384-token limit, and 1,000 characters of multilingual text plus a roughly 40-token label prompt already sits close to it. Raising the chunk size truncates the input. The re-prompting cost is structural to how the model works, not a configuration we neglected. The ordering also reverses by file size. On 300-character fragments GLiNER is the faster of the two, 85 ms against 105 ms. Privacy Filter only wins once files are big enough for chunking overhead to dominate. Any latency number in this comparison is meaningless without the document size attached, which is a thing we would have gotten wrong if we had measured only one size. ## What we shipped Neither model replaced the other. Detection now routes by what is being read: source files to Privacy Filter, prose to GLiNER. Running both on everything has the lowest leak we measured and costs 4.4 GB resident, so it exists and is not the default. Numbers, methodology and the corpus build script are on our [benchmark page](/benchmarks). The Gretel corpus is Apache-2.0, so the figures in this post are reproducible without asking us for anything. ## Limitations One machine, Apple silicon, twelve cores, single run, no variance bands. Latency numbers in particular would benefit from repetition and we have not done it. The comparison is between two specific models at specific quantizations in one pipeline, with our policy layer and our regex tier underneath both. It is not a general claim about either model. And the finding that matters generalizes past all of that: **if you benchmark a model on the dataset its authors report it against, you have measured its home field.** Pick a third corpus. Read the licence first. --- # We benchmarked OpenAI's Privacy Filter. It changed our detector, and our benchmark. (2026-08-04) Source: https://velumprivacy.com/blog/openai-privacy-filter-benchmark In April, OpenAI released [Privacy Filter](https://huggingface.co/openai/privacy-filter): an open-weight model, Apache-2.0, that finds personal data in text. Velum is a product whose entire job is finding personal data in text. So the question was not academic. We spent a few days measuring it against what we already ship. It is now part of Velum 0.12.0, but not in the way we assumed going in, and the most useful thing we learned had nothing to do with OpenAI's model. ## What we thought would happen Privacy Filter is a 1.5 billion parameter model with about 50 million active at any moment, which makes it far cheaper to run than its size suggests. It reads a whole document in one pass. Our existing model, GLiNER, re-runs itself with a prompt every thousand characters. We expected a straight swap. Newer model, bigger lab, better numbers. ## What actually happened On our own evaluation corpus, swapping GLiNER for Privacy Filter made things **worse**. Residual leak went from 0.04% to 3.28%. The misses clustered in Catalan and Spanish person names, which is not a coincidence: those are the languages we have spent the most effort on, and our corpus is dense with them. Running both models together, however, beat either alone. Zero leak on our corpus, zero on source files, and a third off the leak on documents neither model had seen. The two models fail in different places. GLiNER degrades on unfamiliar document formats. Privacy Filter degrades on names in languages it saw less of. Neither is a subset of the other, which is exactly the condition under which running both is worth the cost. So Privacy Filter is an addition, not a replacement. That is the finding. ## The number that did not survive contact Here is the part worth reading if you skim the rest. Our first pass used [PII-Masking-300k](https://huggingface.co/datasets/ai4privacy/pii-masking-300k) as a neutral corpus. It is the obvious choice: it is the set OpenAI reports Privacy Filter against, and it is the standard reference in this space. On it, Privacy Filter alone beat GLiNER by roughly three to one. We nearly published that. Then we changed the corpus, and the result inverted. On documents neither party had a hand in, Privacy Filter alone is **worse** than GLiNER, 26.6% against 23.5%. PII-Masking-300k is what OpenAI benchmarks Privacy Filter against. Whether or not it is in the training data, it is the corpus the model was tuned toward. It was Privacy Filter's home field in exactly the way our corpus is ours. Measuring a model on its own reference set and reporting the result as neutral is a mistake we came within a day of making in public. There was a second problem with it, which we should have checked first: its licence permits academic and non-commercial use only, and forbids derivative works without written permission. We are a commercial product. It was never ours to publish numbers from. We replaced it with [Gretel's synthetic PII corpus](https://huggingface.co/datasets/gretelai/synthetic_pii_finance_multilingual), Apache-2.0, 900 contracts and statements across six languages. Permissive licence, real document lengths, and nobody in this comparison authored it. ## What that corpus told us about our own benchmark This is the uncomfortable part. On our corpus, every tier we ship scores between 0.0% and 1.1% residual leak. Read that as a marketing sheet and it says our worst configuration is nearly perfect. Read it as an engineer and it says the corpus cannot tell our configurations apart. On the corpus we did not write, the same three configurations score 51.2%, 23.5% and 15.1%. Both sets of numbers are real. The first describes clean text in languages we have tuned for. The second describes documents in formats we have never seen. Most people's documents are somewhere between, and we have no way to tell you where yours land. So the [benchmark page](/benchmarks) now publishes both, and it leads the honesty section with the worse one. The corpus is Apache-2.0 and the build script is in the repository, so you can reproduce the number rather than take it from us. We would rather publish a 23% you can check than a 0.04% you cannot. ## Two bugs that only a second model could surface Running two detectors turned up problems that one detector had been hiding. **Dates of birth were about to leak.** Privacy Filter has no date-of-birth category; it reports birth dates as a generic private date. Our policy keeps generic dates by default, because masking every date destroys documents for no privacy gain. Wire the two together naively and every date of birth passes through in plaintext. The model finds 99.7% of them and the policy then waves them through. We caught it because the new corpus labels dates of birth separately, which ours did not. **Form headings were being masked as people.** "T.C. Kimlik", "Vergi", "IBAN", "Póliza": the label printed next to an identifier, not the identifier. Three quarters of Privacy Filter's over-masking was this one category. Fixing it also improved the tier that ships today, whose over-masking dropped from 1.04% to 0.31% without changing what leaks. That fix was sitting there the whole time, waiting for a second model to make it visible. ## What shipped Velum 0.12.0 treats the Maximum setting as a budget rather than a single engine. Source files are read by Privacy Filter, everything else by GLiNER. On source files the two models are tied on leak, both at zero, but Privacy Filter is 3.4 times faster on real files. The reason is structural: GLiNER re-runs a forward pass with its label prompt every thousand characters, so it slows down as files grow, while Privacy Filter reads the file in one pass. On a 300-character fragment GLiNER is the quicker of the two. On a 5 KB source file, the kind a coding agent actually opens, it is not close. We are not running both models on every document. That configuration has the lowest leak we measured, and it costs 4.4 GB of memory. It is available, and it is not wired to a setting, because we do not think the trade is worth making on your behalf. ## If you take one thing Measure the model on a corpus its authors did not choose, and check the licence before you build an argument on it. We got both of those wrong in the first pass, and the only reason it did not ship is that changing the dataset changed the answer. --- # A 5-minute privacy check before pasting into any AI (2026-08-03) Source: https://velumprivacy.com/blog/privacy-check-before-pasting Most data leaks into AI tools are not dramatic. No hacker, no breach. Just a busy professional pasting a real email, a real contract, or a real support ticket into a chatbot to save ten minutes. The text helps you get an answer. It also travels to a server you do not own, where it may be stored, logged, or used to train a future model. You cannot un-paste. So the only reliable moment to protect someone is before you hit enter. Here is a check you can run in your head in under five minutes, every time, until it becomes a habit. ## Start with one assumption Assume the prompt could be stored forever. That single assumption does the heavy lifting. Once you treat every paste as permanent and potentially readable by strangers, the right behaviour gets obvious. You stop asking "is this tool safe enough" and start asking "what in this text would I regret leaving in a public place." The first question depends on a vendor's promises. The second depends only on you. ## The 60-second scan Before you paste anything, read the text once and look for the items below. If any of them are present, the text is not ready yet. - A name, including initials or a nickname that points to one person - An email address or a phone number - A national ID, passport, tax, or social security number - A home or work address, or anything narrowing down a location - Account numbers, case numbers, invoice numbers, or reference codes - Health details, financial details, or anything about a person's private life - Dates of birth, employment dates, or other dates tied to an individual - Anything that, combined with the rest, could identify a person or a client That last point is the one people miss. A job title on its own is harmless. A job title plus a company plus a city plus a project name can point to exactly one human being. Personal data is not only the obvious identifiers. It is any combination that narrows the field to a single person. When you scan, think about the pieces together, not just one at a time. ## If you find something, mask it first You usually do not need the real values for the AI to help you. The model can draft a reply, summarise a thread, or fix the tone of a paragraph just as well with placeholders in place. So replace the sensitive parts before you paste. A few quick ways to mask: Swap names for roles or labels. "Maria Gomez" becomes "the client." "Dr. Patel" becomes "the physician." Replace numbers with shapes, not real digits. An account number becomes "[ACCOUNT]." A case reference becomes "[CASE-REF]." Keep the structure if the format matters, drop the actual value. Cut details you do not need. If the city, the date, or the exact amount is not required for the task, remove it rather than mask it. The safest data is the data that is not there. Keep a small map for yourself. If you need the real values back in the output, note that "[CLIENT]" meant Maria, on paper or in a local file, not in the prompt. Then put the real names back into the AI's answer on your own machine. The goal is simple. The model gets enough context to be useful. It never gets enough to identify anyone. ## A worked example Here is a raw prompt many people would paste without thinking: "Draft a firm but polite reply to John Mercer (john.mercer@acme.test) about invoice 88421, which is 30 days overdue for 14,500 dollars." Run the scan. There is a name, an email, an invoice number, and a financial detail tied to a person. Now mask it: "Draft a firm but polite reply to [CLIENT] about [INVOICE], which is 30 days overdue for [AMOUNT]." Same draft comes back. The chatbot never learned who John is, what he owes, or how to reach him. You drop the real values into the finished reply yourself. ## Make it a habit, not a project You will not do this if it feels like a chore. So shrink it to a reflex. Three beats, every paste: Assume it is permanent. Scan for the list above. Mask anything that points to a person. Five minutes the first few times, under a minute once it sticks. The habit costs far less than a single disclosure of a client's data, and it keeps the decision in your hands instead of in a privacy policy you will never read. ## Or let the check run itself Doing this by hand works, but humans get tired, rushed, and distracted, which is exactly when the mistakes happen. A tool can run the same scan every time without skipping the day you are busy. That is what Velum does. It spots the names, emails, numbers, and other identifiers in your text and masks them for you, locally on your own device, before anything is sent to an AI. The raw text never leaves your machine, and the real values are restored only in the answer you get back. The check still happens. You just stop having to remember it. If you want a whole team running this check rather than one person, Annex D of the free [AI usage policy template](/ai-usage-policy-template) is a one-page version written to be circulated as it stands. See how [Velum](/#downloads) handles it, or [request a demo](/contact) and try the masking on your own text. --- # Auditability as proof: why a privacy tool must be readable (2026-07-31) Source: https://velumprivacy.com/blog/open-source-as-proof A privacy tool makes a claim. "Your data stays local." "Nothing leaves your machine." "We never see your prompts." These are good claims. They are also impossible to confirm when the software arrives as a sealed binary. You can read the marketing page, trust the logo, and install the thing, but you have taken the promise on faith. Faith is a strange basis for a security decision. The fix is not a better promise. It is the ability to check. ## A closed promise is just a promise When a vendor ships closed software, the gap between what it says and what it does is invisible to you. A binary that claims to run locally might still phone home on launch, batch your data overnight, or open a connection the first time you touch a feature you rarely use. You would not know. The behaviour lives inside code you are not allowed to read. This is not a claim that every closed tool is dishonest. Most are not. The problem is structural. You have no way to tell the honest ones from the rest, because the only evidence that would settle the question is the source, and the source is the one thing you cannot see. A promise you cannot test is not a security control. It is a brand asset. Security-minded buyers already know this in other contexts. You would not accept "trust us, the encryption is fine" from a vendor who refused to name the algorithm. Privacy behaviour deserves the same scrutiny. If the claim is "no network at runtime," the natural follow-up is "show me." ## What auditability actually buys you Readable source answers "show me" by default. The license matters, but the real value is the inspection it permits. A few concrete things you get: - **Independent review.** You do not have to read every line yourself. Anyone with the skill can, and in an active project, people do. A hidden network call is the kind of thing a contributor or a curious user notices and files. - **No silent network calls.** When the code is public, claims about what crosses the network become checkable against reality. You can search for the functions that open sockets, make HTTP requests, or resolve domains, and see exactly when they run. - **Reproducible behaviour.** Open code plus a clear build means you can confirm that the binary you run matches the source you read. Behaviour stops being a mystery and becomes something you can predict, test, and explain to your own security team. Auditability also changes the incentive for the vendor. When anyone can look, cutting a corner is a corner that someone will eventually see. The discipline of building in the open tends to produce software that is honest about what it does, because dishonesty has a much shorter shelf life. ## You do not have to read every line A common objection: most buyers are not developers, so what good is source code they cannot parse? Plenty of good, as it turns out. Auditability is a property the whole ecosystem benefits from, not only the people doing the audit. You can gauge a project's health with signals that need no coding: - An active community. Look at recent commits, the pace of releases, and whether maintainers respond to questions. A project that moves is a project that is being watched. - A public issue tracker. Open problems discussed in the open are a sign of a healthy process. A tracker with real bugs, real answers, and real fixes beats a flawless-looking page with nothing behind it. - A clear build. Documentation that lets a technical person compile the tool and get the same result tells you the "show me" path is real, not theater. - Tests that assert the privacy claim. The strongest projects encode their promises as checks. A test that fails if the app makes a network request turns "runs locally" from a sentence into something the codebase enforces on every change. You can also borrow trust. Hand the repository to a security consultant, an engineer on your team, or a community you already rely on. The point is that the verification can be done by someone, and that you get to choose who. ## Why Velum ships readable source Velum's engine is licensed under the PolyForm Noncommercial License. That is deliberately not the same as open source: PolyForm restricts commercial use, which fails the Open Source Definition, and we would rather name the licence accurately than borrow a word that sounds better. What it is meant to give you is the part that matters here: the ability to read the code and check the central claim, that it runs locally with no network calls at runtime, instead of taking it on faith. Personal and noncommercial use is free; commercial use needs a paid licence. One caveat we would rather write than have you discover. The packages are prepared for release to npm as `@velumprivacy/*` and are not on the registry yet, so today the source is not in fact there to read. Our [licensing page](/licensing) says the same thing in the same words. An article arguing that a privacy tool must be inspectable should be the last place to imply a repository exists before it does. We think that is the only honest way to ship a privacy tool. A product whose entire value is keeping your data in your hands has no business asking you to take that on trust. Readable source is not a giveaway or a marketing flourish for us. It is the proof that backs the promise, and it keeps us accountable to the same standard we ask of everyone else. A privacy tool earns trust by being inspectable. Everything else is a slogan. If you want to see what that looks like in practice, read about [Velum](/#downloads) or [request a demo](/contact) and bring your hardest questions. --- # Anonymisation, pseudonymisation, tokenization: which one you actually have (2026-07-31) Source: https://velumprivacy.com/blog/anonymisation-pseudonymisation-tokenization A vendor tells you their tool anonymises data before it reaches the model. A second says it tokenizes it. A third says it masks it. A fourth says it redacts it. The demos look identical: a name goes in, something that is not the name comes out. Only one of those four words describes a state where data protection law stops applying to you. The other three describe security measures applied to data that is still personal data, still in scope, and still your responsibility. If you are signing off on a tool, that distinction is the whole review. This is a plain guide to what each term means, written for the person who has to make the call. It is not legal advice, and the assessment always depends on your specific data and context. ## The only question that changes your obligations Strip away the vocabulary and there is one question underneath: can this data still be connected back to a living person by someone, using means reasonably likely to be used? If yes, it is personal data. Every obligation you had before still applies: lawful basis, transparency, retention limits, subject rights, breach notification. If no, it is anonymous information and the GDPR does not govern it. Everything below is a variation on how completely that link is broken, and on who is holding the piece that would restore it. ## Anonymisation Recital 26 of the GDPR sets the bar. The Regulation does not apply to anonymous information, meaning information that does not relate to an identified or identifiable person, or to personal data rendered anonymous in such a way that the person is no longer identifiable. "No longer identifiable" is doing heavy lifting there. The test is not whether you can identify someone, it is whether anyone can, using means reasonably likely to be used, accounting for available technology and other datasets they could combine with yours. The working framework, from the Article 29 Working Party's opinion on anonymisation techniques and carried forward by the EDPB, asks three things: - **Singling out.** Can you isolate one person's records in the set? - **Linkability.** Can you link two records that belong to the same person, in the same set or across sets? - **Inference.** Can you deduce a person's attribute from the other values with significant probability? Fail any of the three and you have not anonymised anything. This is why the bar is high in practice and why most "anonymised" claims collapse under a careful reading: a dataset with a rare job title and a postcode singles people out even with every name removed. The prize for clearing it is real. Anonymous data leaves scope entirely. The cost is that the process must be irreversible, which usually means throwing away utility you wanted to keep. ## Pseudonymisation This one is defined in the text, at Article 4(5): processing personal data so that it can no longer be attributed to a specific person without the use of additional information, where that additional information is kept separately and protected. Read the second half again. Pseudonymisation assumes the additional information still exists. Something, somewhere, can put the names back. That is the design. The consequence trips people up constantly: **pseudonymised data is still personal data.** It stays in scope. Recital 26 says so directly, treating data that could be attributed to a person through additional information as information about an identifiable person. So pseudonymisation is not an exit. It is a control. The Regulation treats it that way, naming it as an appropriate technical measure under Article 32 on security of processing, and as an example of data protection by design under Article 25. It reduces the harm if the data is exposed, and it narrows who can re-identify. It does not end your obligations. A vendor who says "we pseudonymise, so this is no longer personal data" has told you something incorrect about their own product, which is useful information about the vendor. ## Tokenization Tokenization is not a GDPR term at all. It comes from payments, where the problem was card numbers sitting in merchant systems, and it is the vocabulary of PCI DSS rather than of European data protection law. The mechanic: replace a sensitive value with a surrogate token that has no exploitable meaning, and keep the mapping from token back to value in a separately controlled store, often called a token vault. Held next to Article 4(5), tokenization is a specific implementation of pseudonymisation. The token is the pseudonym. The vault is the "additional information kept separately". Everything said above about pseudonymisation applies to it: still personal data, still in scope. Which makes the important question about any tokenization product a very concrete one. **Who holds the vault?** If the vendor holds it, the vendor can re-identify every record you sent, and that capability sits inside their trust boundary rather than yours. If you hold it, they cannot. Two products can both be described accurately as "tokenization" and land on opposite sides of that line. ## Redaction Redaction is one-way removal. The value is taken out and nothing is kept that restores it. Done properly, and only if the residual data survives the singling out, linkability and inference test, redaction can amount to anonymisation. Done as most people actually do it, it does not remove anything at all. A black rectangle drawn over a PDF is a graphic placed on top of the page. The text underneath is still in the file, still selectable, still recoverable by anyone who opens it in the right tool. We wrote about [what it takes to actually destroy it](/blog/velum-0-9-0-permanent-redaction). The other cost of real redaction is that you lose the answer. Send a model a contract where every party is a black bar and the reply comes back about black bars. That is the trade [one-way redaction forces on you](/blog/one-way-redaction-breaks-ai). ## Masking Masking is an umbrella word. On its own it tells you nothing, because it covers reversible and irreversible techniques alike. When a tool says it masks data, the only useful follow-up is: what happened to the mapping? Destroyed, and you are in redaction territory. Kept and held by you, and it is pseudonymisation under your control. Kept and held by the vendor, and it is pseudonymisation under theirs. ## Side by side | Term | Reversible | Still personal data | Defined in GDPR | |---|---|---|---| | Anonymisation | No | No, if the bar is genuinely met | Recital 26 | | Pseudonymisation | Yes, with the separate information | Yes | Article 4(5) | | Tokenization | Yes, via the vault | Yes | No, PCI vocabulary | | Redaction | No | Only if it clears the anonymisation bar | No | | Masking | Depends | Depends | No | ## Where masking a prompt sits Velum masks personal data on your machine before a prompt or file reaches a model, then restores it in the reply. By the definitions above that is pseudonymisation, and we will not call it anything else. The mapping exists, because reversing it is the point. Data you have masked is still personal data and you still carry every obligation attached to it. What changes is narrower than "anonymised" and more useful than it sounds: the AI provider never receives the personal data in the first place. There is no vault on our side because the mapping never leaves your machine, so there is no copy of your originals for us to lose, be compelled to hand over, or re-identify. The exposure you were worried about, a client name sitting in someone else's logs and possibly their training set, does not happen. The exposure you still have to manage, personal data on your own device under your own control, is the one you were already managing before AI entered the picture. That is a smaller claim than the market usually makes. It is also one you can verify, which is the trade we would rather have. ## What to ask a vendor Five questions that cut through the vocabulary: 1. Is the data still personal data after your tool processes it? A correct answer is yes for anything reversible. 2. Where does the mapping or vault live, and who can read it? 3. What leaves my machine or my network, exactly, and when? 4. If you claim anonymisation, how does the result hold up against singling out, linkability and inference? 5. Can I verify any of this myself, or am I taking your word for it? The answers will tell you which of the five words above the product has actually earned. Most of the time it is pseudonymisation, and that is fine. It stops being fine when it is sold as something else. This post is about which word applies to you in law. For the practical side, which masking mode to reach for on a given piece of text, see [tokenized vs pseudonymized masking](/blog/tokenized-vs-pseudonymized-masking). If you want to see what pseudonymisation before the model looks like in practice, [download Velum](/#downloads) or [see where it fits](/use-cases). --- # Velum Lite is on the Chrome Web Store, and the zip is gone (2026-07-30) Source: https://velumprivacy.com/blog/velum-lite-chrome-web-store Until today, installing Velum Lite meant downloading a 151 MB zip from our site, unpacking it into a folder you had to promise never to move, turning on developer mode in Chrome, and clicking Load unpacked. Then dismissing a warning about developer mode extensions every few restarts. We asked people who care about handling data carefully to do the one thing security teams tell them not to do. Velum Lite is now on the Chrome Web Store. One click, and Chrome keeps it updated on its own. ## We deleted the zip The obvious move is to add the store link and leave the zip up for anyone who prefers it. We took it down instead, from the website and from our download host, and removed the script that publishes it. A zip has no identity. Once a file is passed around, nothing in the browser checks who built it, and a copy with three lines changed installs exactly as smoothly as ours does. The only thing keeping that copy honest is that the person handing it to you has not touched it. That is not a security property, it is a hope. A store listing does not fix everything, but it does fix that. The package is signed, updates arrive through a route we control, and the name on the listing is one we can be held to. So there is now exactly one place to get Velum Lite, and anything else offering it is not ours. The tradeoff is real and worth naming: we gave a third party a switch. Google can pull the listing, and if it does, our users lose their update path. We would rather carry that risk than keep telling people to run unsigned code from a folder. ## What is actually in the package The 151 MB is almost entirely the detection model. It ships inside the extension, which is why the store package is large and why nothing downloads on first run. The first mask after install pauses for a moment while the model warms up, and then it is instant. Everything after that happens in your browser. The extension makes no network requests at runtime, and you do not have to take our word for it: 1. Right click inside the popup and choose Inspect. 2. Switch to the Network tab and set Chrome to Offline. 3. Mask something, then unmask it. The request count stays at zero. It also asks for no site access when you install it. The extension declares no host permissions at all, and the ones it can request are optional: Claude, ChatGPT and Gemini, for the in page Mask button, plus your own machine on localhost if you pair it with the desktop app. Leave the button off and it never asks for any of them. ## Free, with a line that has not moved Masking text in the popup is free. No key, no account, no clock running in the background. Paste, mask, copy, and use the result in whatever chat you were already in. A licence adds masking files you drop on the popup, and the in page button. Unmasking is never gated in either direction, so anything you have already masked can always be restored, licence or not. ## If you already had the unpacked build Remove it from `chrome://extensions` and install from the store. Two things to know. Your licence key does not carry over. An unpacked copy and a store copy are different extensions as far as Chrome is concerned, with separate storage, so paste your key into the popup settings once more. It is the same key, and it still works in the desktop app too. Your unmasking is unaffected, because the mapping between a placeholder and its real value lives in your browser session, not in the extension folder you are deleting. ## On the review itself It took three days from first submission to approval, which is quick for a new developer account shipping a 151 MB package. Two of those days went to rejections, both for keyword spam, both earned. Our listing described what the extension detects by listing things out: file formats in one place, cloud and developer services in another. Read as prose it is a specification. Read by a policy reviewer it is a wall of brand names in a store description, which is exactly the pattern the rule exists to catch. We rewrote both passages to describe categories instead of naming vendors, and the third submission went through. ## Getting it [Velum Lite on the Chrome Web Store](https://chromewebstore.google.com/detail/velum-lite/llmijeemnegmimdpkknbfkkccldjfapb) Works in Chrome, Edge and Brave. The desktop app for macOS is separate and still a direct download from us, because it is a signed and notarized app that Apple already checks. --- # What 'your data never leaves your machine' really means (2026-07-29) Source: https://velumprivacy.com/blog/data-never-leaves-your-machine Every privacy tool sounds the same. They are all private. They are all secure. They all care about your data. The words are free to use, so everyone uses them, and that is the problem. By the time you have read three product pages, the language has stopped meaning anything. You cannot tell the careful tools from the careless ones, because they describe themselves with the same vocabulary. So drop the words and look at the path your data actually takes. The path does not lie. It either includes other people or it does not. ## Encrypt is not the same as never see Start with the most common privacy claim: "we encrypt your data." It sounds final, but it answers a narrower question than you think. Encryption protects your data in transit and at rest, which means while it travels across the network and while it sits in storage. That is real protection against an outsider who intercepts the traffic or breaks into the database. What encryption does not tell you is who holds the keys. If the service can read your data to process it, then somewhere in the pipeline that data is decrypted, in plain readable form, on a machine the service controls. Encryption is the locked armored truck. It says nothing about who is allowed to open the back doors once the truck arrives. "We encrypt your data" is a statement about how your data is protected from third parties. It is not a statement that the service itself cannot see your data. Those are different promises, and the gap between them is exactly where confidential text gets read, logged, or used in ways you never agreed to. "Your data never leaves your machine" is the stronger claim because it removes the question entirely. If nothing crosses the network, there is no truck, no keys, and no one else in the path. There is no one to trust with the back doors, because there are no back doors. ## What local and offline actually mean Two plain words sit underneath that stronger claim, and both deserve clear definitions. Local means the work happens on your own device. When you run a local tool, your text is read, processed, and handled by software running on your computer. The result appears on the same machine. Your data was never sent anywhere to get the job done. Offline means the tool does not need a network connection to function. You could pull the cable, turn off the wifi, and the tool would still work, because it was never reaching out to a server in the first place. Offline is the proof that local is real. A tool that genuinely processes everything on your device has no reason to call home, so it keeps working when the network is gone. Put together, local and offline describe a tool with no one else in the path. Not because the company promises good behaviour, but because the architecture leaves no room for anyone else to participate. ## Proof beats promise Here is the shift that protects you: stop asking whether a tool is private and start asking how you would know. A claim you can check is worth more than a claim you have to believe, because belief depends on the vendor staying honest forever, and checking does not. This is where most marketing falls quiet, because most tools cannot be checked. Their processing happens on servers you cannot see, running code you cannot read, governed by policies that can change next quarter. You are asked to trust the chain. A tool that runs on your own machine, with code open to inspection, asks for nothing. You can confirm the behaviour yourself. That is the standard worth holding any privacy tool to. ## How to verify any privacy claim You do not need to be an engineer to test most of these. Work down the list and let the answers, not the adjectives, decide your trust. - Pull the network. Turn off wifi or unplug the cable and try the tool. If it still does the job, the work is genuinely happening on your device. If it stops, your data was going somewhere. - Watch the traffic. Network monitoring tools, including ones built into your operating system, can show you whether an app makes outbound connections while it runs. No calls means no data leaving. - Read the code, or check that someone could. Open source means the claim is open to inspection by anyone, not just taken on faith. Closed code asks you to trust a description of behaviour you cannot confirm. - Ask where the processing happens, on your device or on their server. If the raw text touches their server, the "never see" claim is gone, no matter how strong the encryption around it. - Ask what is logged or retained, by whom, and for how long. A clear, specific answer is a good sign. A vague one is the answer. ## Where Velum stands This is the standard we hold ourselves to. Velum runs locally and offline, with no network calls while it works. There is no Velum server that sees your raw text, because your text never reaches us. Pull the cable and Velum keeps working, which is the first test in this list and the one we would run first ourselves. The engine is licensed under PolyForm Noncommercial so the claim is meant to be something you can read rather than something we ask you to believe, and we will say plainly that the packages are not on npm yet. We would rather show you the path than describe it. See how [Velum](/#downloads) handles your data on your own machine, and read through [the use cases](/use-cases) to find where it fits your work. --- # A grep for fetch() is not proof your app is offline (2026-07-28) Source: https://velumprivacy.com/blog/grep-fetch-is-not-proof Every tool in this category makes the same claim. Runs locally. Nothing leaves your machine. Fully offline. The words cost nothing to write, which is why everyone writes them, and why none of them should move you. We make the same claim about Velum, so this post is about what would have to be true for you to believe it, including the parts where our own evidence is not good enough. Start with the honest version of the claim, because it is not "zero network calls." ## Velum makes five network calls None of them carry document text. All five are worth naming, because a claim of zero that turns out to be five is worse than a claim of five. Two of them carry an identifier of some kind, and those two are exactly the ones a post like this would be tempted to leave out. **1. An update check on launch.** The Tauri updater fetches a manifest from `downloads.velumprivacy.com`. It sends no document content. It does tell our CDN that some IP launched the app. **2. A one-time detection model download**, which you start deliberately and can decline. The regex tier works without it. This is an inbound transfer: the model comes to you, nothing about you goes out beyond the request itself. **3. A signed license revocation list**, also from `downloads.velumprivacy.com`. This one deserves its own section, further down, because "how do you revoke a license without phoning home" turned out to be the most interesting constraint in the whole product. **4. One activation report**, sent at the moment you enter a license key. It carries the license id and a one-way hash of this install's random id. No email, no key, no hardware identifier. It goes once and is never repeated, including on later launches. **5. One trial registration**, sent once on first run. It carries a one-way salted hash of this machine's platform UUID and nothing else, not the UUID itself. It is what stops the trial being restarted by deleting a local file, which makes it the one request in this list derived from your hardware rather than from a random per-install value. It stops entirely once a purchased key is in place. Four and five are the ones that would embarrass me to omit, so they are named here, on the /desktop page, and in the protection receipt the app exports. If you find the app making a request I have not listed, that is the bug report I most want to receive. What has no network call on it is the masking path. Text goes in, entities are detected, tokens go out, the mapping is written to local disk. That is the claim, and everything below is about whether you should believe it. ## What we do internally, and why it is not proof We run two guards in CI. I am going to describe them and then take them apart, because I would rather do that here than in a comment section. ### The static scan `scan-runtime.mjs` walks every authored source file under `packages/*/src` and fails the build on a set of forbidden patterns: ```js const FORBIDDEN = [ /\bnew\s+XMLHttpRequest\b/, /\bnew\s+WebSocket\b/, /\bnavigator\.sendBeacon\b/, /allowRemoteModels\s*[:=]\s*true/, /allowLocalModels\s*[:=]\s*false/, /\bfetch\s*\(/, ]; ``` The last two entries are the transformers.js and onnxruntime knobs that would let the model layer reach for a remote weight file. The narrow allowlist is build-time scripts and benchmarks, which never get bundled. Now the problems, in ascending order of seriousness. It does not scan `node_modules`. The walk skips it explicitly. So it says nothing at all about what a transitive dependency does. It is checking our discipline, not our supply chain. It is a regex over source text, so it is defeated by anything that does not spell the call literally. `globalThis["fet" + "ch"]`, a dynamic `import()`, the `Function` constructor, a property lookup off a table. None of that is exotic; it is what any obfuscated exfiltration would look like anyway. And most importantly, **it only reads JavaScript and TypeScript**. Velum's desktop app is a Tauri shell, which means there is Rust in the process. There is a Node sidecar. There is a native ONNX runtime and a WASM build of the same. A `reqwest` call in the Rust half would not trip a single one of those patterns, because the scanner never looks at a `.rs` file. The static scan is a lint rule that stops us from regressing. Calling it proof would be a category error. ### The runtime test `no_network.test.ts` replaces `fetch` and `XMLHttpRequest` with functions that log and throw, then runs a full anonymize pass over a string with an email, an IBAN and a national ID in it, and asserts nothing was called. This is better, because it observes behaviour rather than spelling. It is still not proof, for reasons our own comment in the file admits: > Node-only network APIs (`node:http`, `node:https`) are ESM bindings and cannot > be monkey-patched in place; the static scanner catches those. Read that together with the previous section and you can see the shape of the hole. The runtime test cannot see `node:http`, and the static scanner that is supposed to cover for it cannot see Rust. Neither one covers the sockets a native module opens on its own. It also runs in a test process against source modules, not against the signed binary you downloaded. Even if it were airtight, it would be airtight about something other than the artifact in your Applications folder. So: two mechanisms that keep us honest with ourselves, and neither of which you have any reason to accept as evidence. ## What you can actually check, from outside The useful checks are the ones that do not require you to read or trust any of our code, because they observe the process rather than the repository. All of these run against the binary you already have. **Watch the sockets.** ``` lsof -i -P | grep -i velum ``` While masking, you should see the loopback listener and nothing else. The embedded service binds `127.0.0.1` only. If you see a socket to anything that is not localhost during a mask operation, the claim in this post is false and I want to hear about it. **Take the network away.** Pull the cable, or turn off wifi, and mask a document. The whole point of the design is that this changes nothing. The desktop app has a self-test button that runs a masking round trip against a built-in sample so you can watch it work with the interface down. **Watch the browser extension directly.** Load the popup, right click, Inspect, open the Network tab, then set Chrome's throttling to Offline. Paste something with personal data in it and mask. Zero requests, or the claim is false. Paste a token-laced reply back and unmask. Still zero. **Put it in a box.** The strongest version, and the one I would run if I were you: launch the whole app inside a network namespace with no route out, or behind a default-deny firewall, and use it normally for a day. Little Snitch on macOS does this interactively and will show you every connection attempt, including ones we did not tell you about. That last part is the point. It is the only check in this list whose result does not depend on our good faith. If you run that last one you will see the five calls named at the top of this post, at the times described. Most sessions will show fewer, because two of the five happen once in the life of an install. If you see a sixth, I have a problem. ## The revocation list, or: how do you revoke a license without phoning home This is the constraint I found most interesting to build against. Velum's licenses are offline. A key is an Ed25519-signed payload with an expiry, verified locally against a public key embedded in the app. A license server hears from you exactly once, in the activation report at the moment you paste the key in, and never again: not on launch, not on renewal, not while you work. That is the whole reason the offline claim holds for paying customers and not just trial users. That design has an obvious hole: a key that leaks cannot be taken back. The normal fix is an online activation check, which would mean the app phoning home with a license identifier every launch, which would destroy the thing we are selling. What we do instead: - The revocation list is a **static file** on the same host the updater already contacts, so it adds no new destination. - It is requested with **no identifier**. No license id, no install id, no query string. The client downloads the entire list and matches locally. The server cannot learn which license is checking, only that somebody downloaded a file. - It **fails open**. No network, no cache, malformed file, bad signature: the app behaves exactly as it would have anyway. A revocation mechanism that could lock out an offline paying customer during a flight would cost more than the leak it prevents. - The list is signed with a **control key that is deliberately not the license signing key**, and which exists only offline. Someone who steals the issuance key can mint licenses but cannot forge a list that un-revokes them. - Each list carries a monotonic sequence number, and a fetched list with a lower number than the cached one is discarded, so a network attacker cannot serve an old list to resurrect a revoked key. The tradeoff is real and I will state it: revocation is best-effort. Someone who blocks that one URL never receives the list. We decided that a revocation you can evade is better than an activation check you cannot, given what we are claiming about the rest of the product. ## Where this runs out Three things I cannot prove to you in a blog post. **Native code.** The ONNX runtime is a compiled dependency. I can tell you it loads weights from a local path with remote fetching disabled, and there is a test asserting that a missing model directory produces a filesystem error rather than a network call. I cannot personally audit every line of the runtime, and neither can you, and the socket-level checks above are the only real answer to that. **The build.** The binary you downloaded was produced by our CI from our source. Reproducible builds would close that gap. We do not have them. **Intent.** Every check in this post is a check on one version at one moment. A vendor who wanted to defect could ship a clean build, earn the benchmark, and change it in a point release. This is not solvable by promises, including mine. It is solvable by you running the firewall check occasionally, which is the actual reason I would rather hand you `lsof` than a trust badge. The honest summary is that our internal guards are a regression suite, and the only evidence that should move you is the evidence you produce yourself on the machine in front of you. That is a slightly awkward thing for a vendor to write down, but it is the argument, and a privacy tool that asks you to take its word for it has already lost the plot. --- Velum is a local PII masker for text and files. The detection engine is licensed under PolyForm Noncommercial 1.0.0, which is source-available rather than open source, and the packages are not published anywhere yet, so the source cannot currently be read. The desktop app and browser extension are proprietary and paid. It runs on macOS on Apple Silicon and on Linux, as an AppImage built for Ubuntu 24.04 and later. The extension installs from the Chrome Web Store and from Firefox Add-ons. Windows is not shipped and has no date. [velumprivacy.com](https://velumprivacy.com) --- # Writing an AI usage policy: the clauses most drafts miss (2026-07-27) Source: https://velumprivacy.com/blog/writing-an-ai-usage-policy Most organisations write their AI usage policy in a hurry. Someone discovers that a team has been pasting client files into a public chatbot for months, the question goes to the DPO or the head of information security, and a policy is expected by Friday. What comes out of that week is usually one of two documents. The first is three lines long, says staff must use AI responsibly, and cannot be enforced against anything. The second is forty pages of borrowed boilerplate that nobody reads past the contents page. Neither changes what happens the next time someone has a contract to summarise and ten minutes to do it. A usable AI usage policy sits between the two. It is short enough to be read, specific enough to be applied, and it regulates the right thing. Here are the clauses that first drafts leave out, and why each one matters more than it looks. ## 1. The AI features already inside software you license Almost every policy scopes itself to AI tools, meaning the assistants people go and sign up for. That misses the larger surface. Summarisation, drafting, transcription, and classification features are now built into products your organisation already pays for: the office suite, the helpdesk, the CRM, the meeting recorder, the code host. Nobody made a decision to adopt an AI tool. A vendor shipped a feature and it was on by default. Scope the policy to the behaviour, not the product category. Any tool that sends text, files, images, audio, or code to a system that generates or analyses content is in scope, whether or not it is called an AI tool and whether or not anyone chose it. ## 2. Personal accounts on approved tools Approving a tool and approving an account are different decisions, and policies routinely make only the first. If a person uses their own login on an approved product, the work sits outside your contract, outside your negotiated retention and training terms, outside your ability to retrieve or delete anything, and outside any audit you might later need to run. The tool is on your approved list. The usage is not covered by anything on your approved list. Say it explicitly: use the account the organisation provides. ## 3. A rule about data, not a list of tools A list of banned tools is out of date the month you publish it. A rule about data is not. The operative clause of a good policy is a table: which classification of data may go into which category of tool. Public, internal, confidential, restricted, mapped against public AI tools and approved ones. New product appears, staff can work out where it lands without a memo. Reuse the classification scheme you already have rather than inventing a second one for AI. Two schemes means neither gets used. The one-line version, the one people will actually remember: if the tool does not need to know who the person is in order to do the task, the person's identity does not belong in the prompt. ## 4. Client contracts that predate all of this Where you hold data belonging to a client, your contract with them governs what you may do with it. That contract was almost certainly signed before anyone considered whether a chatbot counts as a subprocessor. Before third-party data goes into any AI tool, someone has to confirm that the contract permits disclosure to subprocessors, that any notification or approval requirement has been met, and that the client has not issued a specific instruction about AI. Some clients have. Very few organisations have checked. ## 5. Who is accountable for the output Policies spend all their attention on the input and almost none on what comes back. The rule is that a person is accountable for every output used in the organisation's work, and the tool is not. In practice that means verifying every factual claim, figure, and citation against a source before the output goes to a client, a court, or a filing. Fabricated citations that look entirely plausible are a known and recurring failure, and they have already cost people professionally. Add the harder line too: for decisions that materially affect a person, employment, credit, benefits, admission, discipline, or care, a qualified human makes the decision. AI output may inform it. In several jurisdictions that is not a preference, it is a requirement, and the requirements are moving quickly. ## 6. An incident clause people will actually use Every AI policy has a reporting requirement. Most of them produce silence. If reporting an incident reads like a confession, people work out that the safest option is to delete the conversation and say nothing. You then have a disclosure you never learn about, cannot assess, and cannot notify. Two sentences fix it. Reporting in good faith will not result in disciplinary action. Concealing an incident may. Add the instruction not to delete the conversation before reporting, because the record is what the assessment needs. ## 7. Monitoring, stated honestly If you monitor AI tool usage on managed devices, say so, under your existing monitoring policy. If you do not, say that instead. This is one of the three points in an AI policy where local law genuinely changes the answer. Workplace monitoring rules and consultation requirements vary a great deal, and works council obligations in particular are not something to discover after the fact. The other two are automated decision-making and international transfers. ## 8. The clause that turns the rule into a control The weakest control in any information security programme is asking a person to make a judgement call, correctly, every time, while busy. A policy that stops at instruction has to be followed perfectly to work. Where you can, prefer a control that makes the prohibited version difficult rather than merely forbidden: strip the regulated content out of the text before it can leave, provide approved tools good enough that workarounds are not tempting, and make the approved path the fast one. Then write down what you actually have. If the honest answer is that you have no technical control yet, write that, rather than describing an intention as though it were a control. A policy that overstates its own enforcement is worse than one that admits a gap, because the gap is what an auditor finds. ## The mistake underneath all of this The instinct after discovering unsanctioned AI use is to block it. It is a reasonable instinct and it rarely works. Blocking the domain moves the activity to a phone, and a phone is a device you cannot see. The organisations with the worst exposure are not the permissive ones. They are the ones that issued a ban, believed it, and stopped looking. The alternative is not looser rules. It is a different control point. Instead of asking every person to judge, prompt by prompt, whether what they are about to paste is safe, you remove the regulated content from the text before it can leave. What reaches the provider carries no names, no identifiers, and no client details. The work still gets done, because the model does not need to know who the person is to summarise a case, redraft a clause, or explain a record. The exposure does not happen, because there was nothing regulated in the prompt to expose. That is also what changes your position afterwards. A policy tells a regulator what you asked people to do. A control tells them what was possible. ## A template you can start from Rather than describe a policy, we published one. The [AI usage policy template](/ai-usage-policy-template) is a complete document covering all of the above: seventeen clauses, an approved tool register, the data classification table, a data protection section, an incident procedure, and a one-page card written to be circulated to staff on its own. It is free, it has no form and no email capture, and it downloads as Word, PDF, or Markdown so it can go straight into your approval process under your own name. It is a template rather than legal advice, and the three clauses where local law decides the answer are marked as such. [Read the AI usage policy template](/ai-usage-policy-template) *Free, ungated, and yours to adapt.* If the clause you cannot currently fill in is the one about controls, that is the gap [Velum](/#downloads) exists to close. It masks personal and sensitive data in prompts and files before they reach any AI tool, entirely on the user's own machine, with no network calls at runtime, and restores the real values in the reply so the answer is still usable. There is no server in the path, so adopting it does not add another provider to the subprocessor list you just finished reviewing. --- # Velum 0.11.0: your coding agent reads masked files (2026-07-27) Source: https://velumprivacy.com/blog/velum-0-11-0-coding-agents Most people are careful about what they paste into a chat window. Almost nobody is careful about what their coding agent reads, because they never see it happen. You ask for a small refactor. The agent reads six files to understand the code. One of them is a test fixture with real customer names in it, because that is how the fixture was made. Another has a client's tax ID in a seed script. A third has an address in a comment from two years ago. All of it goes into the context, and the context goes to the model provider. Nobody pasted anything. Velum 0.11.0 closes that. ## What it does Velum runs as a Model Context Protocol server, so it works with any MCP-capable agent or harness. **It works best in Claude Code**, which exposes hooks, and hooks are what make masking unconditional rather than something the assistant has to remember to do. In Claude Code, this is the whole flow: - The agent reads a file. Velum masks it **before the model sees it**. Names, emails, national IDs, IBANs, cards and credentials become tokens like `⟦PERSON_1⟧`. - The agent works on the masked text and asks to write. Velum puts the **real values back** first, so the file on disk keeps its actual contents. - Command output and search results go through the same path. There is no side door where `cat customers.csv` produces something a `Read` would have masked. You do not change how you work. The agent does not know it is happening. ![The AI coding tools panel in Velum Settings](/blog/velum-0-11-0-settings.webp) *Settings, AI coding tools. The model gets no restore tool unless you give it one, and the prompt guard is off because it is the only part that interrupts. Install writes the plugin into Claude Code directly: no marketplace, no account, nothing to download.* ## The part people get wrong An edit is the interesting case. The model saw `⟦EMAIL_1⟧`, so that is what it writes into its edit, on both sides of the change. If only the new text were restored, the edit would fail to match the file, every time. So the old text is restored too, and the edit lands against the real file exactly as the model intended it. That is the difference between a demo and something you can leave switched on. ## What it costs, stated plainly **A typed prompt is not protected.** If you type a client's name into the prompt yourself, it reaches the model provider before any tool call happens. That is true of every MCP server, ours included, and no amount of engineering on our side changes it. There is an optional guard that stops a prompt containing personal data and puts a masked copy on your clipboard, but it is off by default: it is the only part of this that interrupts you, and a tool you fight is a tool you turn off. **Outside Claude Code, masking is a tool the assistant calls.** Codex, Claude Desktop and other MCP clients get the same local engine, but they provide no interception point, so the assistant chooses when to use it. **Filenames are not masked, only contents.** A path is something the agent has to be able to use again. ## Making it fast enough to leave on Detection is the expensive part. Our neural tier runs at about 6,000 characters per second, which means a 93 KB source file would stall the agent for fifteen seconds on a single read. Running the fast pattern-only tier instead is not a fix either: on our benchmark it misses 37% of the values that must not leak, because patterns cannot find a person's name. So the model tier now looks only where prose actually lives in code: inside string literals and comments, and only on lines that could plausibly carry a name. That same 93 KB file now takes 0.19 seconds. Detection quality did not drop. On our code benchmark it improved, because a name near a chunk boundary in a wall of syntax was getting lost, and it no longer is. ## Defaults that assume the worst **The model gets no way to unmask.** Not a discouraged tool, not a warning in a description. The tool is not registered, so it cannot be called. Restoring to a file or to your clipboard, and handing real values back to the model, are separate settings you turn on deliberately. **Some files are withheld entirely.** `.env`, private keys, certificates. Not masked, not shown. The agent is told the file was withheld and why. **If masking fails, the content is withheld.** A sidecar that is not running, a detector error, a file too large to mask inline: in each case the agent gets a notice instead of the content. A mask that quietly falls back to sending the real thing is worse than no mask at all, because you would believe you were covered. ## Getting it 0.11.0 runs on macOS on Apple silicon. If you already have Velum it will offer the update next time you open it. Then go to Settings, AI coding tools, turn it on, and press Install for Claude Code. [Download Velum 0.11.0](https://downloads.velumprivacy.com/Velum_0.11.0_aarch64.dmg) *Direct download, 336 MB. Signed and notarized by Apple, so it opens without a Gatekeeper warning.* Everything above happens on your machine. No file, no command output and no identifier is uploaded to anyone, including us. --- # The model that wins our PII benchmark loses on messy text (2026-07-27) Source: https://velumprivacy.com/blog/pii-benchmark-clean-vs-messy-text Every PII detection tool quotes one accuracy number. Ours is 99.8% F1 and a 0.07% residual leak. It is a measured number rather than a marketing one, taken by a fixed harness on a fixed data set on a named machine. It is also the most flattering true number we have, and a buyer who takes it at face value has learned very little about what happens to their contracts. So this post is the rest of it: what the number measures, where it stops holding, and the case where the tier that wins our headline benchmark comes second on text that looks like real documents. ## What the headline number measures The gold set is 1,800 labelled spans, 200 per language across nine: Spanish, Catalan, English, German, French, Italian, Turkish, UK English, US English. It is generated by a seeded PRNG and checked into version control, so it is byte-identical on every machine that rebuilds it and a run last month is comparable to a run today. Two details matter more than the size. **The identifiers are not minted through our own detector.** Every DNI, NIE, CIF, SSN, NINO, NIR, Steuer-IdNr, TC Kimlik, Codice Fiscale, IBAN and card in the set is generated directly from its published checksum algorithm. An earlier generator brute-forced candidate IDs until Velum's own regex accepted them, which guarantees 100% recall by construction and makes that half of the benchmark a tautology. A separate oracle pass then checks that the regex packs do recognise every committed value, as a cross-check rather than a definition. **Leak is the privacy number, not F1.** Residual leak is the fraction of must-mask gold spans a chain missed. Raw recall on our tables looks low because it counts `organization` and `location` spans that the shipped policy deliberately keeps, since masking every company name and city would make a legal document unreadable and neither is must-mask the way a person or a national ID is. Here is what the three shipped tiers do on that set, 9-language averages: | Tier | Chain | Leak | Over-mask | Must-mask F1 | p50 | RSS | | --- | --- | ---: | ---: | ---: | ---: | ---: | | Standard | regex only | 37.03% | 12.46% | 73.1% | ~0 ms | ~118 MB | | High (default) | regex + 170 MB on-device NER | 1.04% | 1.04% | 99.0% | ~7 ms | ~850 MB | | Maximum | regex + 1.1 GB GLiNER | 0.07% | 0.23% | 99.8% | ~26 ms | ~3,041 MB | That last row is the number on our /benchmarks page. It says that on clean, templated text, the big model closes almost all of the remaining gap. ## The same tiers on messy text Synthetic data is shaped like its generator, however careful the generator is. So there is a second set: ten deliberately messy documents the generator never saw, with the noise real legal and scanned documents carry. ALL-CAPS holder lines, OCR character swaps sitting next to clean values, names broken across a line wrap, dense multi-entity paragraphs, punctuation that ran together. The ranking changes: | Chain | Leak | Over-mask | Must-mask F1 | | --- | ---: | ---: | ---: | | regex | 16.7% | 20.0% | 81.6% | | regex + on-device NER (High) | 4.2% | 11.5% | 92.0% | | regex + GLiNER (Maximum) | 8.3% | 12.0% | 89.8% | Three things worth reading off that table. Leak is 4 to 8%, not 0.07%. On messy text, several points of sensitive material get through at every tier. That is a different product conversation than the one the headline number starts. The cheaper chain wins. The 170 MB quantized model, running in about 7 ms and 850 MB of RSS, comes out ahead of the 1.1 GB one that needs 26 ms and roughly 3 GB resident. And the regex floor alone, with no model at all, scores 81.6% here against 73.1% on the clean set. It goes up. The messy set is dense with the structured identifiers regex owns exactly, and thin on the paragraph-scale context the models exist to read. **The honest caveat, stated as loudly as the result:** n = 10. One missed span moves leak by about 4 points. This is not a tier ranking and we do not present it as one. It is a check on whether the synthetic numbers are an upper bound, and it says they are. ## Why the tiers fail in the ways they do Each detector alone, on the clean gold, is a bad privacy control: | Detector alone | Leak | Over-mask | Must-mask F1 | | --- | ---: | ---: | ---: | | regex | 37.03% | 12.46% | 73.1% | | on-device NER (170 MB) | 51.60% | 33.91% | 58.3% | | GLiNER (1.1 GB) | 27.16% | 0.22% | 84.1% | The regex floor is exact where it fires and blind where it does not. Every national ID, IBAN, card, email, phone, IP and cloud token scores 100% precision and 100% recall, because a checksum either validates or it does not. It cannot see that "Reunidos D. Andrés Castro y la perito Ana Ruiz" contains two people, because nothing about those characters is structurally distinct from any other words. The span model has the opposite shape. It reads people and places well and leaks 27% on its own, because it does not emit the structured identifiers at all. A zero-shot span model has no notion of a mod-97 check on an IBAN or the letter table on a Spanish DNI. It can label a string that looks like an ID, and it does not know whether the ID is real. The small NER model is the worst of the three alone, at 51.6% leak and 33.9% over-mask, and it is still the one we ship by default, because its errors are covered by the floor underneath it and its recall on people is the thing the floor cannot supply. So none of these tiers is a detector in the sense a buyer means. The product is the chain, and the chain's behaviour is not predictable from any single row. ## The tuning trap, which we walked into At one point we lowered the full tier's score threshold from 0.7 to 0.5. Raw recall on the GLiNER row went from 66.7% to 79.2% on the messy set, which looks like exactly the kind of win you ship. Measured on the shipped chain instead of the single detector, it was a regression. Leak did not move, because there was almost no leak left to buy at that tier. Over-mask went up roughly fivefold, and on UK English it went from 0 to 5.1%. Must-mask F1 dropped. The entire recall gain was in `organization` and `location`, the two types the policy keeps, so a user's masked output was identical in the good cases and more damaged in the bad ones. We reverted it and nothing shipped. The rule that came out of it is now a gate in the repository: no threshold change is judged on raw recall or on a single-detector row, only on the leak, over-mask and must-mask F1 of the chain that actually ships. It is worth writing down because the failure mode is not exotic. A number went up, the number was real, and the number was about something other than the thing we sell. ## What we actually conclude The 0.07% figure is an upper bound on real-world performance and we say so on the page that quotes it. The held-out set suggests the real number is several points higher on documents that have been through a scanner, and the largest model is not automatically the safest chain once the text stops being clean. The concrete follow-up is not a better model. It is a better eval: at least 200 hand-labelled real documents instead of ten, which is the only thing that would let us make a claim about messy text with a straight face. Until that exists, the messy numbers in this post are directional and we will keep labelling them that way. ## Where the numbers come from Every figure here comes from one run on 2026-07-23: Apple M2 Max, Node v26.5.0, CPU execution provider, no GPU, single run, no variance bands. What you can check: - The two models are public and pinned by SHA256: `onnx-community/gliner_multi_pii-v1` (`onnx/model.onnx`) and `Xenova/bert-base-multilingual-cased-ner-hrl` (`onnx/model_quantized.onnx`). The weights we score are the weights the apps ship, and both are downloadable from HuggingFace by anyone who wants to test them against their own data. - The full per-language and per-type tables, including the rows that look bad, are on [velumprivacy.com/benchmarks](https://velumprivacy.com/benchmarks), with the same held-out caveat stated there. - The behaviour that matters most to a buyer, which is what the tool does to your documents, is testable directly. Run your own worst file through it and read the masked output. That is the only measurement taken on text you care about. If you are evaluating Velum and want to grade it yourself, ask us for the gold set and we will send you the same 1,800 spans, so you can score our engine, or anyone else's, on the data these tables came from. --- Velum is a local PII masker for text and files. Detection runs on your machine with no network calls at runtime. The engine is licensed under PolyForm Noncommercial and the packages are not published yet, and the desktop app and browser extension are paid. [velumprivacy.com](https://velumprivacy.com) --- # Masking files, not just text: contracts and PDFs (2026-07-27) Source: https://velumprivacy.com/blog/masking-files-not-just-text When people picture an AI privacy mistake, they picture a sentence. Someone types a customer name into a chatbot, hits send, and a single line of text slips out. That happens. But it is the small version of the problem. The large version is a file. Someone drags a signed contract, a folder of client records, a batch of medical notes, or a quarterly export into an AI tool and asks it to summarise, compare, or draft something. One action, and the entire document is now sitting on a server somewhere. The leak is not a sentence. It is the whole thing. ## Why a file is riskier than a prompt A prompt is bounded. You wrote it, you can see it, and the amount of private data in it is whatever you chose to type. A file is the opposite. It carries far more than you are looking at in the moment. Think about a single employment contract. It holds names, a home address, a salary figure, a tax or national ID number, bank details, signatures, and dates. A client record export can hold thousands of rows, each one a person. A medical note can mix a diagnosis with a date of birth and a phone number in the same paragraph. You uploaded the file to ask one narrow question, but you handed over every identifier inside it. Files also tend to involve more people. A prompt is usually about one matter. A document is often the combined record of many: every customer in the export, every patient in the registry, every counterparty in the deal book. The person uploading rarely got consent from all of them to send their data to a third party, because the upload felt like a small convenience, not a transfer. And a file hides things. Tracked changes, comments, metadata, hidden columns, footnotes, and earlier drafts can all carry private data you are not even looking at on screen. You cannot redact what you did not notice. ## What file-level masking actually does File masking works on the document the same way reversible masking works on a prompt, but it reads the whole file first. The tool opens the document and reads the text across all of it, not just the part you are focused on. It finds the private data wherever it appears: names, emails, phone numbers, addresses, identification numbers, financial details, dates tied to a person. It replaces each one with a reversible placeholder, keeping the same value mapped to the same placeholder throughout, so the document still makes sense. Then it produces a masked copy you can safely use with an AI tool. When the AI replies, the original values are restored in the answer. You get a real, specific result, and the document that left for the model never carried the private data in the first place. The difference from old-style redaction is that nothing is destroyed. A redacted PDF gives you a black bar and no way back. A masked copy gives you a clean version to work with and the original values waiting to be put back into the reply. ## Common formats, handled locally Velum is built for files, not only text. It can take common document formats and produce a masked version on your own machine. The desktop app handles: - PDF - DOCX - RTF - TXT and Markdown - CSV and TSV Some PDFs are not really text. They are scans, an image of a page with no readable characters underneath. For those, the desktop app can turn on OCR, an optional extra you enable and download once, so it reads the words inside the image and masks them as it would any other text. It is slower than a text PDF, and it is desktop only. A scanned contract is still a contract, and the private data in it still needs to be found. The point that matters most: this happens locally. The reading, the detection, and the masked copy are all produced on your machine. The file does not take a round trip through someone else's cloud to get cleaned. Nothing readable has to leave your device for the masking to work, which means the document with the real names and numbers never sits on a server you do not control. ## Whole folders, not one file at a time Real work does not arrive as a single tidy file. It arrives as a folder. A case has a stack of exhibits. A deal has a data room. A reporting cycle has a directory full of exports. The Velum desktop app can mask text, single files, and entire folders, fully offline. You point it at a directory and it works through the documents inside, producing masked copies without you opening each one by hand. That is the difference between protecting the one file you remembered and protecting the batch you actually have. Batch masking also closes a quiet gap. When you process files one at a time, the tedious ones get skipped. Someone masks the contract they are thinking about and forgets the twelve supporting documents next to it. Whole-folder masking removes that choice. The set is handled as a set. ## The shift worth making The instinct to watch what you type into a chatbot is a good one. But it solves the smaller half of the problem. The data that moves in bulk moves as files, and files carry more identifiers, more people, and more hidden content than any prompt you would write by hand. Masking at the file level, on your own machine, means you can use AI on the documents you actually work with: the contracts, the records, the notes, the data exports, without sending any of it away to be read. The private data stays where it belongs, and you still get the answer you came for. See how it handles your documents with [Velum](/#downloads), or [request a demo](/contact). --- # Velum 0.9.0: permanent redaction (2026-07-26) Source: https://velumprivacy.com/blog/velum-0-9-0-permanent-redaction There is a particular kind of leak that keeps happening to people who were being careful. Someone opens a contract, draws black rectangles over the names and the account number, saves it, and sends it out. The document looks redacted. Anyone who selects the text under those rectangles gets the names and the account number back, because the words were never removed. A shape was placed on top of them. This has happened to court filings, government releases and corporate disclosures, repeatedly, for two decades. The tooling makes it easy to do the wrong thing and gives you no signal that you did. Velum 0.9.0 adds a third mode to the Files tab: **Redact permanently**. ![The Velum desktop app with Redact permanently selected on the Files tab](/blog/velum-0-9-0-cover.webp) *Redact permanently sits beside Anonymize and Restore, and says plainly what it does to the file.* ## What it actually does Velum does not draw anything on your PDF. It renders each page to an image, paints the bars onto the pixels, and rebuilds the document from those images. What sat under a bar is not hidden in the output. It is not in the output at all, in any encoding. You can check this yourself on the file Velum gives you. Select the whole page and copy it. Nothing comes out, because there is no text layer left to copy from. ![A redacted letter with the name, address, date of birth, IBAN, email and phone covered](/blog/velum-0-9-0-redacted-letter.webp) *Every identifier is gone from the file, not covered up. The reference number, the amounts and the terms are untouched, so the document still says what it needs to say.* Rebuilding the file has a second effect worth knowing about. Document metadata does not survive. XMP and document info routinely carry the original author, the title, and a trail of earlier revisions, none of which appear on the page and all of which travel with the file. A redaction that leaves those in place is only half done. ## The costs, stated plainly This mode is not better than masking. It is different, and it takes something away: - The output has **no text layer**. It is not selectable, not searchable, and not readable by a screen reader. - The file gets larger, because every page is now an image. - There is **no mapping and no undo**. Every other operation in Velum is reversible, by design: text becomes tokens, the mapping stays on your machine, and the original comes back when you ask. This one has no inverse. That is the whole point of it, and it is why the app asks you to confirm before it runs. Your original file is never modified. Velum writes a new one beside it. ## Images too A PDF carries its own text layer, so redacting one is a lookup. An image carries nothing, so on-device OCR does both halves of the job: it reads the text so the detectors have something to check, and it reports where every word sits so there is something to paint. ![A screenshot with an AWS key, an email, a phone number and a Slack token covered](/blog/velum-0-9-0-redacted-screenshot.webp) *A screenshot of deployment notes. The labels stay readable, the values do not.* Re-encoding the image has a useful side effect: EXIF does not survive. That metadata often carries GPS coordinates, which is not something most people think about when they share a photo of a document. ## Why this mode needs Maximum detection Permanent redaction only runs on Velum's strongest detection tier, and that restriction is deliberate. A redacted page carries authority. Someone who sees a row of black bars concludes the document was reviewed and cleared. There is no visual difference between a value that was deliberately kept and a value the tool failed to find. If masking misses something, you can see it and run it again. If this mode misses something, the file has already been sent, wearing the appearance of diligence. We set the floor by testing rather than by taste, and we got it wrong first. The gate originally allowed the middle tier. On a real vehicle registration document, that tier returned two detections and missed the registered owner's name completely. The strongest tier returned five, including the name. A page of confident black bars with the owner's name still legible is worse than a tool that declines the job, so the middle tier is now refused as well. If your detection setting is lower, the mode tells you why and offers to change it for you. ## Also in 0.9.0 **The Audit tab.** Credentials and personal data accumulate in places nobody chose to put them: AI assistant chat histories, shell history, config files and dotfiles, clipboard manager databases, screenshots, documents. Audit scans those surfaces, splits what it finds into secrets you should rotate and personal data you can mask, runs in the background, and keeps past scans so you can compare against them. **Two fixes worth naming.** Some PDFs name a font without embedding it, which government form generators do routinely. Velum was rendering nothing at all for that text while still reading every character from it, so redacted output came back with the values missing from the page. That is fixed, and the same bug was quietly affecting scanned-document OCR. Separately, redacted pages now keep the paper size of the original instead of coming out at double size and printing at the wrong scale. ## Getting it 0.9.0 runs on macOS on Apple silicon. If you already have Velum, it will offer the update next time you open it. [Get Velum for macOS](/desktop) *0.9.0 is superseded. The download page carries the current build, signed and notarized by Apple, so it opens without a Gatekeeper warning.* Everything above happens on your machine. No page, no image and no identifier is uploaded to anyone, including us. --- # Masking protects your data. Cleaning the file cuts your tokens. (2026-07-24) Source: https://velumprivacy.com/blog/masking-privacy-cleaning-tokens When you hand a document to an LLM, two things happen that are easy to miss. Something leaves your machine, and something gets billed. Velum changes both, but for different reasons, and the honest version of the story keeps them apart. The short version: feeding a model the clean, masked Markdown Velum produces, instead of the original PDF, costs roughly **65 to 90 percent fewer input tokens**. That saving is real, and it is worth understanding, but it comes from the file format, not from the masking. The masking is what keeps your personal data off a third party's servers. Both matter. Neither needs the other to be true. ## How an LLM bills a PDF Hand a PDF to a modern multimodal model (Claude, GPT, Gemini) and it does not treat it as text. The provider processes every page two ways and charges for both: 1. The **extracted text** from the page's text layer, tokenised normally. 2. A **rendered image of the page**, tokenised as vision input. That second charge is the one people forget. A full A4 or Letter page, sent as an image, lands at roughly: | Resolution | Image tokens per page | | ------------------------------ | --------------------- | | Standard vision | ~1,600 | | High-resolution vision | up to ~4,784 | Every page you send carries that image cost on top of its text. Velum's Markdown has no page images, so that column drops to zero. ## A worked example Take a real two-page municipal vehicle-tax receipt. Velum's masked Markdown output measures 6,478 characters and 878 words, which is about **1,700 input tokens**. Sending the same document as the raw PDF: | Component | Standard vision | High-res vision | | ----------------------------- | --------------- | --------------- | | Extracted text (both pages) | ~1,700 | ~1,700 | | Page images (two pages) | ~3,200 | ~9,568 | | **Total input tokens** | **~4,900** | **~11,270** | So the same two pages cost about 4,900 tokens as a standard-resolution PDF, or 11,270 at high resolution, against roughly 1,700 for the masked Markdown. That is a **65 to 85 percent** reduction for this document, and it holds up as a headline of **70 to 80 percent** for ordinary text PDFs. ## Why it scales the way it does The saving is dominated by the per-page image charge, and page images grow linearly with page count. A rough model: ``` raw PDF tokens ~ text + pages x image_per_page masked Markdown ~ text (no page images) ``` - **More pages, bigger saving.** A two-page receipt saves around 70 percent. A fifty-page contract is almost all page-image tokens, so the saving climbs toward 85 to 95 percent. - **Scanned or photographed PDFs save the most.** Their text layer is nearly empty, so sending them directly is almost pure image tokens. Velum reads them into clean text and ships text only, and the saving passes 90 percent. - **Dense text pages save the least,** still comfortably over 50 percent, because their extracted text is a larger share of the total to begin with. ## The honest part: this is the format, not the masking It would be easy to write "Velum saves you tokens" and leave the impression that masking does it. It does not. Replacing a name or an IBAN with a short placeholder like `⟦PERSON_1⟧` neither adds nor removes a meaningful number of tokens. Where a long value repeats, a short placeholder can even shave a little, but the effect is small. **Masking is roughly token-neutral.** The token reduction above comes entirely from converting a PDF into clean Markdown text. You would get the same reduction from a plain conversion with no redaction at all. We are saying this out loud because a privacy tool that inflates one claim has spent the trust it needs for the claim that actually matters. So there are two wins, and we state them separately: - **Format conversion** turns a PDF into clean text and drops the page images, cutting input tokens by 65 to 90 percent. - **Masking** keeps your personal data on your machine, so the model works on protected text and never sees the real values. ## What you actually get The document you send an LLM through Velum is clean, masked text. It is cheaper to send because it is text rather than a stack of page images, and it is safe to send because the personal data has been replaced with reversible placeholders that only your machine can restore. One is a cost saving. The other is the reason Velum exists. You get both, and you do not have to take either on faith: the numbers above are estimates you can reproduce, and the masking runs on your own device with no network calls at runtime. --- # Tokenized vs pseudonymized masking, explained (2026-07-17) Source: https://velumprivacy.com/blog/tokenized-vs-pseudonymized-masking You want to send a draft to an AI model, but the text holds a client name, an account number, maybe a phone number. You cannot paste it as is. So you mask it first. The question most people skip is how to mask it, because there is more than one good answer. Velum gives you two: tokenized and pseudonymized. They protect the same data, but they read very differently in the result, and that difference decides which one you should reach for. This post walks through both with small, clearly fictional examples, so you can pick the right mode without guessing. It is about which mode to use. For where those modes sit in data protection law, and why neither one is anonymisation, read [anonymisation, pseudonymisation, tokenization: which one you actually have](/blog/anonymisation-pseudonymisation-tokenization). ## How tokenized masking works Tokenized mode swaps each private value for an opaque placeholder. A person becomes a marker like `PERSON_1`. An identifier becomes something like `ID_1`. The placeholder carries no meaning of its own. It is a label that says "a real value used to sit here," nothing more. Here is a before and after. The original: > Please confirm whether Dilan Acar still holds account 4471-0099 before Friday. After tokenizing: > Please confirm whether PERSON_1 still holds account ID_1 before Friday. The model reads the structure of your request perfectly well. It knows someone holds an account and you want it confirmed by Friday. It just never sees who or which account. When the reply comes back, Velum restores the markers to the real values. The reason tokenized mode is a good default for quick questions and drafting is the way it handles the reply. Models rephrase things. They reorder sentences, change tense, and restate your point in their own words. Tokenized reversal is tolerant of that. Even if the model writes "the account in question" near the marker or shifts the sentence around, `PERSON_1` and `ID_1` stay intact as anchors, so Velum can put the real values back reliably. ## How pseudonymized masking works Pseudonymized mode takes a different path. Instead of an opaque label, it substitutes a fake but realistic stand-in. A name becomes a different, plausible name. An identifier becomes one that is format-valid but invented. The text still reads like ordinary prose, because nothing in it looks like a placeholder. The same original: > Please confirm whether Dilan Acar still holds account 4471-0099 before Friday. After pseudonymizing: > Please confirm whether Mara Voss still holds account 8830-2215 before Friday. Nobody named Mara Voss is involved, and account 8830-2215 is not real. But the sentence flows naturally, and that is the whole point. Pseudonymized mode is built for long prose: letters, contracts, briefs, anything where a string of `PERSON_1` and `ID_1` markers would read strangely and interrupt the model's sense of the document. A fake name lets the model treat the text as the finished piece it is meant to become. Reversal here works by exact match. Velum looks for the exact stand-in it inserted and swaps the true value back in. That makes pseudonymized mode a strong fit when the model is asked to preserve your wording rather than rewrite it freely. ## Why both keep the text consistent One rule holds across both modes: the same input value always maps to the same replacement. If Dilan Acar appears four times in a letter, every instance becomes the same `PERSON_1`, or the same Mara Voss, depending on the mode. The model never sees four different people where there is one. Relationships in your text stay coherent, which matters when a contract refers to the same party again and again. ## Choosing between the two A short way to decide: - Reach for tokenized when you are asking a quick question, drafting, or doing anything where the model will rephrase heavily. The tolerant reversal handles the churn. - Reach for pseudonymized when the output is long prose meant to read naturally, like a letter or contract, where opaque markers would feel wrong on the page. - Structured identifiers such as emails, phone numbers, and ID numbers are good candidates for realistic stand-ins, because a format-valid fake slots cleanly into the text without drawing attention. - Person names deserve a more careful look. A realistic fake name can be mistaken for a real one by anyone reading an intermediate version, so pseudonymizing a name is a deliberate choice, not an automatic one. When in doubt, an opaque marker removes that ambiguity. There is no universally correct mode. There is a correct mode for the job in front of you, and often the difference comes down to how the result needs to read. ## The one step you must not skip Whichever mode you pick, the masking only does its job if you finish the loop. The model returns its answer with placeholders or stand-ins still in place. Always restore, or unmask, that reply before you forward it, save it, or send it on. An unmasked draft is a draft that still has work left, and Velum handles the restore for you so the final text carries the real values and nothing else. Masking is not about choosing between privacy and a usable result. With two modes that suit different jobs, you keep the data protected on the way out and get clean, correct text on the way back. Ready to put this into practice? See how [Velum](/#downloads) masks and restores your data automatically, or [request a demo](/contact) to walk through both modes with your own examples. --- # Your prompts can become training data (2026-07-15) Source: https://velumprivacy.com/blog/your-prompts-are-training-data You open a chatbot, paste in a contract, and ask it to summarise the risky clauses. The reply comes back in seconds. The window feels like a private notebook, just you and the machine. It is not. The text you pasted left your computer, travelled to a company's servers, and may now sit in a log. It might be read by a person. It might help train the next version of the model. Most people never think about this. The interface looks calm and personal, so we treat it like one. But a chatbot is a service run by a company, and what happens to your words after you hit send depends on that company's choices, not yours. ## What "private" usually does not mean When you type into a consumer AI tool, your message is sent to a provider that processes it and stores some record of it. Two things tend to happen that surprise people. First, your content may be used to improve the model. For years, the common pattern across consumer AI products has been that user content can feed model training unless you turn that off or use a business plan. The setting to opt out often exists, but it is off by default in some products and buried in others. Many people never find it. Second, your content may be kept for a while even if it is never used for training. Providers commonly retain logs for a period to monitor for abuse, fraud, and safety problems. That retention is separate from training. So even a tool that promises not to train on your data may still store it for some time. The exact rules differ by provider, by plan, and by region. They also change. A policy you read last year may not describe what happens today. ## Humans may read what you write There is a second assumption worth dropping: the idea that only a machine ever sees your words. To keep these systems safe, providers run review processes. Automated systems flag content, and in some cases human reviewers look at flagged conversations to check for abuse or to improve quality. That is a normal part of running a large service. It also means a stranger could, in principle, read the text you thought was just between you and a model. For a casual question, that may not matter. For a client's financial records, a patient's history, an unreleased product plan, or anything covered by a confidentiality agreement, it matters a great deal. "A human probably will not see this" is not a standard you would accept anywhere else in your professional life. > For confidential or privileged material, "probably not used" and "probably not seen" are not good enough. Treat anything you send as something that could be stored and read. ## Why the defaults are the real problem You might think the answer is simple: just turn on the privacy setting, or pay for the business tier. Those help, and if you handle sensitive material you should do both where you can. But defaults and policies are a moving target. Settings get reorganized. New features ship with their own data handling. Free tiers and paid tiers follow different rules. A teammate on a personal account does not have the protections your enterprise account does. The moment you depend on a setting being correct on every account, on every product, on every day, you have built a system that will eventually fail quietly. And the failure is quiet. You will not get an alert that says your draft contract was retained or that a clause from it was reviewed. The data simply leaves and does not come back. There is no undo. This is why "the provider says it does not train on my data" is a weak control for anything that truly must stay private. It depends on a promise, a configuration, and a policy that can all change without your knowledge. ## The rule that does not depend on trust There is one assumption that is always safe: anything you send to an outside AI service could be stored. If you accept that, the path forward gets simple. The dependable control is not a setting on someone else's server. It is what you remove before your words ever leave your machine. Take out the names, account numbers, addresses, case identifiers, and other sensitive details first. Replace them with stand-ins. Then send the cleaned-up text. If the provider keeps it, reviews it, or trains on it, there is nothing sensitive there to keep. You get the help of a powerful model without handing over the parts that needed protecting. This is the difference between hoping and knowing. Tuning a privacy toggle is hoping the company behaves the way you expect. Masking the sensitive parts before they leave is knowing, because the protection happens on your side, under your control, before anything is sent. ## A simple habit to adopt You do not need to stop using AI tools. You need a habit: - Assume every prompt could be stored and read. - Never paste raw confidential or personal data into a consumer chatbot. - Strip or mask the sensitive parts on your own machine first. - Treat enterprise settings as a useful extra layer, not as your only line of defence. The tools are genuinely useful, and refusing to use them is not realistic for most professionals. The realistic move is to change what you feed them. Keep the question, remove the secret. Masking before sending is exactly what [Velum](/#downloads) is built to do. It removes sensitive details on your machine, so it no longer matters what a provider keeps or reviews. To see how this works for contracts, support tickets, medical notes, and more, [see the use cases](/use-cases). --- # The hidden risk of cloud PII scrubbers (2026-07-13) Source: https://velumprivacy.com/blog/cloud-pii-scrubbers-risk A growing class of tools makes a clean sounding promise. They say they will remove personal data from your text before it ever reaches the AI model. Names, emails, account numbers, health details, all stripped out, so you can use AI without exposing anyone. It sounds like the responsible choice. For many of these tools, it is not. The catch sits in one word that is easy to miss: where. Most of these scrubbers run in their own cloud. To remove your sensitive data, that service first has to receive your sensitive data. The raw, unredacted text leaves your machine, travels to a server you do not control, and only then gets cleaned. You did not reduce the number of companies that can see your confidential information. You added one. ## The promise hides a round trip Picture the path your text actually takes. You paste a contract, a support transcript, or a patient note into a tool. The tool sends that text to its cloud. The cloud finds the personal data, masks it, and returns a cleaner version. Then the cleaner version goes on to the AI provider. Read that again. The masking happens after the data arrives at the scrubbing company. So the order of events is: your raw text leaves your device, lands on their server, and the protection is applied there. The whole reason you reached for the tool was to keep that raw text private, yet the raw text is exactly what you handed over to get the job done. This is not a small detail. It is the difference between a promise of secrecy and a promise of process. "We strip your PII" describes what they do with your data. It does not say your data was never exposed. It cannot, because they had to hold the original to strip anything from it. ## Why "never leaves your machine" is the stronger claim Compare two statements. The first says: send us your raw data and we will clean it before passing it along. The second says: your raw data never leaves your device, because the cleaning happens on the device itself. The first asks you to trust a chain. Trust their network. Trust their storage. Trust their logging settings. Trust that no one on their side keeps a copy, and that their next policy update does not quietly change the rules. Every link in that chain is a place where your confidential text exists in full, readable form, outside your walls. The second removes the chain. If the masking runs locally, there is no server in the middle that ever holds the original. The text is processed where it already lives. Nothing readable crosses the network until the personal data is already gone. You are not trusting a vendor to handle your secrets well. You are arranging things so the vendor never holds your secrets at all. A promise you can verify by design beats a promise you have to take on faith. Local processing is verifiable by design. The data simply has no path to a third party. ## The questions to ask any privacy tool Marketing language blurs the line on purpose. So put the burden on the tool to be specific. Before you trust anything that claims to protect your data, get plain answers to these: - Where does the scrubbing happen, on my device or on your server? If the answer is anything other than "on your device", the raw text is leaving your control. - Who can see the raw text before it is masked? Your staff, your subprocessors, your AI provider, anyone? - Is the raw text or the masked output logged, cached, or retained at any point, and for how long? - Can the tool work fully offline, with no network access, and still do its job? - Can I inspect the code or the process, or am I taking the privacy claim entirely on your word? The offline question is the sharpest one. A tool that can run with the network switched off is a tool that physically cannot send your raw data anywhere. If a scrubber stops working the moment you cut its internet, you have your answer about where the work was happening. ## How Velum is built Velum was designed around the simple rule that the safest data is the data that never leaves. It runs locally and offline. The masking happens on your own device, before anything is sent onward. There is no Velum server sitting in the path, reading your raw text on the way through, because there is no path through us at all. That changes what you are being asked to trust. You are not trusting a privacy policy or a retention setting. The original text stays on your machine because the only place it gets processed is your machine. The claim that nothing leaves your device is one you can test rather than accept. Pull the network and mask a document: if the work still happens, it was always happening locally. Point a connection monitor at the app and watch what it opens while it runs. Those checks observe the software on your own machine, which makes them better evidence than anything we could write here. Velum's engine is licensed under PolyForm Noncommercial so the detection code can be read rather than trusted, though the packages have not shipped to npm yet. ## The point Cloud PII scrubbers can be useful, but be honest about what they are. A service that strips your data in its cloud has seen your data. It moved the exposure, it did not remove it. The stronger position is the boring one: keep the raw text on the device, do the work there, and make the behaviour testable from outside the product. If that is the standard you want, see how [Velum](/#downloads) handles it, or [request a demo](/contact) and put the offline test to it yourself. --- # Why one-way redaction breaks your AI answers (2026-07-10) Source: https://velumprivacy.com/blog/one-way-redaction-breaks-ai You have a sensitive question for an AI assistant, but it contains a client name, an email, maybe a contract number. The old advice is simple: black it out before you send it. Redact the private parts, paste the rest, stay safe. That advice keeps your data private. It also wrecks your answer. If the AI never sees who or what you are asking about, it cannot give you a specific, usable reply. You end up with a vague response that talks about [REDACTED] instead of the actual thing you needed help with. There is a better way, and the difference comes down to one word: reversible. ## What one-way redaction actually does Redaction is a one-way street. You take a piece of text, find the private bits, and destroy them. A name becomes a black bar. An account number becomes [REDACTED]. The original value is gone from the text forever, which is exactly the point when you are publishing a court document or releasing a report. The trouble starts when you want the AI to do real work. Language models answer based on what they can read. Hand them a prompt full of black bars and they have nothing to grab onto. The reply comes back generic, hedged, and stripped of the very details that would have made it worth reading. So you face a bad trade. Keep your data safe and get a useless answer, or paste the raw text and hope nobody minds your private information sitting on someone else's server. ## How reversible masking works instead Reversible masking refuses that trade. Instead of destroying the private values, it swaps them for stand-ins, sends the swapped version to the AI, and then puts the real values back when the reply returns. The flow has three steps: - Private details are detected and replaced with consistent placeholders before the prompt leaves your machine. - The AI reads and answers the masked text, working on structure and meaning without ever seeing the real values. - The original values are restored in the response, so you read a reply that names the actual people and numbers you asked about. The model does its job on a clean, anonymous version. You still get an answer that fits your real situation. Nobody on the other end ever sees a real name. A key detail makes this work: the same value always maps to the same placeholder. If a name shows up four times in your prompt, it becomes the same token every time. The AI can still reason that all four mentions are the same person, which is what keeps the answer coherent. ## A worked example Say you manage support tickets and you want help drafting a reply. Your real prompt is: > Draft a calm response to Gandalf Greyhame, who emails gandalf@fakemiddleearth.test, asking why invoice 7741 has not been refunded yet. With one-way redaction, the AI would see: > Draft a calm response to [REDACTED], who emails [REDACTED], asking why invoice [REDACTED] has not been refunded yet. The model has no name to address, no idea what to reference. You get a hollow template. With reversible masking, the AI instead sees something like: > Draft a calm response to PERSON_1, who emails EMAIL_1, asking why invoice INVOICE_1 has not been refunded yet. The AI writes a complete reply around those placeholders: > Dear PERSON_1, thank you for reaching out about invoice INVOICE_1. I am sorry for the delay on your refund. I have checked the account tied to EMAIL_1 and confirmed the refund is now being processed. Then the real values slot back in before you ever see it: > Dear Gandalf Greyhame, thank you for reaching out about invoice 7741. I am sorry for the delay on your refund. I have checked the account tied to gandalf@fakemiddleearth.test and confirmed the refund is now being processed. Same private prompt protection as redaction. A finished, specific, ready answer that redaction could never give you. ## Where Velum fits Velum is built to run this exact flow, and it runs it locally and offline on your own machine. It detects private data in your text and replaces it with reversible placeholders, sends only the masked version to the AI, then restores the original values in the response. The real data never has to leave your device to get a useful answer back. Velum gives you two ways to do the swap. The first is tokenized placeholders, the clean PERSON_1 and EMAIL_1 style labels you saw above, which make it obvious what was protected. The second is pseudonymized stand-ins: fake but realistic values, so a name becomes another plausible name and an address becomes another plausible address. That second mode is handy when you want the masked text to still read naturally for the model. Either way, the consistency rule holds. The same input value maps to the same placeholder across the whole prompt, so the AI keeps track of who is who and your restored answer lines up perfectly. ## The takeaway Redaction was designed for a world where you publish documents and never need anything back. AI is a different job. You are asking a question and you want a real answer. Reversible masking gives you both halves at once: a prompt that protects your private data and a reply you can actually use. You stop choosing between privacy and a good answer, because you no longer have to. Want to see it in action? Try [Velum](/#downloads) or [see the use cases](/use-cases). --- # The GDPR fines that should worry every firm using AI (2026-07-08) Source: https://velumprivacy.com/blog/gdpr-fines-ai-firms A penalty large enough to end a small firm can now arrive over a single act of mishandled personal data. European regulators have shown they will act, and they will act at a scale that makes the risk impossible to file under "later". The fines below are widely reported and, by any measure, severe. What ties them to your business is not their size but their cause: personal data moved or processed in a way the law did not permit. Every AI tool your staff touches is a fresh chance to do exactly that, often without anyone noticing until it is too late. ## The fines are real, and they are large The figures that follow are approximate and as reported, but the direction is clear. Regulators across Europe have been willing to issue penalties that run into the hundreds of millions of euros, and in one case past a billion. - Meta was fined about 1.2 billion euros in 2023 by Ireland's regulator over the transfer of personal data from the EU to the United States. - Amazon was fined about 746 million euros in 2021 by Luxembourg's regulator. - Google was fined 50 million euros in 2019 by France's data protection authority, the CNIL. - OpenAI was fined 15 million euros in 2024 by Italy's regulator, the Garante, over how ChatGPT handled personal data. - Clearview AI has been fined around 20 million euros by several European regulators, including those in Italy, France, and Greece, for unlawful processing of facial images. Read the list again and notice the spread. These are not all advertising giants caught over targeting. Two of them, OpenAI and Clearview, were penalised over how an AI system collected or processed personal information. The regulators are not waiting for AI to mature before they apply the law. They are applying it now. ## Why this should worry firms that are not Meta It is easy to look at a 1.2 billion euro penalty and decide it belongs to a different world. Your firm does not transfer data across continents at industrial scale, so the headline number feels like someone else's problem. That comfort is misplaced. The law that produced these fines is the same law that governs a lawyer pasting a client file into a chatbot to draft a letter. It is the same law that applies when an accountant uploads a spreadsheet of names and bank details to summarise it, or when a recruiter feeds a stack of CVs into an AI tool to rank candidates. The General Data Protection Regulation does not have a small business exemption for the moment personal data leaves your control. It asks whether you had a lawful basis, whether the data was kept secure, and whether you sent it somewhere it should not have gone. You will almost certainly never be fined 1.2 billion euros. But penalties scale to the organisation, and a sum that a global firm absorbs as a line item can close a practice of ten people. The exposure is not theoretical. It is the everyday gap between what staff do to save time and what the regulation actually allows. ## AI tools create new ways to mishandle data The trouble with most AI tools is that using them well and using them safely pull in opposite directions. To get a useful answer, people give the tool context, and the most useful context is often the most sensitive: the real name, the real account number, the real medical detail. The tool works better the more you tell it, which is precisely the behaviour the law is built to restrain. Once that information is pasted into a third-party service, you have made a transfer. You may not know where the provider stores it, whether it is used to train future models, which country the servers sit in, or how long it is retained. Each of those unknowns maps onto a question a regulator can ask. The OpenAI and Clearview cases show that authorities are already asking them of AI systems specifically. The risk is also quiet. A bad data transfer through an AI tool leaves no broken window and no obvious alarm. A staff member is simply trying to finish a task, and the personal data goes out with the prompt. By the time anyone reviews it, the data has already left. ## The fix is to keep personal data out of the tools The good news is that this exposure is avoidable, and the principle is simple. If personal data never reaches the third-party tool, there is no unlawful transfer to be fined over. You do not have to ban AI to stay on the right side of the law. You have to stop sending it the information it has no business holding. That is the idea behind masking data locally before it ever leaves your device. Names, account numbers, addresses, and other identifiers are detected and replaced on your own machine. The AI tool receives a version of the text with the sensitive parts removed, does its work, and the real values are restored on your side afterwards. The model still helps, but it never sees the data that would put you at risk. The personal information stays where it belongs, under your control. This is not a workaround bolted on after a breach. It is a change to the path the data takes, so that the dangerous transfer never happens in the first place. ## Where to start The fines on this page are a warning, not a forecast. Most firms will not make headlines. But the same law that produced them applies to the smallest, most routine use of an AI tool, and the cost of getting it wrong is high enough to take seriously. The sensible response is to make the safe path the easy path, so staff can use AI without ever handing over what they should not. [Velum](/#downloads) masks personal data on your device before it reaches any AI tool, so the information stays with you. If you want to see how it fits your firm's work, [request a demo](/contact). --- # GDPR and AI chatbots: where prompts cross the line (2026-07-06) Source: https://velumprivacy.com/blog/gdpr-ai-chatbots-line A support agent pastes a customer email into a public chatbot to draft a reply. A recruiter drops a candidate CV into a prompt to summarise it. A lawyer asks an assistant to redline a contract that names real people. Each of these takes seconds, feels harmless, and may be unlawful under GDPR. The reason is simple, and most teams miss it. The moment personal data leaves your control and reaches a chatbot provider, you have carried out a processing operation. If that provider sits outside the EEA, you have also made an international transfer. Both need a lawful footing. Neither is something you can wave away because the tool was convenient. This is not a theoretical concern. Regulators have already acted, and the numbers are not small. ## The prompt is a processing operation GDPR governs the processing of personal data. Processing is broad. It covers collection, use, disclosure by transmission, and making data available. When you type a name, an email address, a health detail, or any information about an identifiable person into a chatbot and press send, you are disclosing that data to a third party. That is processing, and you are doing it as a controller. Every processing operation needs a lawful basis under Article 6. Consent, contract, legitimate interests, and the others are not interchangeable defaults you can assume after the fact. You need to identify the basis before the data moves, and you need to be able to show it. Data minimisation sits right beside this. Article 5 requires that personal data be adequate, relevant, and limited to what is necessary. A prompt that includes a full customer record to answer a narrow question fails that test. If the chatbot only needs the shape of a problem, it does not need the person attached to it. > If the model does not need to know who the person is to do the task, the person's identity has no business being in the prompt. ## The chatbot provider is a third party It is tempting to treat a chatbot as a tool, like a calculator or a text editor that runs quietly on your side. It is not. A public chatbot is operated by a separate company that receives your input, processes it on its own infrastructure, and may use it in ways set out in its own terms. That makes the provider a third party in GDPR terms, and often a separate controller or a processor depending on the arrangement. Either way, sending personal data to it is a disclosure. You need a basis for that disclosure, you need to have done your due diligence on the recipient, and you need the contractual terms that GDPR requires when a processor is involved. The casual, account-level use that happens across most organisations rarely has any of this in place. People sign in with a personal or team login, paste what they need, and move on. There is no record of what was disclosed, no assessment of the recipient, and no basis written down. From a compliance standpoint, that is exposure sitting in plain sight. ## When the data leaves the EEA Chapter V of GDPR restricts transfers of personal data outside the EEA. A transfer needs an adequacy decision, appropriate safeguards such as standard contractual clauses, or a narrow derogation. Many widely used chatbot providers process data on infrastructure outside the EEA. If your prompt reaches them there, you have made a restricted transfer. This is where the convenience of a public chatbot collides hardest with the law. The transfer rules were written precisely for the situation where personal data crosses a border to a recipient whose legal environment you do not control. Pasting a customer file into a prompt can trigger every one of those rules at once: a disclosure to a third party, on the basis of nothing in particular, across a border without safeguards. ## The regulators are not waiting If this still feels abstract, the enforcement record removes any doubt. As widely reported, in March 2023 Italy's data protection authority, the Garante, temporarily banned ChatGPT over privacy concerns. Access was restored only after OpenAI made changes to address what the regulator raised. That was not the end of it. As widely reported, in December 2024 the Garante fined OpenAI 15 million euros over data protection issues connected to ChatGPT. The Garante has also taken action against other AI services. The pattern is consistent: European regulators treat the handling of personal data through these tools as regulated activity, and they are prepared to use the full range of their powers, from suspension to substantial fines. The lesson for a controller is not that chatbots are forbidden. It is that the data you put into them carries the same obligations it carries everywhere else. Regulators have shown they will look, and they will act. ## The safe pattern: nothing regulated to transfer There is a clean way through this, and it does not require banning useful tools. The principle is to make sure that by the time a prompt leaves your control, it contains no personal data at all. If you remove or mask names, contact details, identifiers, and other personal data before the text reaches the chatbot, then the thing you send is no longer personal data. There is no disclosure of an identifiable person, no lawful basis to scramble for, and no restricted transfer, because there is nothing regulated left to transfer. The model still gets the structure and the substance it needs to be useful. The person stays behind. This is data minimisation turned into a workflow rather than a wish. Instead of trusting people to judge, prompt by prompt, what is safe to paste, you strip the regulated content out at the boundary, before it can leave. The task gets done. The exposure does not happen. For DPOs, lawyers, and compliance teams, this reframes the question. You are no longer asking whether each chatbot use was lawful after it happened. You are making the unlawful version impossible to send. If you are turning this into a written rule, the free [AI usage policy template](/ai-usage-policy-template) covers lawful basis, transfers, and what staff may enter into a prompt, with a data classification table you can adopt as it stands. There is no form to fill in. That is the role [Velum](/#downloads) is built to play: it removes and masks personal data before a prompt ever leaves your control, so the regulated content never reaches a third party or crosses a border. If you want to see where this fits across support, recruitment, legal, and the other places prompts go out every day, [see the use cases](/use-cases). --- # What counts as personal data in an AI prompt (2026-07-03) Source: https://velumprivacy.com/blog/what-is-personal-data-in-ai-prompt You open a chat with an AI tool, paste in a work question, and hit send. It feels harmless. It almost never is. The text you just sent often carries more about real people than you realised, and once it leaves your screen you no longer control where it sits or who can read it later. Most people picture personal data as a passport number or a credit card. Those count, but the category is far wider than that. The good news is that once you can spot it, you can deal with it. You do not have to stop using AI. You just have to remove the personal parts first. ## What personal data actually means The clearest definition comes from the GDPR, the European data protection law. Article 4 defines personal data as any information relating to an identified or identifiable natural person. Read that slowly. Two words do the heavy lifting. "Identified" means you already know who the person is. "Identifiable" means you could work out who they are, directly or by piecing other details together. So personal data is not only the obvious identifiers. It is anything that points back to a specific human being. The law also marks out special categories that get extra protection. These include health information, biometric data, and other sensitive details about a person. If your prompt touches any of those, you are handling the most protected kind of data there is. ## The two ways data points to a person It helps to split identifiers into two types. Direct identifiers name the person on their own. A full name, an email address, a phone number, a national ID number, a passport number, or a home address each point to one individual with no extra work needed. Indirect identifiers are the quiet ones. Each looks harmless alone, but combine a few and they single someone out. A job title plus a company plus a city can be enough. A birth date plus a postcode can be enough. None of these is a name, yet together they describe exactly one person. This is why "I removed the name, so it is fine" is a trap. The name is often the easiest part to strip and the least of your worries. The combination of small facts is what quietly gives someone away. ## What hides in an everyday prompt Here is a normal work request, the kind people send dozens of times a week: "Draft a firm but polite email to Maria Gonzalez at maria.g@northbridge.test about her overdue invoice INV-20471 for the consulting work. She mentioned she has been off sick recovering from surgery, so keep the tone gentle. Her direct line is +34 612 445 980 if she wants to call." Look at how much personal data is packed into three sentences: - A full name, which is a direct identifier - An email address, another direct identifier - A phone number, a third direct identifier - An invoice number and account context that tie to a real client relationship - A health detail, recovering from surgery, which falls into the special category that gets extra protection That last one matters most. A health reference about a named person is exactly the kind of sensitive data the rules treat with the most care, and it slipped in almost by accident, just to set the tone of the email. Now imagine that same prompt sent to a tool you do not control, stored on a server you have never seen, possibly read by people you will never meet. You wanted help writing an email. You handed over a small dossier on Maria. ## Why this is easy to miss Personal data hides because it is doing a useful job in your sentence. You include the name so the email feels real. You mention the surgery so the tone lands right. You add the phone number so the reply is easy. Every detail is there for a sensible reason, which is exactly why your eye slides past it. The other reason is habit. When you talk to a colleague you trust, you share context freely, and that is fine because you both work for the same employer under the same rules. An AI tool can feel like that trusted colleague. It is not one. It is a system that may keep, move, or process what you send in ways you cannot see. ## The fix: remove the personal parts first The takeaway is simple. The goal is not to use AI less. The goal is to send it the problem without the people. In the example above, the AI does not need to know the client is called Maria Gonzalez. It does not need her email, her phone number, or her medical history. It needs to know that a named client has an overdue invoice and a sensitive personal reason for a gentle tone. Swap the real details for safe placeholders, reversibly, and the AI writes you the same quality email, because the shape of the request is unchanged. The personal parts were never what made the answer good. The important word is reversibly. If you blank out the details by hand, you get back a draft full of gaps you have to fill in again, and people quickly give up and just paste the raw version. What you want is a way to mask the personal parts on the way out and restore them on the way back, so the final result is ready to use with the real names back in place. That is the whole idea. Spot the personal data, direct and indirect, including the sensitive categories. Replace it before it reaches the AI. Get a useful answer. Put the real details back yourself, on your side, where they belong. Writing this down as a rule people can follow is what the free [AI usage policy template](/ai-usage-policy-template) is for. Its data classification table sets out which categories may reach which tools, and it names the special categories explicitly so nobody has to guess. [Velum](/#downloads) does exactly this. It masks the personal parts of a prompt before they ever reach an AI model, then restores them in the response, so your team keeps the speed of AI without handing over the people behind the words. To see it on your own prompts, [request a demo](/contact). --- # The day Samsung banned ChatGPT (2026-06-29) Source: https://velumprivacy.com/blog/samsung-chatgpt-ban A few keystrokes is all it took. An employee, trying to fix a problem faster, pasted confidential source code into a chatbot. The work got done. The data was gone. Not deleted, gone in the worse sense: copied into a system the company did not control, could not audit, and could not call back. This is the story of how one of the largest technology companies in the world learned that lesson in public, and what it means for anyone who handles information they are paid to protect. ## What happened at Samsung In April 2023, as widely reported, employees in Samsung's semiconductor division turned to ChatGPT to speed up their work. In separate incidents, staff reportedly pasted confidential material into the tool. One case involved internal source code. Another involved notes taken from a recorded internal meeting. The intent was not malicious. These were people doing their jobs, using a tool that felt like a smarter search box. They wanted faster answers, cleaner code, a tidy summary. The chatbot delivered. What they did not see was where their words went after they hit enter. Shortly after, Samsung acted. The company restricted, then banned, the use of generative AI tools like ChatGPT on company-owned devices and networks. It also limited the size of prompts employees could send. A ban is a blunt instrument, and companies do not reach for blunt instruments when the stakes are small. Samsung was not alone. Around the same period, other large organisations did the same. Banks including JPMorgan restricted employee use of public chatbots. Apple and Amazon placed limits of their own. Different industries, same fear: well-meaning staff sending out data they should never have sent. ## Why one prompt is one too many Here is the part that should worry every privacy officer and every lawyer reading this. When you paste text into a public AI tool, you are not borrowing the tool. You are handing over a copy. That copy now lives outside your walls. It may be stored. It may be reviewed by humans for quality and safety. It may, depending on the terms and settings, be used to train future versions of the model. You cannot un-send it. There is no recall button that reaches into someone else's servers and scrubs your trade secret, your client's name, or your draft settlement figure. Once private data is in a prompt, it has left your control, and the only honest assumption is that it is gone. > A confidential document does not stop being confidential because it was useful in the moment. The leak is not the breach you read about later. The leak is the paste. Think about what passes through a normal working day in a law firm, a clinic, or a finance team: - Client names tied to sensitive matters - Draft contracts and settlement terms - Patient details and case histories - Internal source code and system designs - Financial figures that are not yet public Every one of these is something a professional is trusted to keep. And every one of these is exactly the kind of text someone might paste into a chatbot to "just get a quick summary." ## The trap is the tool feels safe The reason this keeps happening is not that people are careless. It is that the tools feel private. A chat window looks like a conversation with one assistant. It feels closed, personal, yours. Nothing about the experience signals that your words are travelling to a third party. There is no warning label on the box that says: anything you type here may leave the building. So the gap is not a gap in good intentions. It is a gap between how the tool feels and what the tool does. You can write a policy that says do not paste confidential data into public AI. Samsung had smart people and serious rules, and it still happened. Policies depend on every person remembering, every time, under deadline pressure. That is not a control. That is hope. The honest conclusion is uncomfortable: if the only thing standing between your confidential data and a public AI tool is an employee's memory, you do not have a safeguard. You have a near miss waiting to be a headline. ## The fix is to mask before you send There is a better answer than banning the tools, and it is simpler than it sounds. If the problem is that private data leaves your machine, then the fix is to make sure private data never leaves your machine in the first place. Not to slow people down. Not to block the tools that genuinely help them work. To remove the secret from the text before the text goes anywhere. This is what masking does. Before a prompt reaches any AI, the sensitive details are stripped out and replaced. The names, the figures, the identifiers, the code that should stay home, all of it is handled on your side. The AI sees a question it can answer. It never sees the parts that would have caused the leak. Your people keep their speed. Your data keeps its place. Samsung reached for a ban because, in 2023, masking before the prompt was not the default way of working. It can be yours. The employees in this story were not the problem. They were trying to do good work. The problem was that there was nothing between their good intentions and a system they could not control. Put something there. If you are writing the rules for your own organisation right now, the [AI usage policy template](/ai-usage-policy-template) is free and asks for no email. Its closing section covers this exact question: how to let staff use AI instead of banning it. See how [Velum](/#downloads) masks private details before they reach any AI, and [request a demo](/contact) to see it on your own data.