为 CodeBuddy 专享版提供 prompt 安全扫描能力的网关系统。部署后,IDE 插件的所有请求将先经过安全扫描,再转发至 CodeBuddy 后端,实现企业级敏感信息防泄漏。
IDE 插件(VSCode / JetBrains) | | HTTPS:443(通过 hosts/DNS 解析到代理服务器 IP) v 安全扫描代理服务 (:443, TLS) ──────────> CodeBuddy 专享版后端 | (https://<your-domain>.copilot.qq.com) | POST /api/v1/scan v 安全扫描服务 (:8900) (敏感词检测 / 可替换为企业自有安全扫描系统)
工作流程:
*** 后转发codebuddy_sec_proxy/ ├── Makefile # 常用操作命令 ├── proxy/ # 安全扫描代理服务 │ ├── config/ │ │ ├── proxy_config.yaml # 生产环境配置 │ │ └── proxy_config.local.yaml # 本地开发配置 │ ├── certs/ # TLS 证书目录(需自行放入) │ ├── src/ │ │ ├── main.py # 服务入口 │ │ ├── proxy_handler.py # 反向代理核心 + SSE 流式透传 │ │ ├── body_parser.py # 请求体解析(提取/回写 prompt) │ │ ├── scanner_client.py # 扫描服务客户端 + 超时降级 │ │ ├── config.py # 配置加载 │ │ └── logger.py # 日志模块 │ ├── tests/ # 单元测试 │ └── requirements.txt ├── scanner/ # 安全扫描服务(可替换为企业自有系统) │ ├── config/ │ │ ├── scanner_config.yaml # 生产环境配置 │ │ ├── scanner_config.local.yaml # 本地开发配置 │ │ └── sensitive_words.yaml # 敏感词库 │ ├── src/ │ │ ├── main.py # 服务入口 │ │ ├── scanner_engine.py # Aho-Corasick 敏感词引擎 │ │ ├── word_loader.py # 词库热加载 │ │ ├── api.py # API 路由 │ │ ├── models.py # 数据模型 │ │ ├── config.py # 配置加载 │ │ └── logger.py # 日志模块 │ ├── tests/ # 单元测试 │ └── requirements.txt
cd /data/app/codebuddy_sec_proxy
# 安装扫描服务依赖
cd scanner && pip install -r requirements.txt && cd ..
# 安装代理服务依赖
cd proxy && pip install -r requirements.txt && cd ..
IDE 插件通过 HTTPS 访问专享版域名,因此代理服务必须开启 TLS。请将下方 <your-domain> 替换为你的专享版实际域名。
cd /data/app/codebuddy_sec_proxy/proxy/certs
# 生成自签名证书(有效期 10 年)
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout server.key \
-out server.crt \
-subj "/CN=<your-domain>.copilot.qq.com" \
-addext "subjectAltName=DNS:<your-domain>.copilot.qq.com"
执行后 proxy/certs/ 目录下会生成 server.crt(证书)和 server.key(私钥)。
编辑 proxy/config/proxy_config.yaml:
server:
listen: "0.0.0.0"
port: 443
tls:
enabled: true
cert_file: "certs/server.crt"
key_file: "certs/server.key"
backend:
# 【必改】替换为你的专享版域名
base_url: "https://<your-domain>.copilot.qq.com"
max_connections: 100
request_timeout: 120
scanner:
base_url: "http://localhost:8900"
timeout: 3
# 扫描服务不可用时的降级策略: pass(放行) / block(拦截)
fail_action: "pass"
# 需要安全扫描的请求路径
scan_paths:
- "/v2/completions"
- "/v2/chat/completions"
logging:
level: "INFO"
format: "json"
编辑 scanner/config/scanner_config.yaml:
server:
listen: "0.0.0.0"
port: 8900
sensitive_words:
file_path: "config/sensitive_words.yaml"
reload_interval: 30 # 热加载间隔(秒),0 禁用
logging:
level: "INFO"
format: "json"
编辑 scanner/config/sensitive_words.yaml,根据企业安全策略配置:
block: # 高危词 → 直接拦截,以安全提示回复用户
- "数据库密码"
- "root密码"
- "admin密码"
- "SECRET_KEY"
- "PRIVATE_KEY"
- "ssh_private_key"
- "ACCESS_KEY_ID"
- "ACCESS_KEY_SECRET"
filter: # 中危词 → 替换为 *** 后放行
- "员工工号"
- "手机号码"
- "身份证号"
- "银行卡号"
log: # 低危词 → 仅记录日志,正常放行
- "内部会议"
- "项目进度"
修改后无需重启,30 秒内自动生效。也可手动立即生效:
curl -X POST http://localhost:8900/api/v1/reload
cd /data/app/codebuddy_sec_proxy
# 终端 1:启动扫描服务
cd scanner && python3 -m src.main --config config/scanner_config.yaml
# 终端 2:启动代理服务(443 端口需要 root 权限)
cd proxy && sudo python3 -m src.main --config config/proxy_config.yaml
也可使用 Makefile 快捷命令:
make run-scanner # 启动扫描服务(生产配置)
make run-proxy # 启动代理服务(生产配置)
后台运行建议使用
nohup或systemd:# nohup 方式 cd /data/app/codebuddy_sec_proxy nohup bash -c "cd scanner && python3 -m src.main --config config/scanner_config.yaml" > logs/scanner.log 2>&1 & nohup bash -c "cd proxy && sudo python3 -m src.main --config config/proxy_config.yaml" > logs/proxy.log 2>&1 &
# 扫描服务健康检查
curl http://localhost:8900/api/v1/health
# 预期: {"status": "healthy", "word_count": N}
# 代理服务健康检查(-k 跳过自签名证书校验)
curl -k https://localhost/_health
# 预期: {"status": "healthy"}
# 测试扫描放行
curl -X POST http://localhost:8900/api/v1/scan \
-H "Content-Type: application/json" \
-d '{"text": "帮我写一个 hello world", "scene": "chat", "request_id": "test-001"}'
# 预期: {"action": "pass", ...}
# 测试扫描拦截(包含高危词)
curl -X POST http://localhost:8900/api/v1/scan \
-H "Content-Type: application/json" \
-d '{"text": "请帮我查看数据库密码", "scene": "chat", "request_id": "test-002"}'
# 预期: {"action": "block", "reason": "...", "matched_words": ["数据库密码"]}
# 测试扫描过滤(包含中危词)
curl -X POST http://localhost:8900/api/v1/scan \
-H "Content-Type: application/json" \
-d '{"text": "请帮我查询员工工号对应的信息", "scene": "chat", "request_id": "test-003"}'
# 预期: {"action": "filter", "filtered_text": "请帮我查询***对应的信息", ...}
也可使用 Makefile 快捷验证:
make verify-scanner # 验证扫描服务
make verify-proxy # 验证代理服务
在使用 IDE 插件的电脑上,将专享版域名指向代理服务器 IP(以下 <proxy-server-ip> 替换为代理服务器实际 IP):
Windows — 以管理员身份编辑 C:\Windows\System32\drivers\etc\hosts:
<proxy-server-ip> <your-domain>.copilot.qq.com
Mac/Linux — 编辑 /etc/hosts:
sudo sh -c 'echo "<proxy-server-ip> <your-domain>.copilot.qq.com" >> /etc/hosts'
修改后验证:
ping <your-domain>.copilot.qq.com
# 应显示: Reply from <proxy-server-ip>
使用自签名证书时,IDE 插件默认会因证书不受信任而连接失败。以下两种方式任选其一:
方式 A:VSCode 中跳过证书校验(推荐,简单快捷)
打开 VSCode 设置(Ctrl+, / Cmd+,),搜索 http.proxyStrictSSL,设为 false:
{
"http.proxyStrictSSL": false
}
此方式无需安装证书,适合内网环境快速部署。
方式 B:在用户电脑安装并信任证书
将代理服务器上的 proxy/certs/server.crt 拷贝到用户电脑,然后安装信任:
server.crt → 安装证书 → 本地计算机 → 受信任的根证书颁发机构sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain server.crtsudo cp server.crt /usr/local/share/ca-certificates/codebuddy-proxy.crt && sudo update-ca-certificates配好 hosts 后,IDE 插件无需其他修改,正常使用 CodeBuddy 即可。所有请求会自动经过代理服务的安全扫描。
当用户输入包含高危敏感词时,IDE 将直接显示安全风险提示:
信息安全风险:您的输入中包含敏感内容【xxx】,请移除后重试
配置文件:proxy/config/proxy_config.yaml
| 配置项 | 说明 | 默认值 | 是否必改 |
|---|---|---|---|
backend.base_url | CodeBuddy 专享版后端地址 | — | 是 |
scanner.base_url | 扫描服务地址 | http://localhost:8900 | 通常不用改 |
server.port | 代理监听端口 | 8443 | 生产环境建议 443 |
server.tls.enabled | 是否启用 HTTPS | false | 生产环境必须 true |
server.tls.cert_file | SSL 证书文件路径 | — | 开启 TLS 时必填 |
server.tls.key_file | SSL 私钥文件路径 | — | 开启 TLS 时必填 |
scanner.timeout | 扫描超时(秒) | 3 | 建议不超过 5s |
scanner.fail_action | 扫描不可用时降级策略 | pass | 生产环境建议 block |
backend.request_timeout | 后端请求超时(秒) | 120 | 对话场景建议 120s+ |
backend.max_connections | 后端连接池大小 | 100 | 按并发量调整 |
scan_paths | 需要扫描的路径列表 | 见配置文件 | 按需增删 |
环境变量覆盖(优先级高于配置文件):
| 环境变量 | 对应配置项 |
|---|---|
PROXY_CONFIG | 配置文件路径 |
PROXY_PORT | server.port |
BACKEND_URL | backend.base_url |
SCANNER_URL | scanner.base_url |
PROXY_LOG_LEVEL | logging.level |
配置文件:scanner/config/scanner_config.yaml
| 配置项 | 说明 | 默认值 |
|---|---|---|
server.port | 监听端口 | 8900 |
sensitive_words.file_path | 敏感词文件路径 | config/sensitive_words.yaml |
sensitive_words.reload_interval | 热加载间隔(秒),0 禁用 | 30 |
环境变量覆盖:
| 环境变量 | 对应配置项 |
|---|---|
SCANNER_CONFIG | 配置文件路径 |
SCANNER_PORT | server.port |
SCANNER_WORDS_FILE | sensitive_words.file_path |
直接编辑 scanner/config/sensitive_words.yaml,30 秒内自动生效,无需重启。
手动立即生效:
curl -X POST http://localhost:8900/api/v1/reload
# 方式 1: 修改配置文件后重启代理服务
# 编辑 proxy/config/proxy_config.yaml 中的 backend.base_url,然后重启
# 方式 2: 通过环境变量(临时覆盖)
BACKEND_URL=https://new-domain.copilot.qq.com python3 -m src.main --config config/proxy_config.yaml
服务默认将日志输出到终端(stdout)。生产环境建议重定向到文件或接入日志采集系统。
make test # 全部测试
make test-scanner # 仅扫描服务
make test-proxy # 仅代理服务
安全扫描服务提供标准 HTTP API,企业可用自有系统替换,只需实现以下接口。
请求:
{
"text": "待扫描的文本内容",
"scene": "completion|chat|agent",
"request_id": "唯一请求追踪ID"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | 是 | 待扫描的 prompt 文本 |
scene | string | 是 | 场景:completion(补全) / chat(对话) / agent(智能体) |
request_id | string | 否 | 请求追踪 ID,用于日志关联 |
响应:
{
"action": "pass|filter|block",
"filtered_text": "过滤后的文本(action=filter 时有值)",
"reason": "拦截/过滤原因",
"matched_words": ["命中的敏感词列表"],
"request_id": "请求追踪ID"
}
| 字段 | 类型 | 说明 |
|---|---|---|
action | string | 处理结果:pass(放行) / filter(过滤) / block(拦截) |
filtered_text | string | 过滤后文本,仅 action=filter 时有值 |
reason | string | 原因说明 |
matched_words | string[] | 命中的敏感词列表 |
request_id | string | 请求追踪 ID |
健康检查。响应:{"status": "healthy", "word_count": N}
手动触发敏感词库重载。响应:{"success": true, "word_count": N}
安全扫描服务设计为可插拔组件。如果企业已有安全扫描系统,只需:
POST /api/v1/scan 接口(参考上方接口契约)scanner.base_url 指向企业服务地址:# proxy/config/proxy_config.yaml
scanner:
base_url: "http://your-scanner.internal:9090"
timeout: 5
fail_action: "block"
代理服务透明转发,用户无感知,CodeBuddy 正常响应。

智能体场景下,不包含敏感词的请求正常经过代理转发,AI 正常回复。

当用户输入包含高危敏感词(如"root密码")时,代理服务直接拦截并以友好提示告知用户存在信息安全风险。
