# 9.3 敏感信息保护

防止隐私和机密信息通过 LLM 泄露是重要的安全要求。

## 9.3.1 敏感信息类型

需要保护的敏感信息包括：

| 类型          | 示例         | 风险    |
| ----------- | ---------- | ----- |
| 个人身份信息（PII） | 姓名、身份证、电话  | 隐私泄露  |
| 认证凭据        | 密码、API Key | 账户安全  |
| 业务机密        | 内部文档、策略    | 商业损失  |
| 系统信息        | 配置、架构      | 被攻击利用 |

## 9.3.2 输入侧脱敏

在输入进入 LLM 前进行脱敏：

```python
import re
import secrets

class InputSanitizer:
    def __init__(self):
        self.patterns = {
            'email': r'\b[\w.-]+@[\w.-]+\.\w+\b',
            'phone': r'\b\d{11}\b|\b\d{3}-\d{4}-\d{4}\b',
            'id_card': r'\b(?:\d{18}|\d{17}[0-9Xx])\b',
            'credit_card': r'\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b',
        }

    def sanitize(self, text: str) -> tuple[str, dict]:
        mappings = {}
        sanitized = text

        for pii_type, pattern in self.patterns.items():
            matches = re.findall(pattern, text)
            for i, match in enumerate(matches):
                token = secrets.token_urlsafe(12)
                placeholder = f"[PII:{pii_type.upper()}:{i}:{token}]"
                mappings[placeholder] = {
                    "value": match,
                    "type": pii_type,
                    "origin": "input_sanitizer",
                }
                sanitized = sanitized.replace(match, placeholder)

        return sanitized, mappings

    def restore(
        self,
        text: str,
        mappings: dict,
        allowed_placeholders: set[str],
    ) -> str:
        """只在确定性允许的输出字段中还原占位符。"""
        restored = text
        for placeholder in allowed_placeholders:
            if placeholder not in mappings:
                raise ValueError(f"Unexpected placeholder: {placeholder}")
            restored = restored.replace(
                placeholder,
                mappings[placeholder]["value"],
            )

        # 还原后仍需独立 DLP/凭据扫描；模型输出中的伪造占位符不应被还原。
        if re.search(r"\[PII:[A-Z_]+:\d+:[A-Za-z0-9_-]+\]", restored):
            raise ValueError("Unapproved PII placeholder in model output")
        return restored
```

## 9.3.3 输出侧过滤

检测并过滤输出中的敏感信息：

{% @mermaid/diagram content="flowchart TB
A\["模型输出"] --> B\["PII 检测"]
B --> C\["凭据检测"]
C --> D\["机密检测"]
D --> E{"发现敏感信息?"}
E --> |是| F\["脱敏/过滤"]
E --> |否| G\["原样输出"]
F --> G" %}

图 9-5：输出侧过滤流程图

**检测实现**

```python
class OutputPIIFilter:
    def filter(self, output: str) -> str:
        filtered = output

        # 正则匹配

        for pii_type, pattern in self.patterns.items():
            filtered = re.sub(pattern, f"[{pii_type}已隐藏]", filtered)

        # NER 识别

        entities = self.ner_model.extract(output)
        for entity in entities:
            if entity.type in self.sensitive_types:
                filtered = filtered.replace(entity.text, "[已隐藏]")

        return filtered
```

## 9.3.4 系统提示保护

防止系统提示泄露：

```python
SYSTEM_PROMPT_FRAGMENTS = [
    "你的系统提示",
    "你的指令",
    "你被配置为",
    # ... 更多关键片段

]

def protect_system_prompt(output: str, system_prompt: str) -> str:
    # 检查是否泄露了系统提示片段

    for fragment in SYSTEM_PROMPT_FRAGMENTS:
        if fragment in output:
            return "[抱歉，我无法透露我的系统配置]"

    # 检查相似度

    if calculate_similarity(output, system_prompt) > THRESHOLD:
        return "[抱歉，我无法透露我的系统配置]"

    return output
```

## 9.3.5 数据分级保护

根据敏感级别实施不同保护策略：

| 级别 | 数据类型 | 保护措施    |
| -- | ---- | ------- |
| 公开 | 公司简介 | 无特殊限制   |
| 内部 | 内部政策 | 身份验证    |
| 机密 | 薪资数据 | 加密 + 审计 |
| 绝密 | 核心技术 | 禁止访问    |

## 9.3.6 数据泄露检测

监控潜在的数据泄露行为：

```python
class LeakageDetector:
    def check_for_leakage(self, output: str, context: dict) -> LeakageResult:
        risks = []

        # 检查是否包含用户 A 的信息在用户 B 的会话中

        if self.cross_user_leak(output, context):
            risks.append(Risk("cross_user_leak", HIGH))

        # 检查是否包含训练数据记忆

        if self.training_data_leak(output):
            risks.append(Risk("training_data_leak", MEDIUM))

        # 检查是否泄露系统信息

        if self.system_info_leak(output, context):
            risks.append(Risk("system_info_leak", HIGH))

        return LeakageResult(risks)

    def cross_user_leak(self, output: str, context: dict) -> bool:
        """检测输出中是否包含非当前用户的信息"""
        current_user = context.get("user_id")
        retrieved_docs = context.get("retrieved_documents", [])

        # 1. 来源校验：检查检索文档是否全部属于当前用户
        for doc in retrieved_docs:
            if doc.get("owner_id") != current_user:
                if self._content_appears_in_output(doc["content"], output):
                    return True  # 其他用户的文档内容出现在输出中

        # 2. 实体交叉检测：提取输出中的命名实体，与当前用户的已知实体集合对比
        output_entities = self.ner_extractor.extract(output)
        user_entities = self.get_user_entity_set(current_user)
        foreign_entities = output_entities - user_entities
        if self._entities_match_other_users(foreign_entities):
            return True

        # 3. 元数据标签检查：验证输出引用的数据源标签
        return False
```

**跨用户泄露检测的局限与建议**

完美的跨用户泄露检测在工程上极其困难，主要原因包括：

* **实体匹配局限**：不同用户可能拥有名称相同的实体（如“张三”这样的常见名字），导致单纯的实体匹配产生误报，难以准确判断信息所有权。
* **语义混淆风险**：输出中的内容可能是模型生成的通用信息，并非来自特定用户的数据，但与某用户的数据在语义上接近，导致检测困难。
* **检索链路复杂性**：在实际 RAG 系统中，用户在一次会话中可能查询多个数据源，跨用户检索的边界判定本身就存在模糊地带。

**因此，我们推荐采用“预防优于检测”的策略**：

1. **在检索阶段就严格过滤**：通过强制的访问控制和租户隔离，确保检索前端已经过滤掉非当前用户的文档，使得检测层只需应对已被过滤后的安全输入。
2. **实施多租户数据隔离**：使用独立的向量索引或显式的租户标签过滤，而不是依赖输出层的事后检测。
3. **审计与监控补偿**：如果仍存在跨用户泄露的残余风险，应通过强化审计日志与异常监控来及时发现，而非期待输出过滤器能完全阻断。

## 9.3.7 审计与合规

满足隐私保护法规要求：

**GDPR 合规要点**

| 要求     | 实现        |
| ------ | --------- |
| 最小化处理  | 只处理必要数据   |
| 目的限制   | 明确数据用途    |
| 数据主体权利 | 支持访问、删除请求 |
| 传输保护   | 加密传输      |

**审计记录**

```python
class PrivacyAuditLog:
    def log_data_access(self, user_id: str, data_type: str, purpose: str):
        record = {
            "timestamp": datetime.now(),
            "user_id": user_id,
            "data_type": data_type,
            "purpose": purpose,
            "legal_basis": self.get_legal_basis(purpose),
        }
        self.store(record)

    def log_data_deletion(self, request_id: str, user_id: str, status: str):
        record = {
            "timestamp": datetime.now(),
            "request_id": request_id,
            "user_id": user_id,
            "action": "deletion",
            "status": status,
        }
        self.store(record)
```

## 9.3.8 敏感信息防护的可测指标

如果没有量化指标，输入输出边界的防护很容易沦为“心理安慰”。在生产环境中实施数据保护体系，必须建立以下核心度量指标，并将其纳入日常监控大盘：

| 指标维度                    | 业务价值与衡量标准                                                           | 统计方式示例                                                                                                                 |
| ----------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| **泄漏率 (Leakage Rate)**  | 衡量脱敏引擎的假阴性（漏报）。高敏数据（如密钥、身份证）要求 **0 容忍**。                            | 利用外部/独立 DLP 旁路探针检测 LLM 回复客户端的最终 Payload，记录被独立探针抓到的未拦截敏感实例数。                                                            |
| **命中规则分布**              | 识别哪些维度的数据最常面临威胁，指导分类器规则库的动态增补。                                      | 按实体类型（如 `API_KEY: 40%`, `ID_CARD: 35%`）聚合网关拦截日志，绘制周环比风险饼图。                                                             |
| **脱敏一致性 (Consistency)** | 衡量输入侧基于不可预测占位符（如 `[PII:EMAIL:0:<nonce>]`）的脱敏机制，在允许还原的确定性字段中是否被正确保留。 | 计算 `通过解析器验证并完成逆向替换的占位符数量 / 允许还原的占位符总数`；低于阈值时应 fail closed，进入修复/重试流程，并通过独立 DLP 检查最终 payload。Prompt 只能作为提示，不应作为一致性的唯一控制。 |
| **下游执行防护率**             | 防止脱敏后的文本或大模型裸输出在下游业务链条中“把数据变成了指令”（即二次注入引发 RCE 或 SQLi）。              | 监控通过了敏感扫描的 LLM 输出流向，确保抵达 Shell/DB 前 100% 经过显式的参数化转移或严格的静态分析门禁。                                                         |

将上述指标作为自动化红队回归测试的一部分，并在 CI/CD 中设定熔断阈值，是验证隐私防护有效性的关键。

## 9.3.9 开源工具推荐

以下开源工具可帮助快速落地敏感信息保护能力：

| 工具                   | 核心能力                                                                                                          | 适用场景                                                |
| -------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| Microsoft Presidio   | 成熟的 PII 识别与数据脱敏引擎，通过规则引擎和 NER 模型自动识别文本中的姓名、电话、邮箱、信用卡号等敏感实体，并替换为占位符（如 `[PERSON]`、`[CREDIT_CARD]`），支持脱敏后的安全反演恢复 | 数据发送给大模型前的自动脱敏处理，以及模型返回后的敏感信息过滤，是落实“机密不入上下文”原则的首选工具 |
| Stanza NER（Stanford） | 多语言 NLP 工具包，其中当前官方 NER 模型覆盖 8 种语言，可提取人名、地名、组织名等实体                                                             | 多语言场景下的 PII 实体抽取，与正则规则互补，提升部分非英文环境下的识别准确率           |

敏感信息保护需要在系统设计的各个层面落实，是合规和信任的基础。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yeasy.gitbook.io/ai_security_guide/di-san-bu-fen-fang-yu-pian/09_io_protection/9.3_sensitive_data.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
