文章建议将发送给托管编程模型的字段划分为本地、可共享和禁止外传三类,并在客户端序列化前拦截违规请求。编辑器、本地 Agent 与远程服务应分别定义信任边界,避免差异、日志和工具轨迹被打包外传。
你应该把每个托管的 coding model 都视为一位访客,只允许它读取你特意装载的那些货箱。免费不会让这位访客的记忆变短,免费服务器也不会自动成为你的合规边界。在把审查循环接入任何远程模型之前,先为每个字段标注:仅限本地、可以共享,或禁止发送。这些标签应当在你的进程内部拦截不合规请求,先于客户端库对请求进行序列化。
把这条路径想象成装卸区,而不是你在会议间隙随手填内容的聊天框。编辑器是仓库,Agent 是装卸员,托管模型则是等在外面的访客。装卸员会把 diff、日志和工具执行轨迹堆到同一个托盘上,因为一次请求看起来更高效。你得把装卸区的规则写进客户端调用路径,否则,按照日常操作习惯,访客就会收到整个托盘。
先在纸上划出四个区域,每个区域只授予你确实有把握保障的信任。编辑器区域可以存放秘密,因为这些字节本来就应该留在你管理的磁盘上。本地 Agent 区域可以读取这些文件,但没有标签就不得转发。免费服务器区域依然是别人的进程:它有日志、备份和管理员,而这些都不由你安排。
模型区域是一个独立的接收方,即使服务器和模型权重由同一家供应商运营,也是如此。免费服务器可以改变你的费用,也可以改变进程在哪台机器上启动。但它不会改变客户端提交 payload 后,谁有权读取其中的内容。你应该假定,prompt、工具参数和捕获的 stderr 都可能被保存,用于滥用审查或调试。
接入当天,查阅最新文档,确认数据保留期限、处理区域,以及数据是否用于训练。如果这些页面没有说明,或相互矛盾,就把 payload 留在装卸区的仓库这一侧。不要因为调用免费,就发送客户执行轨迹、生产环境文件或私钥。低价不是管控措施,新模型发布也不是。
利益披露:本文是 MonkeyCode 产品推广的一部分。这份草稿的运营方将 MonkeyCode 描述为一个提供免费模型访问和免费服务器选项的开源项目。即使去掉这个产品,本文的操作流程仍然适用;本文也不承诺任何配额、硬件配置或长期价格。请在接入当天阅读项目仓库,因为如果没有最新的一手来源,关于可用性的描述很快就会过时。
你应该添加一个字段分类器,在任何客户端提交 JSON 之前运行它。下面的脚本是未经执行验证的示例,不是 benchmark;你需要根据自己的项目目录扩充拒绝列表。它从标准输入读取一个 payload,遍历嵌套键,并为每个匹配项打印标签。匹配到禁止发送的内容时,退出状态为 2;匹配到仅限本地的内容时,退出状态为 1;未发现问题的 payload 则以状态 0 退出。
#!/usr/bin/env python3
'''Unexecuted example: label fields before a model request is sent.'''
import json
import re
import sys
# False positives are expected on names such as token_count.
FORBIDDEN_KEY = re.compile(
r'(api[_-]?key|secret|password|token|authorization|private[_-]?key|cookie|credential)',
re.I,
)
LOCAL_ONLY_KEY = re.compile(
r'(stack|traceback|env|home_path|email|phone|session)',
re.I,
)
SHAREABLE_KEY = re.compile(
r'(diff_summary|language|test_name|public_error_code|file_role)',
re.I,
)
VALUE_HINT = re.compile(
r'(AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]+PRIVATE KEY-----|Bearer\s+\S+)',
re.I,
)
def walk(node, path='$'):
findings = []
if isinstance(node, dict):
for key, value in node.items():
child = f'{path}.{key}'
if FORBIDDEN_KEY.search(key):
findings.append((child, 'forbidden'))
elif LOCAL_ONLY_KEY.search(key):
findings.append((child, 'local_only'))
elif SHAREABLE_KEY.search(key):
findings.append((child, 'shareable'))
findings.extend(walk(value, child))
elif isinstance(node, list):
for index, value in enumerate(node):
findings.extend(walk(value, f'{path}[{index}]'))
elif isinstance(node, str) and VALUE_HINT.search(node):
findings.append((path, 'forbidden_value'))
return findings
def main():
payload = json.load(sys.stdin)
findings = walk(payload)
for path, kind in findings:
print(f'{kind}\t{path}')
kinds = {kind for _, kind in findings}
if 'forbidden' in kinds or 'forbidden_value' in kinds:
return 2
if 'local_only' in kinds:
return 1
return 0
if __name__ == '__main__':
sys.exit(main())
先运行不含敏感内容的 fixture:当 payload 只包含可以共享的键时,预期退出状态为 0。接着运行含有秘密的 fixture,预期状态为 2,因为键名本身就已经表明这是传递秘密的通道。然后运行包含 traceback 的 fixture,预期状态为 1,确保仅限本地的字段也无法离开本地。在客户端之前接入同样的检查,让任何检查失败的请求都无法进入网络调用。
python3 gate_payload.py <<'JSON'
{"language":"python","diff_summary":"rename helper","test_name":"test_gate"}
JSON
echo "clean exit:$?"
python3 gate_payload.py <<'JSON'
{"diff_summary":"rename helper","api_key":"sk-live-do-not-send"}
JSON
echo "forbidden exit:$?"
python3 gate_payload.py <<'JSON'
{"diff_summary":"rename helper","traceback":"/home/dev/app.py"}
JSON
echo "local-only exit:$?"
将分类器保存为 gate_payload.py,赋予它可执行权限,并把它放在 fixture 旁边,而不是服务器上。通过标准输入传入 fixture,获取退出状态;如果状态不为零,就在调用 curl 或 SDK 之前退出。对于个人使用的循环,一段 shell 守卫就够了,下面这段未经执行验证的示意代码展示了基本形式。这个先后顺序比 URL 背后的产品更重要,因为一旦跳过本地检查,远程端就无法挽回已经发生的发送。
python3 gate_payload.py < fixture.json
status=$?
if [ "$status" -ne 0 ]; then
printf '%s\n' "refusing model call: gate status ${status}" >&2
exit "$status"
fi
原始环境变量转储、认证请求头和私钥块,都应该留在编辑器区域。客户标识符、会话 cookie 和完整堆栈轨迹,在你改写处理之前,都属于仅限本地的类别。公开错误码、语言名称和精简后的 diff 摘要,在已经移除名称的前提下,可以通过检查。不确定时就拒绝发送,因为漏标而拒绝发送的代价,比凭证泄露小得多。
这个关卡对命中规则的键名采取默认拒绝策略,但像 note 这样普通的键,仍然可能藏着秘密。拆开的 token、base64 数据块,以及粘贴进 diff 片段的秘密,也能绕过这份简短的模式列表。你应该增加第二轮检查来扫描字段值,并在信任一个新 fixture 之前,亲自检查 diff。这个脚本不会加密传输,不能证明数据已经删除,也无法告诉你哪个区域接收了这些字节。
不要把这套方法用于健康记录、支付数据,或任何已被监管机构明确列为监管对象的 payload。也不要用它替代合同约定的数据处理审查、私有网络边界,或真正的 DLP 产品。如果团队说不清日志存放在哪里,就不要采用这套方法,因为这个关卡只能拦住它看得见的内容。清理个人仓库的独立开发者可以使用它,但医院系统集成团队不应该使用。
分三个稳妥的步骤搭建审查循环,每一步都不要引入生产流量。第一,把一个失败的测试复制到 fixture 文件中,确保里面不包含你主目录中的任何路径。第二,运行分类器,只要退出状态不为零就停止,即使这个失败看起来无害。第三,只把这个 fixture 发给托管模型,然后在应用建议之前,把建议再交给同一个分类器检查。
把 completion 当作访客送来的不可信文本,而不是你已经审查过的补丁。建议可能重新引入你已经剔除的秘密,也可能推荐读取本地凭证文件的命令。对回复运行分类器,并拒绝任何访问你的环境、SSH 目录或 shell 历史记录的命令。如果回复只是改写了一个函数,没有引入新的标识符,你可以在一个分支中应用它,再运行平常的测试。
如果你在免费服务器上练习,就创建一个只存放 fixture 的项目,绝不要把真实的主目录挂载进去。让客户端指向这个项目,同时把分类器留在笔记本电脑上,避免远程 shell 绕过它。免费的进程依然可能写入不由你轮转的日志,因此,只发送能够复现 bug 的最小 fixture。练习结束后删除远程项目,但不要把删除操作当作所有副本都已消失的证明。
结论很简单:给货箱贴上标签,检查不通过就拒绝发送,只让模型看到你愿意发布到公开 gist 的内容。免费模型访问是练习这个习惯的便利场所,不是跳过这个习惯的理由。如果你想找一个托管服务来接收已标注的 fixture,就阅读 MonkeyCode 当前的项目仓库,只有在条款与你划定的区域和信任边界相符时才接入。把生产日志、客户姓名和有效凭证留在仓库里,访客从未获准进入那里。
如果要采取进一步行动,你可以考虑屏蔽此人和/或举报滥用行为。