关于 gdpr-compliant
面向开发者、架构师、DevOps 团队和技术负责人的 GDPR 工程参考,将隐私原则转化为软件实践。涵盖数据处理、API、日志、保留期限、安全措施和代码审查清单。
主要功能
- 01隐私保护设计工程指南
- 02数据最小化与保留实践
- 03API、日志和错误处理规则
- 04加密、密码与密钥管理建议
- 05面向 GDPR 的 PR 审查清单
适用场景
- 01审查处理个人数据的功能
- 02设计存储数据的保留与删除流程
- 03检查 API 和日志中的隐私风险
- 04为 GDPR 审查准备技术变更
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ github/ awesome-copilot --skill gdpr-compliant安装后在 Claude Code 中输入/gdpr-compliant确认已加载。
附带文件references/data-rights.mdreferences/Security.md
详细介绍
GDPR 工程技能
面向工程师、架构师、DevOps 和技术负责人的可操作 GDPR 参考。 灵感来自 CNIL 开发者指南以及 GDPR 第 5、25、32、33、35 条。
黄金法则: 少收集。少存储。少暴露。少保留。
如需深入了解,请阅读 references/ 中的参考文件:
references/data-rights.md— 用户权利端点、DSR 工作流、RoPAreferences/security.md— 加密、哈希、密钥、匿名化references/operations.md— 云、CI/CD、事件响应、架构模式
1. GDPR 核心原则(第 5 条)
| 原则 | 工程义务 |
|---|---|
| 合法性、公平性和透明性 | 在 RoPA 中记录每项处理活动的法律依据 |
| 目的限制 | 为目的 A 收集的数据不得在没有新法律依据的情况下复用于目的 B |
| 数据最小化 | 只收集当下有书面业务需求的字段 |
| 准确性 | 提供更新端点;将更正传播到下游存储 |
| 存储限制 | 在 schema 设计时定义 TTL —— 绝不要在之后 |
| 完整性和保密性 | 静态和传输中加密;限制并审计访问 |
| 问责制 | 保留合规证据;RoPA 随时可供 DPA 检查 |
2. 默认隐私与设计隐私
必须
- 在创建时向每个存储个人数据的表添加
CreatedAt、RetentionExpiresAt。 - 所有可选数据收集默认设为关闭。用户主动选择加入;他们绝不需要退出默认开启的设置。
- 在构建高风险处理(生物识别、健康数据、大规模画像、系统性监控)之前进行 DPIA。
- 每个引入处理活动的新功能都要更新 RoPA。
- 在数据流向任何子处理者之前与其签署 DPA。
不得
- 在没有书面法律依据的情况下发布新的数据收集功能。
- 在没有明确同意的情况下默认启用分析、跟踪或遥测。
- 将个人数据存储在 RoPA 中未列出的系统中。
3. 数据最小化
必须
- 将每个 DTO/model 字段映射到具体的业务需求。移除未记录的字段。
- 为创建、读取和更新使用单独的 DTO —— 绝不要复用同一个对象。
- 只返回调用者有权查看的内容 —— 使用响应投影。
- 在边缘屏蔽敏感值:卡号返回
****1234,绝不返回完整值。 - 从默认列表/搜索投影中排除敏感字段(出生日期、身份证号、健康信息)。
不得
- 如果请求/响应正文可能包含个人数据,不要记录完整正文。
- 在 URL 路径段或查询参数中包含个人数据(CDN 日志、浏览器历史记录)。
- 在没有明确法律依据的情况下收集
dateOfBirth、身份证号或健康数据。
4. 目的限制
必须
- 在代码注释和 RoPA 中记录每项处理活动的目的。
- 在将数据复用于次要目的之前,获取新的法律依据或进行兼容性分析。
不得
- 在没有明确同意的情况下,将为服务交付收集的个人数据与广告网络共享。
- 在没有单独法律依据和用户通知的情况下,使用支持工单内容训练 ML 模型。
5. 存储限制与保留
必须
- 每张存储个人数据的表必须有明确的保留期限。
- 通过定时任务(Hangfire、cron)自动执行保留策略——绝不能依赖手动流程。
- 保留期满后对数据匿名化或删除——绝不能将过期数据无声无息地留在生产环境中。
推荐默认值
| 数据类型 | 最长保留期限 |
|---|---|
| 身份验证 / 审计日志 | 12–24 个月 |
| 会话 / 刷新令牌 | 30–90 天 |
| 邮件 / 通知日志 | 6 个月 |
| 非活跃用户账户 | 最后登录后 12 个月 → 通知 → 删除 |
| 支付记录 | 按税法要求(7–10 年),并最小化存储 |
| 分析事件 | 13 个月 |
应当
- 添加
RetentionExpiresAt列——在插入时计算。 - 使用软删除(
DeletedAt),并在擦除请求窗口期(30 天)后通过定时任务执行硬删除。
绝不能
- 以"以后可能有用"为由无限期保留个人数据。
6. API 设计规则
必须
- 绝不能将个人数据包含在 URL 路径或查询参数中。
GET /users/{userId}
- 对所有返回或接收个人数据的端点进行身份验证。
- 从 JWT 中提取操作用户的身份——绝不能从请求体中提取。
- 对每个资源验证所有权:
if (resource.OwnerId != currentUserId) return 403。 - 使用 UUID 或不透明标识符——绝不能将连续整数用作公开资源 ID。
应当
- 对敏感端点(登录、数据导出、密码重置)进行速率限制。
- 设置
Referrer-Policy: no-referrer和明确的CORS允许列表。
绝不能
- 在 API 响应中返回堆栈跟踪、内部路径或数据库错误。
- 在需要身份验证的 API 上使用
Access-Control-Allow-Origin: *。
7. 日志记录规则
必须
- 对应用日志中的 IP 进行匿名化——屏蔽最后一个八位组(IPv4)或最后 80 位(IPv6)。
192.168.1.xxx
- 绝不能记录:密码、令牌、会话 ID、凭据、卡号、国民身份证号、健康数据。
- 绝不能记录可能包含 PII 的完整请求/响应体。
- 强制执行日志保留策略——在定义的期限后自动清除。
应当
- 记录事件而非数据:
"User {UserId} updated email"而非"Email changed from [email protected] to [email protected]"。 - 使用结构化日志(JSON),以
userId作为内部标识符,而非电子邮件地址。 - 将审计日志(敏感访问、管理员操作)与应用日志分开——不同的保留期限和 ACL。
8. 错误处理
必须
- 返回通用错误消息——绝不能暴露堆栈跟踪、内部路径或数据库错误。
"Column 'email' violates unique constraint on table 'users'""A user with this email address already exists."
- 对所有错误响应使用 Problem Details (RFC 7807)。
- 在服务端使用关联 ID 记录完整错误;仅向客户端返回关联 ID。
绝不能
- 在错误响应中包含文件路径、类名或行号。
- 在错误消息中包含个人数据(例如 "User [email protected] not found")。
9. 加密(概要——完整细节见 references/security.md)
| 范围 | 最低标准 |
|---|---|
| 标准个人数据 | AES-256 磁盘/卷加密 |
| 敏感数据(健康、财务、生物识别) | AES-256 列级加密 + 通过 KMS 的信封加密 |
| 传输中 | TLS 1.2+(优先 1.3);强制启用 HSTS |
| 密钥 | 基于 HSM 的 KMS;每年轮换 DEK |
绝不能允许 TLS 1.0/1.1、空密码套件或硬编码加密密钥。
10. 密码哈希
必须
- 使用 Argon2id(推荐)或 bcrypt(成本 ≥ 12)。绝不能使用 MD5、SHA-1 或 SHA-256。
- 为每个密码使用唯一的盐。仅存储哈希值。
绝不能
- 以任何形式记录密码。通过 URL 传输密码。以明文存储重置令牌。
11. 密钥管理
必须
- 将所有密钥存储在 KMS 中:Azure Key Vault、AWS Secrets Manager、GCP Secret Manager 或 HashiCorp Vault。
- 使用 pre-commit 钩子(
gitleaks、detect-secrets)防止密钥被提交。 - 在开发者离职、年度计划或疑似泄露时轮换密钥。
.gitignore 必须包含: .env、.env.*、*.pem、*.key、*.pfx、*.p12、secrets/
禁止
- 将密钥提交到源代码。将密钥存储为明文环境变量默认值。
12. 匿名化与假名化(摘要 — 参见 references/security.md)
- 匿名化 = 不可逆 → 不属于 GDPR 范围。用于擦除后需保留的记录。
- 假名化 = 可通过密钥逆转 → 仍属个人数据,风险降低。
- 擦除用户时,应匿名化必须保留的记录(财务、审计),而非删除它们。
- 将假名化密钥存储在 KMS 中 — 绝不能与假名化数据存放在同一数据库。
禁止在可通过关联攻击重新识别的情况下将数据称为"匿名化"。
13. 使用伪造数据进行测试
必须
- 禁止在开发、预发布或 CI 环境中使用生产个人数据。
- 禁止在未先清洗 PII 的情况下将生产数据库备份恢复到非生产环境。
- 使用合成数据生成器:
Bogus(.NET)、Faker(JS/Python/Ruby)。 - 所有测试电子邮件地址使用
@example.com。
14. 反模式
| 反模式 | 正确做法 |
|---|---|
| URL 中包含 PII | 使用不透明 UUID 作为公共标识符 |
| 记录完整请求体 | 仅记录结构化事件元数据 |
| "永久保留"模式 | 在设计时定义 TTL |
| 开发/测试中使用生产数据 | 合成数据 + 清洗管道 |
| 团队间共享凭据 | 个人账户 + RBAC |
| 硬编码密钥 | KMS + 密钥管理器 |
认证 API 上使用 Access-Control-Allow-Origin: * | 显式 CORS 允许列表 |
| 将同意与个人资料数据一起存储 | 专用同意存储 |
| GET 查询参数中包含 PII | POST 请求体或已认证会话 |
| 公共 URL 中使用连续整数 ID | UUID |
| 带准标识符的"匿名化"数据 | 应用 k-匿名性,测试关联抗性 |
| 备份区域混用至 EEA 以外 | 对备份任务实施明确的区域锁定 |
15. PR 审查清单
数据模型
- 每个新增 PII 列都有文档化的用途和保留期限。
- 敏感字段(健康、财务、国民身份证)使用列级加密。
- 公共标识符不使用连续整数主键。
API
- URL 路径或查询参数中不包含 PII。
- 所有返回个人数据的端点均已认证。
- 存在所有权检查 — 用户无法访问其他用户的资源。
- 对敏感端点应用速率限制。
日志
- 不记录密码、令牌或凭据。
- IP 已匿名化(掩码最后一段八位字节)。
- 在可能存在 PII 的情况下不记录完整请求/响应体。
基础设施
- 无公共存储桶或公共 IP 数据库。
- 新增云资源标记
DataClassification。 - 新增存储资源启用静态加密。
- 新增数据存储地理区域符合 EEA 要求或受 SCCs 覆盖。
密钥与 CI/CD
- 源代码或已提交配置文件中无密钥。
- 新增密钥已添加到 KMS 和密钥清单文档。
- CI/CD 密钥在管道日志中已掩码。
保留与擦除
- 保留执行作业或策略覆盖新增数据存储或字段。
- 擦除管道已更新以覆盖新增数据存储。
用户权利与治理
- 数据导出端点包含任何新的个人数据字段。
- 若引入新的处理活动,则更新 RoPA。
- 新的子处理者拥有已签署的 DPA 和 RoPA 条目。
- 若变更涉及高风险处理,则触发 DPIA。
黄金法则: 少收集。少存储。少暴露。少保留。
你未收集的每一个字节的个人数据,都是你不会丢失、 不会泄露、也不会被追究责任的字节。
灵感来自 CNIL 开发者 GDPR 指南、GDPR 第 5、25、32、33、35 条、 ENISA、OWASP 和 NIST 工程最佳实践。
评论
支持 Markdown