# Masking Pii Data

> Protect personally identifiable information in data pipelines — classifying PII, choosing masking vs tokenization vs hashing vs encryption, dynamic data masking and column-level access control, and handling deletion/right-to-be-forgotten. Use when handling sensitive data, masking or anonymizing PII, meeting GDPR/CCPA/HIPAA requirements, or restricting column access in a warehouse.

- Skill: `unknown-333/masking-pii-data` (Agent Skill)
- Install (CLI): `npx skillmds@latest add unknown-333/masking-pii-data`
- Raw SKILL.md: https://api.skillmd.com/api/skills/unknown-333/masking-pii-data/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: Unknown-333 (https://skillmd.com/u/unknown-333)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/unknown-333/masking-pii-data

---


# Masking PII Data

## When to use

- A pipeline or table contains personal/sensitive data (names, emails, SSNs,
  payment, health).
- Choosing how to de-identify data for analytics or lower environments.
- Restricting who can see raw sensitive columns.
- Handling deletion / right-to-be-forgotten requests.
- Do NOT use for general access control unrelated to sensitive data.

## Choose the right technique

| Technique           | Reversible      | Keeps analytics utility | Use for                               |
| ------------------- | --------------- | ----------------------- | ------------------------------------- |
| Masking / redaction | No              | Low                     | Display, lower envs (`j***@x.com`)    |
| Hashing (salted)    | No              | Join/match only         | Pseudonymous keys, dedup              |
| Tokenization        | Yes (via vault) | Referential joins       | Reversible pseudonymization           |
| Encryption          | Yes (with key)  | None until decrypt      | At-rest protection, restricted fields |

## Workflow

```
- [ ] Classify columns: what is PII/sensitive and its risk level
- [ ] Pick technique per column by whether you need reversibility/joins
- [ ] Apply as early as possible (mask on ingest for lower environments)
- [ ] Enforce column-level access / dynamic masking for raw data
- [ ] Support deletion: know every location a subject's data lives
```

1. **Classify first.** You can't protect what you haven't identified; tag columns
   by sensitivity. Pair with `designing-data-contracts` to declare PII fields.
2. **Pick per column.** Need to join across systems but not reverse? Salted hash.
   Need to recover the value later? Tokenization/encryption. Just hide it? Mask.
3. **Apply early.** Mask/tokenize before data reaches analysts or dev/test
   environments; never copy raw PII into lower environments.
4. **Access control.** Use warehouse dynamic data masking and column-level grants
   so only authorized roles see raw values.
5. **Deletion.** Track where each subject's data lives (lineage helps) so
   erasure requests are complete.

## Patterns

**Snowflake dynamic masking policy** (unmask only for a privileged role):

```sql
CREATE MASKING POLICY email_mask AS (val string) RETURNS string ->
  CASE WHEN CURRENT_ROLE() IN ('PII_READER') THEN val
       ELSE REGEXP_REPLACE(val, '^[^@]+', '***') END;
ALTER TABLE customers MODIFY COLUMN email SET MASKING POLICY email_mask;
```

**Salted hash for pseudonymous joins** — hash with a secret salt so the same
person matches across tables without exposing the raw identifier; keep the salt in
a secrets manager.

**Tokenization** — replace the value with a token and store the mapping in a
restricted vault; analytics use the token, authorized systems detokenize.

## Common pitfalls

- **Copying raw PII to dev/test** — the most common leak; mask on the way down.
- **Unsalted hashes** — vulnerable to rainbow tables and re-identification; always
  salt.
- **Masking at display only** while storing raw everywhere — breach still exposes
  data; protect at rest and restrict access.
- **Forgetting free-text/logs** — PII hides in comments, logs, and JSON blobs, not
  just typed columns.
- **No deletion plan** — right-to-be-forgotten fails if you can't locate all
  copies; use lineage.
- **Reversible where you meant irreversible** — don't tokenize when the requirement
  is true anonymization.

