Should you mask or tokenize before an agent reads the data?

Tokenize before ingest if the reader is an autonomous agent. Mask if the reader is a human on a BI dashboard whose role you actually trust. The reasoning behind that split is what the rest of this walks through.

Snowflake Dynamic Data Masking is a query-runtime, role-based control. The unmasked plaintext still lives in the table, and it gets returned in full to the roles you authorize. Masking is reversible inside the platform by design, and the raw identifier stays reachable in the query path. That's great when you trust the role.

An agent is a role you can't fully trust. The OWASP Top 10 for Agentic Applications, published December 9, 2025 and formally branded the 2026 edition, ranks ASI01 Agent Goal Hijack as the number one risk: attacker content buried in a document or a RAG result rewrites what the agent is trying to do. If the hijacked agent's role can read plaintext, it can exfiltrate plaintext. Tokenization pulls the sensitive value out of that path, so a hijack leaks tokens rather than the underlying identifiers.

How Snowflake dynamic data masking actually works

Dynamic Data Masking is column-level security. You attach a masking policy to a column, and per Snowflake's docs, the policy is applied to the column at query runtime at every location where the column appears. Projections, WHERE, JOIN, ORDER BY, GROUP BY, all of it. It rewrites the result set, not the stored bytes. The plaintext in the table never moves.

What comes back depends on who's asking. Again from the docs: depending on the masking policy conditions, the SQL execution context, and role hierarchy, a query operator may see the plain-text value, a partially masked value, or a fully masked value. Authorized roles see the clear value in full.

Two things fall out of that. One, masking is a cheap, native, correct way to keep an unprivileged human analyst from seeing SSNs. Two, it's reversible-by-role by definition, so it does nothing to shrink what a privileged reader can pull. An agent connecting under a privileged service role is a privileged reader, which is exactly where the risk sits.

One more wrinkle worth naming. DDM masks individual column values, but it does nothing about re-identification through joins or aggregation, so a masked dataset can still leak someone's identity through linkage. Snowflake pairs DDM with aggregation and projection policies for exactly that reason. Masking alone doesn't stop a linkage attack, and treating it like it does is a common mistake.

How tokenization is different, and what Snowflake tokenization is not

Tokenization swaps a sensitive value for a non-sensitive surrogate. The mapping lives in a separate vault, so the original is recoverable only by whoever holds that vault. Masking transforms a value for display while the original stays put. Tokenization removes the original from the dataset and parks the key somewhere else. That relocation is the entire security difference.

Vaulted tokenization isn't the only shape that preserves format and joins. Format-preserving encryption (NIST SP 800-38G) keeps the field's format and type intact, so column joins and schemas survive just like they would with deterministic tokens. The trade-off is that FPE derives the surrogate from a key rather than a lookup vault, so you give up the key-relocation benefit: the secret that reverses every value lives with the algorithm instead of sitting in a separate store you can lock down, rotate, or destroy independently. If the key-relocation property is the reason you're tokenizing, a vault buys you something FPE doesn't.

Snowflake does ship a tokenization feature, and it pays to be precise about what it is. Per the docs, External Tokenization enables accounts to tokenize data before loading it into Snowflake and detokenize the data at query runtime. Detokenization runs through a masking policy that calls an external function to a tokenization provider, and wiring up a provider needs Enterprise Edition or higher. That external-function round-trip happens at query time, so it adds latency and ties query availability to the provider's uptime, which is a big part of why the detokenization path stays inside the query engine rather than getting pushed elsewhere.

The mechanism has a catch. Detokenization happens at query time, for authorized roles. Both DDM and External Tokenization are implemented as column-level masking policies. So the clear value is reconstructable inside Snowflake's query path for the roles you allow. Better than raw plaintext sitting at rest. Still the same trust question the moment someone reads.

Why the choice matters more for agents than for humans

A human analyst who gets phished is a bad afternoon. An agent that gets goal-hijacked is a program that will follow attacker instructions at machine speed against every row it can touch. The blast radius is not in the same league.

The published standards back this up. The OWASP Top 10 for LLM Applications 2025, released November 2024, puts LLM01 Prompt Injection at number one and splits direct injection from indirect injection, where the model ingests untrusted external content and treats it as instructions. The agentic list then promotes prompt-injection-driven goal manipulation to its own number one slot, ASI01 Agent Goal Hijack. Small nuance worth keeping honest: OWASP kept LLM01 on the LLM list and reframed the agent version as ASI01. It's a reframing across two lists, not a formal merger.

Taken together, the picture is concrete. An agent treats retrieved content as instructions, and it can be talked into exfiltrating whatever it can read. Masking that's reversible for the agent's role leaves raw PII sitting in the query path, so a hijacked agent walks it out the front door. Tokenize before the data reaches the agent and the exfiltration channel carries surrogates. Same attack, much smaller hole.

EchoLeak: the incident that makes this concrete

If this still reads as theoretical, meet EchoLeak (CVE-2025-32711). Aim Labs found it, Microsoft rated it critical at CVSS 9.3, shipped a server-side fix in May 2025, and it went public on June 11, 2025.

The mechanism is remarkably simple. One crafted email carries hidden instructions. Microsoft 365 Copilot pulls that email into its RAG context and runs the instructions, exfiltrating internal data (chat, OneDrive, SharePoint, Teams) to an attacker server. Zero clicks from the victim. Aim Labs named the underlying class LLM Scope Violation in their own writeup, and independent reporting corroborated the disclosure. Separate research has documented EchoLeak as the first real-world zero-click prompt-injection exploit in a production LLM system.

Keep the label accurate, because it matters. This was responsibly disclosed research, and Microsoft found no evidence of in-the-wild exploitation. It's still the cleanest proof of the thesis. An agent with reversible read access to sensitive data can be made to leak it. Had that data been tokenized at ingest, the same channel carries only surrogate tokens. And yes, this is an engineering threat model, not a full security program. Treat EchoLeak as one control's worth of lesson, not the whole syllabus.

Masking vs tokenizing: a quick decision table

  • Human BI, trusted role, needs the real value sometimes: Dynamic Data Masking. Cheap, native, right for the job.
  • Autonomous agent reading at scale: tokenize before the agent sees it. Don't lean on a reversible-by-role control.
  • You need equality joins and GROUP BY on the field but never the raw value: deterministic tokenization. Same input yields the same token, so joins and grouping survive.
  • You need LIKE/substring search or range and ordering on the original value: neither deterministic tokenization nor full masking gives you that. Deterministic tokens preserve equality, not substring or order. Design the query pattern first.
  • Regulated erasure (GDPR right to be forgotten): tokenization with a held key lets you crypto-shred. Destroy the key and the token is irreversible.

One compliance note so nobody gets it wrong. NIST SP 800-188, finalized September 2023, is the federal taxonomy for de-identification, covering pseudonymization, k-anonymity, quasi-identifiers, and re-identification risk. Under GDPR Article 4(5), reversible tokenization with a separately held vault is pseudonymized data. It's still personal data, because the vault mapping is exactly the additional information kept separately that the definition points at. Tokenizing is not anonymizing. Don't let anyone tell you otherwise.

How to secure PII before an agent reads it: best practices

In practice, the sequence looks like this:

1. Classify at ingest, not at query time. Decide which fields are identifiers before anything lands in your analytical store. This is also where k-anonymity generalization earns its keep: coarsen quasi-identifiers (birthdate to birth year, ZIP to region) so a token plus surrounding context can't quietly re-identify someone. 2. Tokenize the direct identifiers with deterministic, join-preserving tokens, and hold the vault outside the query path. The agent should never have a code path to the clear value. 3. Keep the vault customer-side. If detokenization is reachable from the same query engine the agent uses, you have put the clear value right back within the agent's reach. 4. Authorize per tool call, not per session. A long-lived agent session is a long-lived hole. Scope each call and keep the ability to revoke mid-session. 5. Govern the MCP boundary. The MCP Security Best Practices, companion to the June 2025 authorization spec, is blunt: "MCP servers MUST NOT accept any tokens that were not explicitly issued for the MCP server," and token passthrough is flatly forbidden. It also covers the confused-deputy attack on proxies, SSRF during OAuth discovery, and session hijacking, and it wants per-client consent, exact redirect_uri matching, and least-privilege scopes. Remember that injection doesn't only ride in on user input: tool poisoning hides instructions in tool descriptions, and in practice the malicious content often arrives in the tool result itself. 6. Log every read into something tamper-evident so that after an incident you can prove exactly what the agent touched.

The sibling deep-dive, tokenizing PII before it reaches an LLM, walks the ingest pipeline in more detail.

Govern the data plane, not just the prompt

Most agent-security tooling watches what the model produces. Prompt filters, output guards, jailbreak classifiers. Useful, and all of it is guessing at intent. The sturdier move is to govern what the agent can reach, so a fully hijacked agent still finds nothing worth stealing.

That's the idea behind DataShield's Ontology: govern at ingest. PII is tokenized into Parquet served over MCP (the DataShield Analytical DB) with a customer-held vault, using deterministic join-preserving tokens plus k-anonymity generalization, with crypto-shred erasure for the right-to-be-forgotten case. A hijacked agent reading that store sees surrogates.

Plain framing so procurement doesn't get surprised: DataShield doesn't rewrite your Snowflake tables in place, it isn't a Snowflake masking policy, and it isn't a prompt or proxy interceptor sitting in front of the model. It governs at ingest or at the MCP boundary, where per-call authorization and mid-session revocation live, and every call is sealed into a tamper-evident audit chain you can check at /verify. And no, there's no SOC 2 attestation yet. When there is, we'll say so plainly.

The honest limits

Tokenization isn't a free lunch, and any pitch that claims otherwise is overselling it.

Deterministic tokens preserve equality joins and GROUP BY. They don't preserve LIKE/substring search, or range and ordering queries on the original value. If your agent workload genuinely needs fuzzy search over raw names, tokenization at ingest will fight you, and you're better off designing around that up front than discovering it in production at 2am. Masking keeps those query semantics because the real value is still sitting right there, which is exactly why it's also still reachable.

Snowflake's surface keeps moving, so verify current edition requirements and whether Horizon governance features have shifted the comparison by the time you read this. The mechanism-level point survives the product renames: a control that returns clear values to an authorized role doesn't protect you from a reader you can't trust. An agent is that reader. Pick the control that matches the threat, and if the reader is autonomous, get the secret out of the query path. When you want to scope this against your own data, the architecture overview and a quote are the next stops.

Snowflake dynamic masking in practice, plus the agent-side risks that make tokenization worth it.

Dynamic data masking: Snowflake data security video

Snowflake dynamic data masking (Sanjay Kattimani)

MCP Tool Poisoning: A Critical Agent Security Vulnerability video

MCP tool poisoning (sublimetechie)

OWASP LLM01:2025 Prompt Injection Explained video

OWASP LLM01 prompt injection explained (IT Bulls)

Frequently asked questions

Does Snowflake dynamic data masking change the stored data?

No. Per Snowflake's docs, the masking policy is applied to the column at query runtime at every location it appears, and it rewrites the result set. The unmasked plaintext still lives in the table and is returned in full to authorized roles. Masking is a display-time, reversible-by-role control, not a change to the stored value.

Is tokenization reversible?

It depends on the vault. Reversible tokenization keeps a mapping in a separately held vault so an authorized party can recover the original, which under GDPR Article 4(5) makes the data pseudonymized rather than anonymized. If you crypto-shred by destroying the key or vault entry, the token becomes irreversible, which is how tokenization supports a right-to-erasure request.

Can a masked column still leak PII to an AI agent?

Yes, if the agent's role is authorized to see the clear value. Masking returns full plaintext to authorized roles, so a hijacked agent reading under a privileged service role can exfiltrate the raw identifier. OWASP ASI01 Agent Goal Hijack (December 2025) and the EchoLeak proof-of-concept both show agents being induced to leak whatever they can read.

Does deterministic tokenization break my SQL joins?

No. Deterministic tokenization yields the same token for the same input, so equality joins and GROUP BY on the tokenized column still work. What it does not preserve is LIKE/substring search or range and ordering queries on the original value. Confirm your query patterns before you tokenize a field.

Is Snowflake External Tokenization the same as masking?

They are implemented the same way, as column-level masking policies, but the intent differs. External Tokenization lets you tokenize before loading and detokenize at query runtime via an external provider, and it requires Enterprise Edition or higher. Because detokenization is available to authorized roles at query time, the clear value remains reconstructable inside Snowflake's query path, same as with masking.