imohad/pdpl-scanner

GitHub: imohad/pdpl-scanner

面向沙特 PDPL 法规的实体感知合规扫描器,在 CI 中自动检测跨境数据流、加密缺陷、日志泄露等代码层违规并生成双语报告。

Stars: 7 | Forks: 1

# PDPL 扫描器 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/imohad/pdpl-scanner/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/pdpl-scanner.svg)](https://pypi.org/project/pdpl-scanner/) [![Python](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) [![欢迎提交 PR](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) **针对沙特阿拉伯《个人数据保护法》(PDPL)的实体感知合规扫描器。** 将其放入任何项目的 CI 中,即可扫描代码是否存在 PDPL 违规行为,并据此拦截合并。它能发现通用隐私 linter 遗漏的问题,因为沙特的合规性并非单一的规则手册:托管和驻留规则以及监管机构的叠加要求会根据*实体是谁*以及*它处理什么数据*而变化。对于私营 SaaS 来说仅仅是“修复你的安全防护”的跨境数据流,对于受 SAMA 监管的银行或政府实体来说,实际上是**被禁止的**。这个扫描器知道其中的区别。 **[العربية ↓](#نظرة-عامة-بالعربية)** — 完整的阿拉伯语指南位于本文件底部。 ## 演示 以**受 SAMA 监管的金融实体**身份扫描一个小应用(`pdpl-scan ./src --entity financial --show-pass`): ``` PDPL scan — entity=financial class=confidential residency=prohibited_without_approval Files scanned: 3 | Score: 3/100 | Gate: FAIL Findings: critical=3 high=3 medium=1 | leads=2 | manual-verify=9 [CRITICAL] FAIL PDPL-CB-01 api.js:6 Personal data flows to a non-KSA region/endpoint [CRITICAL] FAIL PDPL-SEC-03 api.js:7 Hardcoded secret / credential in source [CRITICAL] FAIL PDPL-SEC-01 api.js:8 TLS verification disabled / plaintext transport [HIGH ] FAIL PDPL-LB-03 signup.jsx:1 Pre-ticked / default-on consent [HIGH ] FAIL PDPL-LOG-01 api.js:4 Personal/sensitive data written to logs [HIGH ] LEAD PDPL-DSR-01 (repo-wide) No data-access / export path for data subjects [MEDIUM ] LEAD PDPL-RET-01 (repo-wide) No retention limit / purge logic Auto-checks passed: PDPL-CB-02, PDPL-SEC-02, PDPL-SEC-05 Manual-verify (confirm with DPO/legal): [ ] SAMA-CLOUD-01 SAMA approval before cloud use / any cloud outside the Kingdom [ ] SAMA-RESID-01 Highly sensitive financial data resides in-Kingdom + in-Kingdom key mgmt [ ] NCA-ECC-01 Information hosting and storage inside the Kingdom (ECC 4.2.3.3) ... +6 more ``` `FAIL` = 确认的自动发现(用于拦截构建) · `LEAD` = 高召回率的辅助排查线索。 对相同的目录树运行 `--entity private_general`,跨境判决定从*禁止*降级为 *在具备安全防护下允许*,并且 SAMA/NCA 的义务也会消失。添加 `--markdown report.md`、 `--html report.html` 或 `--sarif results.sarif` 以生成可共享的产物。 ## 它的功能 - **扫描代码和配置**以查找技术性的 PDPL 违规行为:跨境数据流、缺失/禁用的加密、硬编码的密钥、日志中的个人数据、默认勾选的同意、弱哈希、缺失的数据主体权利路径、仅软删除的擦除、无保留期限限制、对敏感数据处理不当。 - **识别沙特标识符**:国民 ID、Iqama(居留证)、沙特手机号(`+9665…` / `05…`)、沙特 IBAN 以及阿拉伯语字段名。这正是通用扫描器的盲区。 - **根据实体进行调整**:通过交互式问卷(或提交的 `pdpl.config.yaml`)设置实体类型和数据分类,这会重新加权发现结果,并呈现正确的行业义务(SAMA、NDMO、CST、NCA、医疗健康)。 - **区分可证明与不可证明的内容**:代码可检测的控制措施返回真实的 PASS/FAIL;组织义务(SDAIA 注册、DPO、RoPA、处理者合同、DPIA、72 小时违规响应手册)作为**手动验证清单**呈现,绝不蒙混过关。 - **与 GitHub 原生集成**:输出 SARIF,使得发现结果可以直接显示在 Security(安全)选项卡和 Pull Request 的内联评论中。 ### 它不包含什么 这是一个**工程层**扫描器。它**不是 PDPL 合规的法律认证**,也不能替代 SDAIA 注册、DPIA、行业审批或法律审查。一次干净的扫描只代表你的代码是干净的,并不意味着你的组织是合规的。手动验证清单的存在,正是为了避免将一份绿色的报告误认为是健康状态的全面合格证明。 ## 快速开始 ### 选项 A — GitHub Action(推荐) 添加 `.github/workflows/pdpl-scan.yml`(在 [`examples/pdpl-scan.yml`](examples/pdpl-scan.yml) 中有一个可直接复制的版本): ``` name: PDPL Compliance on: [push, pull_request] permissions: contents: read security-events: write jobs: pdpl-scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: imohad/pdpl-scanner@v1 with: entity: "financial" # or commit a pdpl.config.yaml instead fail-on: "critical" ``` 发现结果将出现在 Security 选项卡和 PR 中。如果存在严重违规,构建将会失败。 ### 选项 B — CLI ``` pip install pdpl-scanner # or: pip install git+https://github.com/imohad/pdpl-scanner pdpl-scan init # interactive questionnaire -> pdpl.config.yaml pdpl-scan . # scan using that config ``` 无需配置直接运行: ``` pdpl-scan ./src --entity health --fail-on critical,high --show-pass \ --json findings.json --sarif results.sarif --markdown report.md --html report.html ``` 当拦截失败时,退出码为非零,因此它可以直接在开箱即用的状态下拦截 CI。`--html` 会生成一份 自包含的双语报告,你可以直接交给 DPO/法务团队;`--show-pass` 还会列出所有已评估并返回正常结果的自动控制项。 ### 选项 D — pre-commit ``` # .pre-commit-config.yaml repos: - repo: https://github.com/imohad/pdpl-scanner rev: v1.1.0 hooks: - id: pdpl-scan args: [".", "--fail-on", "critical"] ``` ### 选项 C — 作为库使用 ``` from pdpl_scanner import scan, EntityProfile from pdpl_scanner.report import to_markdown profile = EntityProfile(type="financial", cross_border_transfers=True, processes_sensitive_data=True) result = scan("./src", profile=profile) print(result.gate, result.score) print(to_markdown(result)) ``` ## 实体类型及其重要性 问卷会询问你的身份。该答案会改变数据驻留判定和适用义务: | 实体类型 | 监管机构叠加要求 | 范围内个人数据的驻存姿态 | |---|---|---| | `government`(政府) | NDMO + NCA ECC | **未经批准禁止** — 必须留在王国境内;受分类驱动 | | `financial`(金融) | SAMA + NCA ECC | **未经批准禁止** — 上云前必须获得 SAMA 批准,明确禁止使用沙特境外的任何云 | | `critical_infrastructure`(关键基础设施) | NCA ECC + CCC | **未经批准禁止** — 必须在王国境内托管 (ECC 4.2.3.3) | | `health`(医疗健康) | MOH / Saudi Health Council + SFDA | **默认必须在王国境内** — 健康数据属于敏感数据;适用 HIE 控制措施 | | `telecom`(电信) / `cloud_provider`(云提供商) | CST CCRF | **默认必须在王国境内** — 沙特政府内容绝不能离开王国 | | `private_general`(一般私营) / `nonprofit`(非营利) | PDPL 基础要求 | **在具备安全防护下允许** — 需要合法依据 + SCCs/充分性认定/例外情况 + 转移风险评估 | NDMO 数据分类(`top_secret` / `secret` / `confidential` / `public`)进一步收紧了驻留要求:无论实体类型如何,任何被归类为 `secret` 或更高级别的数据都必须保留在王国境内。 因此,相同的数据流会产生不同的判定。对于一家银行而言,将客户数据传输到 `eu-west-1` 的代码属于**严重 (critical)** 发现,补救措施为“必须驻留在王国境内,并获取 SAMA 批准”。对于私营 SaaS 而言,这属于**高 (high)** 发现,补救措施为“确认你的传输安全防护”。扫描器会自动为你计算这些。 完整细分请参阅 [`docs/entity-types.md`](docs/entity-types.md)。 ## 控制措施 该目录将每项 PDPL 义务映射到一种检测模式。重点如下: | 领域 | 示例控制措施 | 模式 | |---|---|---| | 跨境传输 | `PDPL-CB-01` 数据离开沙特、`CB-02` 外国第三方处理者(感知实体严重性) | auto(自动) | | 安全防护 | `PDPL-SEC-01` TLS 关闭、`SEC-02` 数据库 TLS 禁用、`SEC-03` 密钥、`SEC-05` 哈希 | auto(自动) | | 日志与暴露 | `PDPL-LOG-01` 日志中的个人数据 | auto(自动) | | 法律依据与同意 | `PDPL-LB-03` 默认勾选同意(自动)、`LB-01` 同意拦截(辅助) | auto / assisted(自动 / 辅助) | | 数据主体权利 | `PDPL-DSR-01` 访问/导出、`DSR-02` 真实擦除 | assisted(辅助) | | 敏感数据 | `PDPL-SEN-01` 升级处理 | assisted(辅助) | | 保留期限 | `PDPL-RET-01` 保留限制 | assisted(辅助) | | 治理与记录 | `PDPL-GOV-02..07`、`BR-01` 72小时违规响应 | manual(手动) | `auto` 控制措施会生成确认的 **FAIL**(用于拦截构建),并附带文件:行号证据。`assisted` 控制措施会生成高召回率的 **LEAD** —— 即一种**永远不会单独导致拦截失败**的 `WARN`,最适合由人工或内置的 Claude 技能进行筛查。`manual` 控制措施是属于组织层面的义务,呈现出来供人确认。完整的机器可读目录:[`controls/pdpl-controls.yaml`](controls/pdpl-controls.yaml)。人类可读版本:[`docs/controls-catalog.md`](docs/controls-catalog.md)。 ### 调整噪音:抑制规则 高召回率的规则会显示你已经处理过的排查线索。有三种方法可以静音它们: ``` db_url = "postgres://app:pw@host/db" # pdpl-ignore[PDPL-SEC-03] ← one control on this line legacy_call() # pdpl-ignore ← all controls (covers the line below too) ``` ``` # .pdplignore(位于扫描根目录,gitignore 风格的 globs) tests/fixtures/** **/*.generated.* ``` …或使用 `--exclude ''`(可多次重复)。明显的占位符/默认密钥(`changeme`、`your_password`) 会被自动降级为中等程度的线索,这样配置模板就不会导致拦截失败。 ## 配置 `pdpl.config.yaml`(由 `pdpl-scan init` 生成): ``` entity: type: financial data_classification: confidential # top_secret | secret | confidential | public is_public_entity: false processes_sensitive_data: true processes_children_data: false cross_border_transfers: true large_scale_processing: true uses_ai_on_personal_data: false scan: paths: ["src"] exclude: ["tests", "node_modules", "dist", "build"] gate: fail_on: [critical] weights: { critical: 25, high: 10, medium: 4, low: 1 } ``` 提交它,这样每次扫描和每位贡献者都会使用相同的配置档案。 ## AI 增强审查(可选 Claude 技能) 该仓库在 [`skill/`](skill/) 中内置了一个 Claude 技能。确定性 CLI 在设计上具有高召回率;该技能增加了一个筛查层,在上下文中打开每个候选发现项,剔除误报,编写双语报告,并针对你的实体量身定制补救措施。将 Claude Code 指向 `skill/SKILL.md`,或者安装该技能,然后要求它对你更改的路径运行 PDPL 审查。如果没有它,CLI 也能完全独立运行。 ## 范围、准确性与免责声明 PDPL 的《实施条例》在 2025–2026 年期间处于修订状态,且 SDAIA 会发布补充指南(例如 2025 年的 AI 采用框架)。本工具中的条款引用是一份工作用映射图,并非最终的法律定论。本项目按“原样”基于 MIT 许可协议提供,**不构成法律建议**。请务必将重大决策与 SDAIA 当前的[法规和政策](https://sdaia.gov.sa/en/SDAIA/about/Pages/RegulationsAndPolicies.aspx)以及你自己的法律顾问进行核对。监管信息来源列于 [`docs/regulatory-references.md`](docs/regulatory-references.md) 中。 ## 保持规则最新 PDPL 及其行业叠加要求在不断变化。《实施条例》在 2025–2026 年期间处于修订状态, 且 SDAIA/NDMO/CST/NCA/SAMA 及卫生主管部门会发布更新。因此,扫描器会在每份报告上 加盖其规则最后审查的日期(位于 [`pdpl_scanner/_meta.py`](pdpl_scanner/_meta.py) 的 `RULES_LAST_UPDATED`),并在该日期过期时发出警告。 ``` pdpl-scan update # shows freshness status and the refresh workflow ``` 刷新是一个刻意的研究步骤,而不是静默的自动更新。请使用内置 Claude 技能的 **update mode**(或直接要求 Claude)研究自该日期以来监管机构发布的最新变更,将其应用于规则, 为每项变更注明来源,并更新日期。**你有 责任定期重新验证合规性。** 本目录的初始内容截至其发布之日为最新。将此之后的任何内容视为需要刷新。 ## 许可证 MIT — 请参阅 [`LICENSE`](LICENSE)。
## 阿拉伯语概述 **فاحص امتثال لنظام حماية البيانات الشخصية السعودي (PDPL)، يدرك نوع الجهة.** ضعه في خط التكامل المستمر (CI) لأي مشروع ليفحص الكود بحثاً عن مخالفات النظام ويمنع الدمج عند وجودها. يلتقط ما تعجز عنه أدوات الخصوصية العامة، لأن الامتثال في المملكة ليس كتاباً واحداً: قواعد الاستضافة والإقامة وطبقات الجهات الرقابية تختلف حسب **من هي الجهة** و**أي بيانات تعالج**. تدفّق بيانات خارج المملكة قد يكون "صحّح ضماناتك" لشركة خاصة، لكنه **محظور فعلياً** على بنك خاضع لساما أو جهة حكومية. هذه الأداة تفرّق بينهما. ### 它的作用是什么 تفحص الكود والإعدادات بحثاً عن: تدفّق بيانات خارج المملكة، تشفير معطّل أو غائب، أسرار مضمّنة في الكود، بيانات شخصية في السجلات، موافقة مفعّلة افتراضياً، تجزئة ضعيفة، غياب وسائل حقوق صاحب البيانات، حذف وهمي، وعدم وجود مدة احتفاظ. وتعرف المعرّفات السعودية: الهوية الوطنية، الإقامة، الجوال السعودي، الآيبان السعودي، وأسماء الحقول العربية.فصل ما تستطيع إثباته من الكود (نجاح/فشل حقيقي) عن الالتزامات التنظيمية (التسجيل في سدايا، مسؤول حماية البيانات، سجل المعالجة، تقييم الأثر، إجراء الإخطار خلال ٧٢ ساعة) التي تعرضها كقائمة **تحقق يدوي**، فلا يُفهَم الفحص الأخضر على أنه شهادة امتثال. ### 它不是什么 هذا فاحص **للطبقة الهندسية**، وليس شهادة امتثال نظامية، ولا يغني عن التسجيل في سدايا أو تقييم الأثر أو موافقات الجهات القطاعية أو المراجعة النظامية. الفحص النظيف يعني أن كودك نظيف، لا أن جهتك ممتثلة. ### 快速开始 ``` pip install pdpl-scanner pdpl-scan init # استبيان نوع الجهة ينشئ ملف pdpl.config.yaml pdpl-scan . # فحص باستخدام الملف pdpl-scan update # حالة حداثة القواعد وكيفية تحديثها ``` أو عبر GitHub Action: أضف الإجراء في `.github/workflows` فتظهر النتائج في تبويب الأمان وعلى طلبات الدمج، ويرسب البناء عند وجود مخالفة حرجة. **مخرجات وضبط الضجيج:** تنتج الأداة تقارير JSON وMarkdown وHTML (ثنائية اللغة) وSARIF. الملاحظات المؤكدة (`FAIL`) تكسر البوابة، أما الإشارات عالية الاسترجاع (`LEAD`) فلا تكسرها وحدها وتحتاج مراجعة بشرية. لإسكات ملاحظة عالجتها: أضف `# pdpl-ignore[PDPL-SEC-03]` في السطر، أو ملف `.pdplignore`، أو `--exclude`. وتُخفَّض الأسرار الافتراضية الواضحة (مثل `changeme`) تلقائياً إلى إشارة متوسطة بدل كسر البوابة. ### 主体类型决定裁决 | الجهة | الإقامة | حكم تدفّق البيانات خارج المملكة | |---|---|---| | حكومية / مالية (ساما) / بنية تحتية حساسة | محظور دون موافقة | حرج | | صحية / اتصالات / مزود سحابي | داخل المملكة افتراضياً | عالٍ | | خاص عام / غير ربحي | مسموح بضمانات | عالٍ قابل للمعالجة | وتصنيف بيانات NDMO يشدّد أكثر: أي شيء "سري" فأعلى يبقى داخل المملكة مهما كان نوع الجهة. ### 免责声明与更新 **هذه الأداة مساعِدة، وليست بديلاً عن التدقيق اليدوي ولا استشارة نظامية.** أكمل دائماً قائمة التحقق اليدوي وراجع القرارات الحساسة مع مسؤول حماية البيانات والفريق النظامي. والأنظمة تتغيّر: القواعد محدّثة حتى التاريخ المسجّل في `pdpl_scanner/_meta.py` والظاهر في كل تقرير. **مسؤوليتك إعادة التحقق دورياً** عبر `pdpl-scan update` أو بطلب البحث والتحديث من سكيل كلود المرفق. التفاصيل في [DISCLAIMER.md](DISCLAIMER.md).
标签:PDPL, Python, SARIF, 代码分析, 凭证管理, 合规扫描器, 数据隐私, 无后门, 逆向工具