AI 工具

粘贴到 Copilot 前:用 Python 做敏感信息预检

往 Copilot 粘贴前,用启发式规则扫描 API Key、私钥、密码赋值、身份证号等。拦得住常见事故,不是完整 DLP。

BINBHO · 图文教程

往 Copilot 粘贴前,用启发式规则扫描 API Key、私钥、密码赋值、身份证号等。拦得住常见事故,不是完整 DLP。

先看清成品

  • safe → OK;risky → BLOCK(多条命中)。
  • 3 项 pytest 通过。

合规提醒:个人 Copilot 与 Microsoft 365 Copilot 是不同产品;企业场景用公司账号并遵守组织数据政策。不要把密钥、客户名单、未公开财报等粘贴进个人版聊天。Graph 连接器写入的外部内容受 ACL 约束;错误开放等于数据泄露。本文不编造价格。

运行说明:无 Microsoft 365 / Graph 租户密钥。三篇均为本地离线助手:A 从会议记录抽待办;B 粘贴前 DLP 启发式扫描;C 校验 externalItem 形状。未调用官方聊天 API(消费级 Copilot 无通用「随便调」的公开 chat API)。2026-10-23(Asia/Shanghai)pytest 通过。

做完之后你会得到什么?

成果 说明
paste_guard.py 粘贴门禁
样例 txt safe/risky
test_102b.py 测试

需要准备哪些环境?

项目 说明
Python 3.10+

关键事实

事实 来源
个人版与企业版数据保护边界不同;企业应遵守组织策略 定位说明
启发式无法覆盖所有密钥形态 重要
真正企业控制应使用 M365 DLP / 纯视图等管理功能 产品能力,以租户配置为准

文件结构

102-microsoft-copilot-B-src/
├── paste_guard.py
├── sample_safe.txt
├── sample_risky.txt
└── test_102b.py

第 1 步:门禁脚本

#!/usr/bin/env python3
"""Scan text before pasting into Microsoft Copilot / M365 Copilot (heuristic DLP)."""
from __future__ import annotations

import argparse
import json
import re
from pathlib import Path

RULES = [
    ("api_key", re.compile(r"(?i)(api[_-]?key|secret|token)\s*[:=]\s*['\"]?[A-Za-z0-9_\-]{16,}")),
    ("private_key", re.compile(r"-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----")),
    ("aws_akid", re.compile(r"AKIA[0-9A-Z]{16}")),
    ("password_assign", re.compile(r"(?i)password\s*[:=]\s*\S+")),
    ("cn_id", re.compile(r"\b[1-9]\d{5}(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]\b")),
    ("email_batch", re.compile(r"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+.*){5,}", re.S)),
]


def scan(text: str) -> list[dict]:
    hits = []
    for name, pat in RULES:
        for m in pat.finditer(text):
            hits.append({"rule": name, "span": m.span(), "snippet": text[m.start():m.start()+40]})
    return hits


def main(argv=None) -> int:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("file")
    ap.add_argument("--json", action="store_true")
    args = ap.parse_args(argv)
    text = Path(args.file).read_text(encoding="utf-8")
    hits = scan(text)
    if args.json:
        print(json.dumps({"ok": not hits, "hits": hits}, ensure_ascii=False, indent=2))
    else:
        if not hits:
            print("OK: 未命中常见机密模式(启发式,非企业 DLP)")
        else:
            print(f"BLOCK: {len(hits)} hits")
            for h in hits:
                print(f"- [{h['rule']}] {h['snippet']!r}")
    return 1 if hits else 0


if __name__ == "__main__":
    raise SystemExit(main())

第 2 步:测试

from pathlib import Path
import subprocess, sys
from paste_guard import scan
HERE = Path(__file__).resolve().parent

def test_safe():
    assert scan((HERE/"sample_safe.txt").read_text()) == []

def test_risky():
    hits = scan((HERE/"sample_risky.txt").read_text())
    assert {h["rule"] for h in hits} >= {"api_key", "private_key"}

def test_cli():
    r = subprocess.run([sys.executable, str(HERE/"paste_guard.py"), str(HERE/"sample_safe.txt")], capture_output=True, text=True)
    assert r.returncode == 0

第 3 步:运行

$ python paste_guard.py sample_safe.txt
OK: 未命中常见机密模式(启发式,非企业 DLP)

$ python paste_guard.py sample_risky.txt
BLOCK: 3 hits
- [api_key] 'api_key = "sk-proj-THISISFAKESECRETVALUE'
- [private_key] '-----BEGIN PRIVATE KEY-----\nMIIEvgIBADAN'
- [password_assign] 'password: hunter2\n-----BEGIN PRIVATE KEY'

$ pytest -q
...                                                                      [100%]
3 passed in 0.03s

怎么检查结果?

  • safe 退出码 0。
  • risky 打印 BLOCK 与规则名。

调试示例

「这是假的 sk- 也拦」。 对:粘贴门禁按形态拦截,不验证真伪。演示密钥同样不该进聊天记录。

常见问题

现象 原因 处理
误报 放宽规则 按团队白名单改
漏报 正常 再叠企业 DLP
截图里的密钥 本脚本不 OCR 禁止截图敏感信息

模板规则

  • 个人版不贴客户机密。
  • 命中即改写或删除后再问。
  • 企业场景用公司账号。

项目资源

用途 地址
Copilot 网页 https://copilot.microsoft.com/
M365 Copilot(介绍) https://www.microsoft.com/en-us/microsoft-365/copilot
扩展性概览(官方 Learn) https://learn.microsoft.com/en-us/microsoft-365-copilot/extensibility/overview

先扫再贴,少一次密钥进模型的事故。