Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Data Protection Patterns

ASecurity

Technical patterns for anonymization, pseudonymization, field-level encryption, data minimization, consent management, and data subject request automation, with the difference between anonymous and pseudonymous data. Use when implementing privacy controls in code or data pipelines.

4 stars
0 votes
0 copies
0 views
Added 10/1/2026
securitypythongoawsgcpazureapidatabase

Works with

api

Security Analysis

A100/100

Scanned 10/1/2026

$npx -y skills add HermeticOrmus/LibreSecOps-Claude-Code --skill data-protection-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Data Protection Patterns?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Data Protection Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hermeticormus-data-protection-patterns/badge)](https://www.skillsdirectory.com/skills/hermeticormus-data-protection-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: "data-protection-patterns"
description: "Technical patterns for anonymization, pseudonymization, field-level encryption, data minimization, consent management, and data subject request automation, with the difference between anonymous and pseudonymous data. Use when implementing privacy controls in code or data pipelines."
---

# Data Protection Patterns

> Technical patterns for anonymization, pseudonymization, encryption, data minimization, and consent management in software systems.

## Knowledge Base

### Anonymization vs Pseudonymization

This distinction has significant regulatory consequences. Truly anonymous data is outside the scope of GDPR. Pseudonymous data remains personal data under GDPR, just with reduced risk.

**Anonymization** (irreversible -- removes data from regulation scope):
- No one, including the data controller, can re-identify individuals
- Must resist: singling out, linkability, and inference attacks
- Techniques: aggregation, generalization, suppression, noise addition
- Test: Could this data be combined with any other reasonably available dataset to identify an individual?

**Pseudonymization** (reversible -- reduces risk but remains personal data):
- The data controller can re-identify using a separately stored key/mapping
- Reduces risk of unauthorized re-identification
- Techniques: tokenization, hashing with salt, encryption
- Benefit: Reduced obligations in some GDPR contexts (Article 6(4)(e), Article 32, Recital 29)

### Anonymization Techniques

**k-Anonymity**: Each record is indistinguishable from at least k-1 other records with respect to quasi-identifiers.

```
# Before (k=1, each record unique on age+zip)
| Age | Zip   | Diagnosis |
|-----|-------|-----------|
| 28  | 10001 | Flu       |
| 29  | 10002 | Diabetes  |
| 35  | 10005 | Flu       |

# After k-anonymity (k=2, generalize age and zip)
| Age   | Zip   | Diagnosis |
|-------|-------|-----------|
| 25-30 | 1000* | Flu       |
| 25-30 | 1000* | Diabetes  |
| 35-40 | 1000* | Flu       |
```

Limitation: k-anonymity does not protect against attribute disclosure if all records in a group share the same sensitive value.

**l-Diversity**: Extends k-anonymity by requiring that each equivalence class has at least l well-represented values for the sensitive attribute.

**t-Closeness**: Extends l-diversity by requiring that the distribution of the sensitive attribute within each equivalence class is close to the distribution in the overall dataset.

**Differential Privacy**: Adds calibrated noise to query results or data so that the presence or absence of any individual record does not significantly affect the output.

```python
# Simplified differential privacy for count queries
import numpy as np

def dp_count(true_count, epsilon=1.0):
    """Add Laplace noise to a count query for differential privacy."""
    noise = np.random.laplace(0, 1/epsilon)
    return max(0, int(true_count + noise))

# epsilon controls privacy/utility tradeoff:
# Lower epsilon = more privacy, more noise
# Higher epsilon = less privacy, more accurate
```

**Data masking**: Replacing identifying portions of data with realistic but non-identifying values.

```python
# Email masking: j***@example.com
def mask_email(email):
    local, domain = email.split('@')
    return f"{local[0]}{'*' * (len(local)-1)}@{domain}"

# Phone masking: ***-***-1234
def mask_phone(phone):
    return f"***-***-{phone[-4:]}"

# Name masking: J*** D**
def mask_name(name):
    parts = name.split()
    return ' '.join(f"{p[0]}{'*' * (len(p)-1)}" for p in parts)
```

### Pseudonymization Techniques

**Tokenization**: Replace identifiers with random tokens. Store the mapping separately.

```python
import secrets

class Tokenizer:
    def __init__(self):
        self.token_map = {}  # Stored separately from tokenized data
        self.reverse_map = {}

    def tokenize(self, identifier):
        if identifier not in self.token_map:
            token = secrets.token_hex(16)
            self.token_map[identifier] = token
            self.reverse_map[token] = identifier
        return self.token_map[identifier]

    def detokenize(self, token):
        return self.reverse_map.get(token)
```

**Format-preserving encryption (FPE)**: Encrypt data while maintaining the original format (useful for systems that validate format).

```python
# Concept: SSN 123-45-6789 encrypts to 987-65-4321
# Same format, but the value is encrypted
# Use FF1 or FF3-1 algorithms (NIST SP 800-38G)
```

**Keyed hashing (HMAC)**: One-way pseudonymization using HMAC. Cannot be reversed without brute-forcing the input space.

```python
import hmac
import hashlib

def pseudonymize(identifier, key):
    """One-way pseudonymization using HMAC-SHA256."""
    return hmac.new(key, identifier.encode(), hashlib.sha256).hexdigest()

# Same identifier always maps to same pseudonym (with same key)
# Different key produces different pseudonyms
# Cannot reverse without the original identifier
```

### Encryption Patterns

**Field-level encryption**: Encrypt individual fields containing sensitive personal data rather than (or in addition to) full database encryption.

```python
from cryptography.fernet import Fernet

class FieldEncryptor:
    def __init__(self, key):
        self.cipher = Fernet(key)

    def encrypt_field(self, plaintext):
        return self.cipher.encrypt(plaintext.encode()).decode()

    def decrypt_field(self, ciphertext):
        return self.cipher.decrypt(ciphertext.encode()).decode()

# Usage in ORM
class User(Model):
    id = Column(UUID, primary_key=True)
    email_encrypted = Column(Text)      # Encrypted
    name_encrypted = Column(Text)       # Encrypted
    email_hash = Column(Text, index=True)  # For lookups (HMAC)
    created_at = Column(DateTime)       # Not encrypted (not PII)
```

**Envelope encryption**: Use a data encryption key (DEK) to encrypt data, then encrypt the DEK with a key encryption key (KEK) stored in a key management service (AWS KMS, Azure Key Vault, GCP KMS).

**Cryptographic erasure**: Instead of finding and deleting every copy of a user's data (which is hard with backups, caches, logs), destroy the encryption key. All encrypted data becomes permanently unreadable.

### Consent Management

**Technical implementation**:

```python
class ConsentRecord:
    user_id: str
    purpose: str           # Specific processing purpose
    granted: bool
    granted_at: datetime
    withdrawn_at: datetime | None
    method: str            # "web_form", "api", "verbal"
    version: str           # Consent text version
    evidence: str          # Proof of consent (form snapshot, recording ID)

class ConsentManager:
    def check_consent(self, user_id, purpose):
        """Check if user has active consent for a specific purpose."""
        record = get_latest_consent(user_id, purpose)
        return record and record.granted and not record.withdrawn_at

    def grant_consent(self, user_id, purpose, method, version):
        """Record consent grant with full audit trail."""
        store_consent(ConsentRecord(
            user_id=user_id,
            purpose=purpose,
            granted=True,
            granted_at=now(),
            method=method,
            version=version
        ))

    def withdraw_consent(self, user_id, purpose):
        """Record consent withdrawal. Must be as easy as granting."""
        record = get_latest_consent(user_id, purpose)
        record.withdrawn_at = now()
        update_consent(record)
        # Trigger downstream: stop processing, queue data deletion
        trigger_consent_withdrawal_workflow(user_id, purpose)
```

**Consent receipts** (Kantara Initiative):
Machine-readable records of consent that can be verified by both parties.

### Data Subject Request Automation

**Right to Access (Article 15)**:
```python
def handle_access_request(user_id):
    """Generate a data export for DSAR."""
    data = {
        'personal_data': get_all_user_data(user_id),
        'purposes': get_processing_purposes(user_id),
        'recipients': get_data_sharing_partners(user_id),
        'retention': get_retention_periods(user_id),
        'source': get_data_sources(user_id),
        'automated_decisions': get_automated_decisions(user_id),
        'generated_at': datetime.utcnow().isoformat()
    }
    return export_as_json(data)  # Machine-readable format
```

**Right to Erasure (Article 17)**:
```python
def handle_erasure_request(user_id):
    """Delete all personal data for a user."""
    # Check for legal retention obligations first
    if has_legal_retention_obligation(user_id):
        return restrict_processing(user_id)  # Restrict instead of delete

    # Delete from all storage locations
    delete_from_primary_database(user_id)
    delete_from_search_index(user_id)
    delete_from_cache(user_id)
    delete_from_file_storage(user_id)
    anonymize_in_analytics(user_id)
    notify_processors_to_delete(user_id)  # Third-party processors

    # Cryptographic erasure for encrypted data in backups
    destroy_user_encryption_key(user_id)

    # Audit trail (record that deletion occurred, not what was deleted)
    log_erasure_completed(user_id)
```

## Patterns

### Pattern: Data Minimization by Architecture
Design systems so that components only have access to the personal data they need. The analytics service receives pseudonymous IDs, not names. The email service receives email addresses but not browsing history. This is structural data minimization.

### Pattern: Retention by Design
Implement automatic retention enforcement in the data layer, not as a manual process. Use TTL (time-to-live) fields, scheduled cleanup jobs, and cryptographic erasure so that data expires automatically.

### Pattern: Privacy-Preserving Analytics
Use aggregated, anonymized, or differentially private analytics instead of individual-level tracking. Most business questions ("How many users completed onboarding?") do not require individual-level data.

## Anti-Patterns

- **Anonymization that is not anonymous**: Removing names and emails but leaving IP addresses, timestamps, and behavioral patterns that enable re-identification through linkage
- **Consent dark patterns**: Making "Accept All" prominent and colorful while hiding "Manage Preferences" in small gray text
- **Backup blind spot**: Deleting data from production but leaving it indefinitely in backups, defeating the purpose of erasure
- **Encryption key shared across all users**: Using one encryption key for all user data means you cannot cryptographically erase one user's data without destroying everyone's
- **Logging personal data**: Writing personal data to application logs, which are then stored for months in log aggregators without encryption or retention controls

## References

- GDPR Full Text -- https://gdpr-info.eu/
- Article 29 Working Party -- Opinion on Anonymisation Techniques (WP216)
- ENISA -- Pseudonymisation techniques and best practices -- https://www.enisa.europa.eu/publications/pseudonymisation-techniques-and-best-practices
- NIST Privacy Framework -- https://www.nist.gov/privacy-framework
- Differential Privacy by Cynthia Dwork -- foundational research
- Kantara Initiative Consent Receipt Specification -- https://kantarainitiative.org/
- ICO Anonymisation Code of Practice -- https://ico.org.uk/media/for-organisations/documents/1061/anonymisation-code.pdf
- CNIL DPIA Guidelines -- https://www.cnil.fr/en/guidelines-dpia

Attribution

HermeticOrmusHermeticOrmus
View sourceSee grades on GitHubMore from HermeticOrmus →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Security Review

Use this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment/sensitive features. Provides comprehensive security checklist and patterns.

2456590 votes

Springboot Security

Java Spring Boot 服务中关于身份验证/授权、验证、CSRF、密钥、标头、速率限制和依赖安全的 Spring Security 最佳实践。

2456590 votes

Summarize Status

Write a short, colloquial summary for a Paperclip summary slot: open with the 1–3 specific, concrete actions the reader needs to take right now to unblock the work, then a brief plain-language status, streaming progress as it works.

953190 votes

Paperclip Task Bridge

Create, comment on, update, and list Paperclip tasks from Hermes using scoped Paperclip API credentials.

953190 votes

Paperclip Evals

Choose, inspect, validate, and report Paperclip Runner or Product E2E evaluations while preserving evidence, provenance, cost, and failure classification.

953190 votes
View all in security →