ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LLM系统提示词泄露风险:AI工程中的隐蔽安全盲区

LLM系统提示词泄露风险:AI工程中的隐蔽安全盲区 1. 项目概述什么是 system_prompts_leaks它为什么值得一线开发者警惕“system_prompts_leaks”不是某个具体工具、软件或开源项目而是一个在AI工程实践中高频出现、却长期被低估的系统性风险现象——指大语言模型LLM应用中本应严格隔离、不可见、仅用于内部指令调度的 system prompt系统提示词因设计疏漏、调试习惯、日志暴露、中间件透传、前端误显或API响应体污染等原因意外泄露给终端用户、第三方服务、爬虫、甚至公开API文档或错误堆栈中。这个术语最近在开发者社区快速升温并非因为出现了新漏洞而是因为越来越多真实事故被复盘有人在生产环境的ChatGPT插件响应里看到完整的system prompt有团队在Claude Workspace的调试日志中发现包含敏感权限逻辑的system指令还有人在用OpenAI Codex做代码补全时通过抓包看到{role: system, content: You are a senior security auditor...}明文返回。这些都不是理论风险而是已发生、可复现、有明确攻击链的实操问题。关键词“system_prompts_leaks”背后实际串联起的是当前AI原生应用开发中最脆弱的一环我们把system prompt当成“后台开关”却忘了它本质上是一段可执行的、带上下文权重的、可能含业务逻辑甚至密钥片段的代码。它不像数据库密码那样被专门加密存储也不像API Key那样有独立鉴权机制它常以纯文本形式硬编码在config.toml、写死在Python的messages[{role:system,content:...}]里甚至被当作调试注释直接print出来。当Anthropic官方强调“Claude Code是强绑定Claude系列模型的闭源工具”当OpenAI反复更新chat completion协议规范当VS Code插件配置稍有偏差就触发failed to start Claudes workspace——所有这些表层报错背后都可能藏着system prompt被意外加载、解析、透出的底层路径。我去年帮一家金融SaaS公司做AI客服模块审计时就发现他们把“禁止透露内部利率计算公式”的system指令和用户query一起打进了Elasticsearch日志索引且该索引对运维侧开放只读权限——这意味着任何有Kibana访问权的实习生都能在日志里搜到那条本该只对模型生效的约束指令。这不是危言耸听而是每天都在发生的“信任链断裂”。这个问题之所以突然成为热搜核心在于三重现实挤压第一模型能力越强system prompt越复杂从简单角色设定“你是一位律师”演进为多步骤工作流编排“先调用RAG检索再比对3个合规条款最后用FHIR格式输出”其信息密度和敏感度指数级上升第二开发链路越来越长从前端React组件、到FastAPI后端、再到LangChain代理层、最后到Anthropic或OpenAI的原始API调用任意一环的日志、监控、错误响应、调试面板都可能成为泄漏出口第三监管视角正在转向——GDPR第25条“默认数据保护”、中国《生成式人工智能服务管理暂行办法》第12条“不得含有歧视性内容”都要求system prompt本身必须可控、可审计、可回收。所以“system_prompts_leaks”本质是AI工程化落地过程中的一个可观测性盲区权限控制断点合规责任缺口。它适合所有正在用ChatGPT、Claude或OpenAI API构建真实产品的工程师、技术负责人、安全同学阅读尤其适合那些已经上线了AI功能但还没做过prompt层渗透测试的团队。接下来我会从设计原理、泄漏路径、实操检测、防御加固四个维度带你一层层剥开这个看似抽象、实则致命的问题。2. 核心泄漏路径拆解system prompt到底会在哪些环节“自己跑出来”要真正堵住system_prompts_leaks必须先搞清楚它最常从哪里“溜走”。这不是靠猜而是基于我过去三年跟踪的76个真实泄漏案例含内部审计报告与公开CVE总结出的五大高危路径。每一条都对应具体的代码结构、框架行为和网络协议特征而非泛泛而谈的“注意安全”。2.1 调试模式下的明文回显你以为的“本地调试”其实是公开广播这是新手最容易踩的坑。很多开发者习惯在本地启动FastAPI或Flask服务时开启debugTrue并在请求处理函数里加一句print(messages)或logger.info(fSending to LLM: {messages})来确认输入是否正确。问题在于当messages是一个包含system prompt的列表时这条日志不仅会出现在控制台更可能被自动采集进云日志服务如Datadog、阿里云SLS而这些日志平台默认对DevOps团队开放全文检索权限。更隐蔽的是某些前端调试工具如React DevTools的Network Tab会完整捕获fetch请求的body如果你用fetch(/api/chat, {method:POST, body:JSON.stringify({messages})})发送请求那么system prompt就会作为明文JSON字段出现在浏览器开发者工具里——哪怕你没主动点开看只要有人截屏或录屏信息就已外泄。我见过最典型的案例是一家教育科技公司的AI备课助手。他们在Vue组件里写了这样一段代码// src/components/AIAssistant.vue async sendQuery() { const messages [ { role: system, content: You are an expert in K12 curriculum design. All responses must cite CCSS standard codes. Never mention internal tool names like CurriSync or Eduscan. }, { role: user, content: this.inputText } ]; console.log(DEBUG: Full messages sent, messages); // ← 这行导致system prompt进入Chrome控制台历史 const res await fetch(/api/llm, { method: POST, body: JSON.stringify({messages}) }); }结果某次客户演示时销售同事用投屏软件共享了整个Chrome窗口system prompt里的CurriSync和Eduscan两个内部系统名被全程直播。事后复盘发现console.log在生产环境未被移除且Webpack未配置drop_console压缩规则。这提醒我们调试语句不是临时便利贴而是永久性数据出口。真正的做法是——所有涉及messages的log必须做字段脱敏例如# Python后端示例日志前强制过滤 def safe_log_messages(messages): redacted [] for m in messages: if m[role] system: redacted.append({role: system, content: [REDACTED_SYSTEM_PROMPT]}) else: redacted.append(m) logger.info(fLLM request: {redacted})2.2 API响应体污染当错误信息比正常响应更“诚实”这是最危险的泄漏路径——因为它利用了开发者对错误处理的天然松懈。当你调用Anthropic API时如果请求体格式错误比如messages数组为空、max_tokens超限服务端返回的400错误响应里常常会包含原始请求的片段用于定位问题。OpenAI的error response同样如此其error.message字段有时会直接回显你发送的system prompt内容。例如{ error: { message: Invalid request: system message content exceeds 1000 characters. Received: You are a certified financial advisor... [长达1200字符的完整system prompt], type: invalid_request_error } }这段错误信息如果未经处理就直接返回给前端或被记录在用户可见的错误弹窗里system prompt就完成了从服务端到客户端的“合法迁移”。更麻烦的是某些前端框架如Next.js的getServerSideProps在服务端渲染失败时会把整个错误堆栈序列化为HTML注释而这些注释在View Source里清晰可见。实测验证我用curl模拟了一个故意超长的system prompt请求curl -X POST https://api.anthropic.com/v1/messages \ -H x-api-key: $ANTHROPIC_KEY \ -H anthropic-version: 2023-06-01 \ -d { model: claude-3-haiku-20240307, max_tokens: 1024, messages: [ {role: system, content: A$(printf A%.0s {1..1500})}, {role: user, content: Hello} ] }响应体中果然包含了截断的system prompt字符串。这意味着任何未做error.message清洗的错误处理中间件都是system prompt的免费快递员。防御方案必须双管齐下服务端在返回错误前用正则rcontent\s*:\s*[^]*匹配并替换所有content字段值前端绝对禁止将error.message直接innerHTML到页面而应映射为预设的友好提示如“请求参数异常请检查输入长度”。2.3 中间件与代理层透传Nginx、LangChain、自定义Router的“无心之失”当你的架构里存在API网关、反向代理或LLM编排框架时system prompt的泄漏风险会呈几何级放大。以Nginx为例如果配置了log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $request_body;那么所有POST请求的原始body含system prompt都会被写入access.log。而默认情况下Nginx日志权限是644任何能SSH登录服务器的运维人员都能cat /var/log/nginx/access.log | grep system直接提取。LangChain更是重灾区。它的RunnableSequence或ChatPromptTemplate在调试时会调用.invoke()方法而该方法的返回值默认包含完整的messages对象。如果你在Jupyter Notebook里写from langchain_core.prompts import ChatPromptTemplate template ChatPromptTemplate.from_messages([ (system, You are a {role} with access to {tools}. Always use JSON format.), (user, {input}) ]) chain template | model result chain.invoke({role: doctor, tools: [lab_api, med_db], input: Whats my diagnosis?}) print(result) # ← 这里会打印出含system prompt的完整消息链那么result对象的__dict__里就存着原始system内容。更隐蔽的是LangChain的CallbackHandler如FileCallbackHandler会把每一步执行日志写入文件其中就包括system prompt的渲染结果。我曾审计过一个医疗问诊项目其FileCallbackHandler日志文件被部署在/public目录下导致system prompt可通过https://app.com/logs/2024-05-20.json直接下载。防御关键点在于所有中间件必须将system prompt视为“敏感载荷”而非普通文本。Nginx需禁用$request_body日志LangChain需重写invoke方法在返回前删除messages中的system项自定义Router如用Express写的LLM路由必须在req.body.messages进入业务逻辑前用req.body.messages req.body.messages.filter(m m.role ! system)做预处理。2.4 前端框架的“自动序列化”陷阱React、Vue、Svelte的隐藏副本现代前端框架为了提升开发体验会自动将组件状态序列化为可调试格式。React的useEffect依赖数组、Vue的watch监听器、Svelte的$:声明式响应都可能在内部创建messages的深拷贝。而当这些拷贝被传递给第三方SDK如Sentry错误监控、Heap用户行为分析时system prompt就随之出境。例如某电商公司使用Sentry捕获前端错误其初始化配置为Sentry.init({ dsn: https://xxxsentry.io/xxx, integrations: [new Sentry.BrowserTracing()], tracesSampleRate: 1.0, });当用户在AI导购页面触发错误时Sentry会自动收集window.location、document.title、以及当前React组件的全部state。如果state里有个chatHistory: [{role:system, content:...}]那么这条记录就会上传到Sentry云端且默认对所有项目成员可见。另一个典型场景是localStorage持久化。很多AI聊天应用为实现对话续聊会执行localStorage.setItem(chat_history, JSON.stringify(messages));而JSON.stringify不会对content字段做任何过滤。这意味着只要用户打开浏览器开发者工具的Application Tab点击localStorage就能看到完整的system prompt。更糟的是某些PWA渐进式Web应用会将localStorage数据同步到云端备份服务形成二次泄漏。破解之道非常直接前端永远不要让system prompt进入可序列化的状态树。正确做法是——将system prompt单独存于内存变量const SYSTEM_PROMPT ...在每次构造messages时动态拼接而非将其作为state的一部分// ✅ 正确system prompt不进state const [chatHistory, setChatHistory] useState([]); const SYSTEM_PROMPT You are a shopping assistant...; function sendMessage(text) { const newMessages [ { role: system, content: SYSTEM_PROMPT }, // 仅此处使用 ...chatHistory, { role: user, content: text } ]; // 发送newMessages但state只存user/assistant消息 setChatHistory(prev [...prev, {role:user,content:text}]); }2.5 模型服务自身的“调试后门”Claude Workspace、OpenAI Playground的隐式暴露这是最容易被忽视的路径——你以为的安全沙箱其实是最大的泄漏源。Anthropic官方推出的Claude Desktop和Claude Workspace虽然标榜“本地运行”但其底层仍需连接api.anthropic.com。当Workspace启动失败报错failed to start Claudes workspace或unable to connect to anthropic services时其错误日志位于%APPDATA%\Anthropic\Claude\logs或~/Library/Application Support/Anthropic/Claude/logs会详细记录加载的配置文件路径、尝试连接的endpoint、以及最关键——从config.toml中读取的system prompt原始内容。我实测过当config.toml中写有[llm] system_prompt You have access to internal CRM data via crm_api. Never expose field names like cust_id or sales_rep_id.Workspace的日志文件里就会出现INFO 2024-05-18T10:23:41.123Z [ConfigLoader] Loaded system_prompt: You have access to internal CRM data via crm_api. Never expose field names like cust_id or sales_rep_id.同理OpenAI Playground在“Share Link”功能中会将当前session的完整messages含system编码进URL hash形如https://platform.openai.com/playground#shareabc123...。任何人拿到这个链接都能在Playground里还原出你的system prompt。而很多开发者习惯把Playground链接发到Slack频道讨论等于主动分发敏感指令。因此所有本地AI工具的错误日志目录必须纳入CI/CD的敏感文件扫描清单Playground的Share Link功能应在团队安全规范中明令禁止用于生产相关prompt测试。真正的替代方案是用curl或Postman做最小化API测试system prompt通过环境变量注入SYSTEM_PROMPT$(cat ./prod_system.txt) curl -d {\messages\:[{\role\:\system\,\content\:\$SYSTEM_PROMPT\}]} ...确保其生命周期严格限定在单次命令中。3. 实操检测与验证如何在自己的项目中发现system_prompts_leaks发现泄漏不能靠运气必须建立一套可重复、可自动化、覆盖全链路的检测流程。我给团队制定的标准操作手册SOP包含四个阶段静态扫描、动态拦截、日志审计、人工渗透。每个阶段都有具体命令、工具配置和判定标准下面逐一分解。3.1 静态代码扫描用grep和ripgrep揪出所有硬编码的system prompt这是最基础也最有效的第一步。目标是找出代码库中所有明文出现的system prompt定义。关键在于不能只搜system字符串因为开发者可能用变量名sys_prompt、base_role、core_directive等代替也不能只搜Python文件因为TypeScript、JSON配置、甚至Dockerfile的ENV指令都可能藏匿。我使用的扫描命令组合如下Linux/macOS# 1. 全局搜索所有含system且后跟冒号/等号的行覆盖JSON、TOML、JS/TS赋值 rg -i \b(system|sys_|role|directive)\s*[:]\s*[\] --type-add json:**/*.json --type-add toml:**/*.toml --type-add ts:**/*.ts --type-add tsx:**/*.tsx --type-add py:**/*.py . # 2. 精准定位messages数组中role为system的条目正则匹配JSON/JS结构 rg -o -U role\s*:\s*system\s*,\s*content\s*:\s*[^]* --type-add json:**/*.json --type-add js:**/*.js --type-add ts:**/*.ts . # 3. 检查所有日志调用标记可能输出messages的位置 rg -i logger\.info|console\.log|print\(|logging\.debug --type-add py:**/*.py --type-add js:**/*.js --type-add ts:**/*.ts .提示rgripgrep比grep快10倍以上且支持类型过滤。如果团队用Windows可用Select-String -Path . -Pattern role\s*:\s*system -Recurse替代。扫描结果需要人工复核重点看三点位置是否合理system prompt是否定义在config/或constants/目录下合理还是散落在pages/或components/里高危内容是否敏感是否包含内部系统名如crm_api、字段名如cust_id、权限描述如admin_only是否被日志调用该变量是否出现在logger.info()或console.log()的参数中我曾用这套方法在一个20万行的AI客服项目中15分钟内找到17处硬编码system prompt其中3处直接关联到console.log(messages)2处被写入localStorage。这证明静态扫描不是形式主义而是最高效的泄漏定位器。3.2 动态流量拦截用mitmproxy捕获真实请求中的system prompt静态扫描只能发现“写死”的prompt而动态拦截能捕捉运行时实际发送的内容。这里推荐mitmproxy——一个支持Python脚本扩展的HTTPS代理工具比Charles或Fiddler更适合开发者定制规则。安装与基础配置pip install mitmproxy # 启动代理监听8080端口证书自动安装 mitmproxy --mode regular --port 8080然后在系统网络设置中将HTTP/HTTPS代理指向127.0.0.1:8080。此时所有浏览器、App、CLI工具的HTTPS请求都会经过mitmproxy且能被解密需安装mitmproxy根证书。关键技巧在于编写自定义脚本detect_system.py自动识别并告警system prompt# detect_system.py from mitmproxy import http def request(flow: http.HTTPFlow) - None: # 只检查POST请求且Content-Type为application/json if flow.request.method POST and application/json in flow.request.headers.get(content-type, ): try: body flow.request.get_text() # 检查JSON body中是否含system role if role:system in body or role: system in body: print(f⚠️ DETECTED SYSTEM PROMPT in {flow.request.url}) # 提取content字段值简化版实际用json.loads更稳 import re content_match re.search(rcontent\s*:\s*([^]*), body) if content_match: print(f Content preview: {content_match.group(1)[:100]}...) except Exception as e: pass # 忽略JSON解析失败运行命令mitmproxy --mode regular --port 8080 -s detect_system.py此时当你在浏览器中操作AI应用mitmproxy控制台会实时打印出所有含system prompt的请求。我用此方法在测试一个金融AI投顾App时发现其前端在每次用户提问前会先发一个预热请求POST /v1/chat/completions { model: gpt-4-turbo, messages: [ {role:system,content:You are a FINRA-certified advisor. Never discuss tax implications without disclaiming not tax advice.} ] }而这个请求的URL是/v1/chat/completions?prewarmtrue属于未文档化的内部接口静态扫描根本无法覆盖。这说明动态拦截是发现“活”泄漏的唯一可靠手段。3.3 日志文件审计从Nginx、应用日志、错误监控中挖掘泄漏痕迹日志是system prompt泄漏的“犯罪现场”。审计日志不是翻页找关键词而是用结构化查询精准定位。以常见的ELKElasticsearchLogstashKibana栈为例Nginx access.log查询request_body字段需Logstash已配置codec json解析GET /nginx_logs/_search { query: { bool: { must: [ { match: { request_method: POST } }, { wildcard: { request_body: *\role\:\system\* } } ] } } }应用日志如Python logging在Kibana中用KQL查询log.level : INFO and message : messages and message : systemSentry错误事件用Sentry的Discover功能筛选event.type:error且message:*system*的事件然后查看其extra字段是否包含messages。对于没有集中日志系统的团队可用awk做本地快速筛查# 扫描所有.log文件提取含system且content长度50的行 find /var/log -name *.log -exec awk /system.*content.*.{50,}/ {print FILENAME : NR : $0} {} \;注意审计日志前务必确认日志采集策略已排除敏感字段。例如Logstash配置中应加入filter { mutate { gsub [message, content\s*:\s*[^]*, content: [REDACTED]] } }3.4 人工渗透测试模拟攻击者视角的四步验证法最后也是最关键的一步像真实攻击者一样主动尝试触发泄漏。我设计了一套四步法每次测试耗时不超过20分钟但能覆盖90%的泄漏场景Step 1错误注入测试向API发送一个明显错误的请求例如OpenAI{model:gpt-4,messages:[{role:system,content:test},{role:user,content:a*10000}],max_tokens:1}超长content超小max_tokensAnthropic{model:claude-3-opus-20240229,messages:[{role:system,content:test}],max_tokens:1}观察响应体中是否回显system content。如果出现立即修复error handler。Step 2前端审查测试打开浏览器开发者工具执行// 检查所有localStorage键值 Object.keys(localStorage).forEach(k { try { const v localStorage.getItem(k); if (v v.includes(system) v.includes(role)) console.log(LEAK IN LOCALSTORAGE:, k, v.substring(0,200)); } catch(e) {} }); // 检查所有全局变量 Object.keys(window).filter(k k.includes(prompt) || k.includes(system)).forEach(k console.log(GLOBAL LEAK:, k, window[k]));Step 3网络请求审查测试在Network Tab中筛选XHR/Fetch请求逐一点击查看Headers和Payload。重点关注Content-Type: application/json的POST请求URL含/chat、/completions、/messages的请求Payload中是否有role:system字段Step 4配置文件审查测试直接访问应用可能读取的配置路径需有服务器权限# 检查常见配置文件 ls -la /etc/app/config.toml ~/.config/myapp/settings.json ./config/production.json # 查看是否含system_prompt字段 grep -i system_prompt\|role.*system /etc/app/config.toml这套方法在我给12家客户做的渗透测试中平均发现3.2个有效泄漏点其中2个是客户自己从未意识到的如Nginx日志透传、Sentry自动捕获。它证明安全不是靠祈祷而是靠可执行的验证动作。4. 防御加固实战从代码、配置、流程三个层面彻底封堵system_prompts_leaks发现问题是起点加固才是终点。我总结的防御体系分为三层代码层即时生效、配置层基础设施保障、流程层组织级防护。每一层都给出可直接复制的代码、配置片段和Checklist拒绝空泛建议。4.1 代码层加固用“三不原则”重构所有LLM交互逻辑所谓“三不原则”即不硬编码、不直传、不日志。这是我在所有项目代码审查中强制推行的铁律。不硬编码system prompt必须从受控源加载而非写死在代码里。推荐方案是环境变量配置中心双保险# config.py import os from typing import Optional class LLMConfig: staticmethod def get_system_prompt() - str: # 优先从环境变量读取支持Docker/K8s secrets prompt os.getenv(LLM_SYSTEM_PROMPT) if prompt: return prompt # 兜底从加密配置文件读取需提前用AES加密 try: from cryptography.fernet import Fernet key os.getenv(CONFIG_ENCRYPTION_KEY).encode() f Fernet(key) with open(/etc/secrets/system_prompt.enc, rb) as f_enc: return f.decrypt(f_enc.read()).decode() except Exception: raise RuntimeError(No system prompt configured) # 使用时 messages [ {role: system, content: LLMConfig.get_system_prompt()}, {role: user, content: user_input} ]不直传所有发送给LLM的messages必须经过净化函数处理def sanitize_messages_for_llm(messages: list) - list: 移除所有可能泄露的字段仅保留role/user/content最小集 sanitized [] for m in messages: # 强制移除system role由服务端统一注入 if m[role] system: continue # 清洗content中的敏感token clean_content m[content] # 移除API Keys匹配类似sk-xxx的模式 clean_content re.sub(rsk-[a-zA-Z0-9_\-]{20,}, [API_KEY_REDACTED], clean_content) # 移除内部域名如internal-api.company.com clean_content re.sub(r\b[a-z0-9.-]*\.company\.com\b, [INTERNAL_DOMAIN], clean_content) sanitized.append({ role: m[role], content: clean_content }) return sanitized # 调用前 safe_messages sanitize_messages_for_llm(raw_messages) response client.messages.create(modelclaude-3-haiku-20240307, messagessafe_messages)不日志所有日志调用必须使用专用包装函数import logging import json logger logging.getLogger(__name__) def log_llm_interaction( operation: str, input_messages: list None, output_content: str None, status: str success ): 安全日志函数自动脱敏messages和output log_data { operation: operation, status: status, input_count: len(input_messages) if input_messages else 0, output_length: len(output_content) if output_content else 0 } # 关键绝不记录原始messages if input_messages: # 只记录统计信息不记录内容 system_count sum(1 for m in input_messages if m[role] system) user_count sum(1 for m in input_messages if m[role] user) log_data[input_summary] f{system_count} system {user_count} user messages logger.info(json.dumps(log_data)) # 使用 log_llm_interaction(chat_completion, raw_messages, response.content, success)这套代码层加固已在我们团队的17个AI项目中落地上线后system prompt泄漏事件归零。它不增加开发负担反而提升了代码可维护性——因为所有敏感逻辑都收口在config.py和sanitize.py里新人无需理解业务细节只需按规范调用即可。4.2 配置层加固Nginx、Docker、K8s的七项必改配置基础设施配置是防御的第二道墙。以下是我在生产环境强制实施的七项配置修改每项都附带具体命令和效果说明1. Nginx禁用$request_body日志# /etc/nginx/nginx.conf log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent; # 删除 $request_body 字段效果避免POST body含system prompt写入access.log。2. Docker容器限制日志大小与轮转# Dockerfile # 添加日志驱动配置 RUN mkdir -p /var/log/myapp \ chown -R app:app /var/log/myapp # docker-compose.yml services: llm-api: image: myapp:latest logging: driver: json-file options: max-size: 10m # 单个日志文件最大10MB max-file: 3 # 最多保留3个历史文件效果防止日志文件无限增长降低信息暴露面。3. K8s Pod安全上下文禁用特权模式# deployment.yaml securityContext: runAsNonRoot: true runAsUser: 1001 seccompProfile: type: RuntimeDefault capabilities: drop: [ALL] # 禁用所有Linux capabilities效果即使容器被攻破攻击者也无法读取宿主机日志文件。4. OpenTelemetry Collector过滤敏感字段# otel-collector-config.yaml processors: attributes/example: actions: - key: body action: delete # 删除所有span中的body字段 - key: attributes.system_prompt action: delete效果防止APM工具如Datadog、New Relic采集system prompt。5. Sentry SDK配置脱敏// sentry.client.config.js Sentry.init({ dsn: https://xxxsentry.io/xxx, // 关键移除所有含prompt的字段 normalizeDepth: 3, beforeBreadcrumb: (breadcrumb) { if (breadcrumb.category ui.click breadcrumb.message?.includes(system)) { return null; // 丢弃该面包屑 } return breadcrumb; }, beforeSend: (event) { // 移除event中所有含system的字段 const cleanEvent JSON.parse(JSON.stringify(event)); delete cleanEvent.extra?.messages; delete cleanEvent.extra?.system_prompt; return cleanEvent; } });效果确保Sentry不存储任何system prompt副本。6. VS Code设置禁用自动保存日志// .vscode/settings.json { files.autoSave: off, editor.formatOnSave: false, extensions.ignoreRecommendations: true, // 关键禁用所有可能记录prompt的扩展 extensions.autoUpdate: false }效果防止开发者本地VS Code的扩展如REST Client将system prompt存入临时文件。7. CI/CD流水线添加敏感词扫描# .gitlab-ci.yml stages: - test sensitive-scan: stage: test script: - apt-get update apt-get install -y ripgrep - rg -i role\s*:\s*system\s*,\s*content\s*: --max-count1 . - if [ $? -eq 0 ]; then echo ERROR: System prompt found in code!; exit 1; fi allow_failure: false效果在代码合并前自动拦截硬编码system prompt。这七项配置看似琐碎但共同构成了一个纵深防御网络。我在上一家公司推动落地时用Ansible Playbook统一推送3天内完成全部23个生产集群的加固。结果是后续半年的安全审计中system prompt
返回列表