TL;DR
Detect-then-Reflect and Retrieve-then-Detect are two mechanisms for spotting sensitive data in tables that take context into account, not just the data type. The first works in two steps: first it finds potentially sensitive columns (email, address, phone), then it evaluates them in the context of the whole table. The second first retrieves sensitivity rules for a specific domain (country, industry), then evaluates the data based on them.
Standard tools (Google DLP, Microsoft Presidio) work on the principle of "found an email, so it's sensitive," which produces tons of false positives. If a table has an "email" column, it might hold corporate addresses like [email protected] (not sensitive) or employees' personal addresses (sensitive). Naive methods flag everything. Same with "addresses" — a company's office address vs a person's home address. Or "names" — the name of an organization's contact person vs the full name of a private individual. Context decides.
Detect-then-Reflect first casts a wide net (finds every column of type "name," "address," "phone"), then filters through the context of the whole table: it looks at the other columns, the values, and the table's purpose. The result: precision rose from 53% (Google DLP) to 73-90% while keeping recall high at 94%. Retrieve-then-Detect handles non-standard data: it retrieves rules (for example, "coordinates of hospitals in a conflict zone — high sensitivity") and evaluates the data with them in mind.
Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.
Method Blueprint
Detect-then-Reflect (for typical sensitivity)
STEP 1 (Detection): Find potentially sensitive columns
→ A list of columns with types: email, phone, address, name, etc.
STEP 2 (Reflection): Evaluate each one in the context of the table
→ For each column: non_sensitive / moderate_sensitive / high_sensitive
Both steps can be done in one conversation with two consecutive prompts.
Retrieve-then-Detect (for domain-specific sensitivity)
STEP 1 (Retrieve): Extract sensitivity rules for the domain
→ Relevant rules from documents/policies/standards
STEP 2 (Detect): Evaluate the data based on those rules
→ For each column: non_sensitive / moderate / high / severe
Example in Practice
Task: You're preparing a table of speaker contacts for a tech conference to publish on the website. The table has: name, company, title, email, phone, city. You need to figure out which columns can be published openly and which are for organizers only.
Prompt (Step 1 — Detection):
I have a table with conference speaker data. Find every column
that may contain personal data (PII).
Table (first 5 rows):
| Name | Company | Title | Email | Phone | City |
|------------------|-----------------|-----------------|--------------------------|----------------|------------|
| Alex Miller | Google | Head of ML | [email protected] | +1 312 555-0147 | Chicago |
| Maria Peterson | Chase | Lead Developer | [email protected] | +1 212 555-0198 | New York |
| Daniel Evans | Meta | Tech Lead | [email protected] | +1 206 555-0163 | Seattle |
Return a list: Column name → Data type (name/email/phone/address/etc)
Prompt (Step 2 — Reflection):
Now evaluate the sensitivity of each column you found in the context of the whole table.
Context: the table will be published on the conference website.
For each column, say:
- non_sensitive (can be published openly)
- moderate_sensitive (OK, but with care / with consent)
- high_sensitive (must not be published)
Explain why.
Result:
The model will return two blocks. The first is a list of potentially sensitive columns (Name, Email, Phone). The second is an evaluation of each in context:
- Name → non_sensitive (a public figure, a conference speaker)
- Email → moderate_sensitive (a corporate address, usually published with consent; a personal one would be high)
- Phone → high_sensitive (a personal contact, not meant for publication)
- Company, Title, City → non_sensitive (public information)
You get a concrete decision for each column with a rationale, not just "there's PII, so everything is sensitive."
Why It Works
The weakness of LLMs and naive methods: Regexes and simple detectors (Google DLP, Presidio) work on the principle "found a pattern → flagged it." Found an @, so it's an email — flagged as sensitive. Found a phone format — flagged. The result: a flood of false positives. A table of company contacts gets flagged as "full of personal data," even though it only contains corporate addresses like [email protected].
The strength of LLMs: The model can analyze context — look at the whole table, understand the relationships between columns, and tell "an employee's email" from "a company's support email." It sees that a "Company" column next to an "Email" column hints at a corporate context. It sees that "Address" in the context of "Headquarters" is public information, while "Address" in the context of "Place of residence" is private.
How Detect-then-Reflect uses this: The first step gives high recall — we catch every potentially sensitive type. The second step gives high precision — we filter through context. The model looks not only at the column itself but at its neighbors, at the data type in the rows, at the table's overall topic. "Email in a B2B partner table" → most likely corporate. "Email in a donors table" → more likely personal. Context decides.
Control knobs:
- Sensitivity levels — you can swap the three-level scale (non/moderate/high) for your own: for example, "publish / publish with consent / don't publish / delete."
- Types to detect — in Step 1, list specific types for your task (for example, add "bank details," "SSN," "passport data").
- Usage context — state explicitly in Step 2 where the data will go ("for an internal report" vs "for publication on the website" vs "for sharing with third parties") — the model will rate sensitivity differently.
- Domain rules — for Retrieve-then-Detect, plug in your own rules: corporate policies, industry standards, regional requirements.
Prompt Template
Detect-then-Reflect
Step 1 — Detection:
I have a table: {brief_table_description}.
Find every column that may contain sensitive data
(personal, financial, confidential).
Table (first 5 rows):
{paste_table_in_markdown}
Return a list: Column name → Data type (name/email/phone/address/financial/etc)
Step 2 — Reflection:
Evaluate the sensitivity of each column you found in the context of the whole table.
Usage context: {where_the_data_goes, e.g.: "publication on the website",
"internal report", "sharing with partners"}
For each column, decide:
- non_sensitive (not sensitive, can be used freely)
- moderate_sensitive (moderately sensitive, requires care)
- high_sensitive (highly sensitive, requires protection/removal)
Explain why for each.
Retrieve-then-Detect
Step 1 — Retrieve:
Here are the data sensitivity rules for {domain/region/industry}:
{paste_relevant_rules_or_policies}
Extract concrete criteria: which data types count as
low / moderate / high / severe sensitivity.
Step 2 — Detect:
Based on these rules, evaluate the sensitivity of the columns in the table:
{paste_table}
For each column:
1. Sensitivity level (low/moderate/high/severe)
2. A quote from the rules you based this on
3. Recommendation (can be published / needs masking / delete)
What to plug in:
{brief_table_description}— one sentence on the table's purpose ("customer contacts," "vendor list," "survey data"){paste_table_in_markdown}— 5-10 rows of the table in markdown format (copy from Excel via a converter, or ask the LLM to format it){where_the_data_goes}— usage context ("public release," "internal use only," "submission to a regulator"){domain/region/industry}— your context ("US healthcare," "fintech," "education," "humanitarian aid"){paste_relevant_rules}— the text of the policy/standard/regulation (GDPR, corporate policy, industry standard)
🚀 Quick start — paste into the chat:
Here is a Detect-then-Reflect template for checking data sensitivity in a table.
Adapt it to my task: {your task}.
Ask me questions one at a time to fill in the fields.
[paste the template above]
The LLM will ask: what your table is, where the data will go, and which sensitivity types matter. It will take the two-step structure and plug in your data — first finding what's potentially sensitive, then evaluating it in context.
Limitations
⚠️ Requires structured data: The method is built for tables. Unstructured text (documents, email threads) needs adapting — the model can look for sensitive fragments, but the "column in the context of a table" structure doesn't apply.
⚠️ The "usage context" is subjective: The same data can be sensitive or not depending on the purpose. The model evaluates based on your description of the context — describe it vaguely and the evaluation will be off. "For a report" — which one? Internal or public? Spell it out.
⚠️ Retrieve-then-Detect needs rules: The second mechanism only works if you can supply relevant rules/policies. Without them (a new industry, a unique case), the model falls back on general knowledge, which lowers accuracy. For standard domains (personal data, finance, healthcare) it works great.
⚠️ Not a substitute for legal review: The model gives a technical sensitivity assessment, but the final decision (whether you can publish, share, or store data) requires knowing the law (GDPR, CCPA, HIPAA, industry regulations). Use it as a first filter, not the final verdict.
Resources
Towards Contextual Sensitive Data Detection
GitHub: https://github.com/trl-lab/sensitive-data-detection
Liang Telkamp (University of Amsterdam), Madelon Hulsebos (Centrum Wiskunde & Informatica)
Built on: - GDPR (Article 4) for the definition of personal data - UN OCHA Information Sharing Protocols for humanitarian data - Contextual Integrity (Nissenbaum) — the theory of contextual privacy