通过HTTP代理在请求发送前清除JSON中的密钥、内部主机名等敏感信息,降低使用免费模型API的安全风险。
一次粘贴进聊天窗口可能暴露比你预期更多的东西。API 密钥、内部主机名、客户邮件都在 prompt 里流动。免费模型端点可能会存储或记录那段文本。请求离开之后,你无法检查它们的数据保留策略。
更安全的做法是先脱敏再发送。这篇教程构建一个本地 HTTP 代理,它从外发的 JSON 中剥离常见敏感信息,只记录被移除值的单向哈希。
MonkeyCode 的免费模型访问是跑通这个实验的方式之一,无需付费账号。披露:本文是 MonkeyCode 产品推广的一部分。代码可配合任何 JSON 聊天补全端点使用。
聊天窗口让粘贴整个文件变得容易。这些文件通常包含敏感信息。免费模型端点不是你的私人保险箱,它的日志可能比你的会话存在得更久。
你需要一道自己控制的边界。这道边界应该在请求离开你的机器之前就发挥作用。
你要构建两个小的 Python 文件。
proxy.py 位于你的客户端和模型端点之间。
mock_upstream.py 为离线测试模拟端点。
代理遵循四个步骤。
从常见令牌的规则开始。保持规则明确,不要试图捕获所有可能的敏感信息。
为自己的秘密格式添加一条规则。窄规则优于宽规则。
import hashlib
import json
import os
import re
import urllib.request
from http.server import BaseHTTPRequestHandler, HTTPServer
UPSTREAM = os.environ.get('UPSTREAM_URL', 'http://127.0.0.1:9000/echo')
KEY = os.environ.get('UPSTREAM_API_KEY', '')
RULES = [
('sk-[A-Za-z0-9_-]{16,}', '[REDACTED_API_KEY]'),
('eyJ[A-Za-z0-9_-]{10,}[.][A-Za-z0-9_-]{10,}[.][A-Za-z0-9_-]{10,}', '[REDACTED_JWT]'),
('[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+[.][A-Za-z]{2,}', '[REDACTED_EMAIL]'),
('AKIA[0-9A-Z]{16}', '[REDACTED_AWS_KEY]'),
('-----BEGIN [A-Z ]*PRIVATE KEY-----', '[REDACTED_PRIVATE_KEY]'),
]
def redact(value):
if isinstance(value, dict):
return {k: redact(v) for k, v in value.items()}
if isinstance(value, list):
return [redact(item) for item in value]
if isinstance(value, str):
for pattern, replacement in RULES:
match = re.search(pattern, value)
if match:
token = match.group(0)
digest = hashlib.sha256(token.encode()).hexdigest()[:12]
print('redacted ' + digest, flush=True)
value = re.sub(pattern, replacement, value)
return value
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
length = int(self.headers.get('content-length', '0'))
raw = self.rfile.read(length)
data = json.loads(raw.decode('utf-8'))
cleaned = redact(data)
req = urllib.request.Request(
UPSTREAM,
data=json.dumps(cleaned).encode('utf-8'),
method='POST',
headers={'content-type': 'application/json'},
)
if KEY:
req.add_header('authorization', 'Bearer ' + KEY)
with urllib.request.urlopen(req, timeout=30) as resp:
body = resp.read()
self.send_response(resp.status)
self.send_header('content-type', 'application/json')
self.end_headers()
self.wfile.write(body)
def log_message(self, fmt, *args):
pass
HTTPServer(('127.0.0.1', 8000), Handler).serve_forever()
代理不打印敏感信息,只打印一个短哈希。这个哈希足以确认某条规则被触发了。
创建 mock_upstream.py。
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
length = int(self.headers.get('content-length', '0'))
raw = self.rfile.read(length)
print('UPSTREAM_GOT ' + raw.decode('utf-8'), flush=True)
self.send_response(200)
self.send_header('content-type', 'application/json')
self.end_headers()
payload = json.dumps({'choices': [{'message': {'content': 'ok'}}]}).encode('utf-8')
self.wfile.write(payload)
HTTPServer(('127.0.0.1', 9000), Handler).serve_forever()
这个文件精确打印代理本应转发的内容。用它可以在调用真实提供商之前验证脱敏效果。
在一个终端启动模拟上游。
python mock_upstream.py
在第二个终端启动代理。
python proxy.py
在第三个终端发送一个测试 fixture。
import json
import urllib.request
payload = {
'model': 'example',
'messages': [
{'role': 'user', 'content': 'Fix sk-12345678901234567890 for dev@example.com'}
]
}
req = urllib.request.Request(
'http://127.0.0.1:8000/',
data=json.dumps(payload).encode('utf-8'),
method='POST',
headers={'content-type': 'application/json'},
)
print(urllib.request.urlopen(req).read().decode())
检查模拟上游终端。它应该显示 [REDACTED_API_KEY] 和 [REDACTED_EMAIL],而不应该显示 sk-12345678901234567890 或 dev@example.com。
代理终端应该显示两个短哈希。这些哈希对高熵敏感信息不可逆。
设置上游变量并重启代理。
export UPSTREAM_URL='https://your-provider.example/v1/chat/completions'
export UPSTREAM_API_KEY='your-key-here'
python proxy.py
如果提供商给了标准聊天补全 URL,MonkeyCode 的免费模型访问可以作为上游使用。免费服务器选项也可以托管这个脚本,如果它允许长时间运行的 Python 进程。先确认当前的限制。
不要把密钥硬编码到版本控制中,使用环境变量或密钥管理器。
正则脱敏是一个尽力而为的过滤器。它会漏掉截图、PDF 或 base64 blob 中的敏感信息,也会漏掉未知格式的令牌。
本地代理增加了一个网络跳数。它不能替代访问控制或数据分类。不要用它处理受监管的数据,比如健康记录或支付详情。
如果你的团队需要经过批准的 DLP 工具,不要使用这个。本教程是一个小的技术控制手段,不是合规项目。
这个版本只处理非流式 JSON。流式响应需要不同的传输路径。
如果你上传文件而不是文本 prompt,跳过这个。如果额外的进程不可接受,跳过这个。如果你无法长期维护正则规则,跳过这个。
过时的规则会产生虚假的安全感。代理的效果取决于它的规则列表。
在边界脱敏,而不是在 prompt 内部脱敏。一个 60 行的代理在明显泄漏到达外部 API 之前就阻止它们。用模拟上游测试,这样你可以精确看到什么离开了你的机器。
运行一次模拟测试,然后把上游替换成你已经使用的端点。添加一条匹配你自己秘密格式的规则。