CodeQL 系统提示词注入:JavaScript 修复清单

原文:https://indieseek.co/zh/blogs/codeql-system-prompt-injection-javascript-checklist/

CodeQL 系统提示词注入:JavaScript 修复清单

快速结论

GitHub 发布了 CodeQL 2.26.0,其中新增高精度 JavaScript / TypeScript 查询 js/system-prompt-injection。它会报告不可信数据流入 system prompt、developer prompt 或 AI 工具描述的路径。

遇到告警后,可以按下面的最短流程处理:

确认不可信输入源
-> 找到高权限提示词或工具描述 sink
-> 将开放文本移到 user message 或工具参数
-> 确实需要影响可信指令时使用固定 allowlist
-> 重跑 CodeQL 并增加回归测试
-> 单独复核运行时权限

不要把“转义输入”或“在 system prompt 里再强调一次安全规则”当成主要修复。真正的问题是信任边界:攻击者可控文本不应该变成高权限指令。

适合谁

这份清单适合使用 OpenAI、Anthropic、Google GenAI、agent framework 或自定义 tool calling 构建 JavaScript / TypeScript 产品的独立开发者。只要请求参数、数据库内容、上传文件、网页抓取结果、工作区指令或租户配置可能影响 system message 或工具描述,就需要检查这条数据流。

这里讨论的是 AI 应用代码安全,不是如何安全打开陌生仓库。安装或运行第三方代码前,先使用不可信仓库沙箱清单;引入新的 AI 依赖前,再按 npm 包审查清单核对供应链风险。

这次变更是什么,为什么现在值得处理

GitHub 在 2026 年 7 月 10 日宣布 CodeQL 2.26.0。新查询 js/system-prompt-injection 用于发现不可信用户值流入 AI 模型 system prompt 的路径。其查询元数据将它标记为高精度、error、security severity 7.8,并对应 CWE-1427。

同一版本还扩展了 OpenAI、Anthropic 和 Google GenAI SDK 的 JavaScript / TypeScript prompt injection sink。GitHub 的查询说明同时明确了一个容易漏掉的边界:工具描述也是高权限指令。即使 system prompt 是静态的,只要工具描述拼入了用户可控值,攻击者仍可能影响模型行为。

CodeQL 的价值在于把一类 prompt 安全问题转成可审查的 source-to-sink 路径。但它不能证明整个 LLM 应用已经安全,也不能替代对抗测试、鉴权、工具权限限制、输出复核和隔离。它只负责发现一个通常应该移除的代码模式。

实际审查流程

1. 扫描前先列出所有高权限字符串

先搜索应用中构造可信模型上下文的位置:

system message
developer message
agent instructions
工具名称和描述
handoff 或 subagent instructions
缓存的 system content
realtime session instructions

然后标记每个插值变量的来源:常量、开发者配置、租户管理员设置、数据库记录、检索内容或直接用户输入。一个值经过数据库存储,并不代表它自动变成可信数据。

2. 在真实 JavaScript / TypeScript 链路上运行 CodeQL

对于符合条件的 GitHub 仓库,default setup 是维护成本最低的起点:进入 Settings -> Advanced Security -> CodeQL analysis -> Set up -> Default,确认已包含 JavaScript / TypeScript,再运行首次分析。

如果 code scanning 已经启用,需要确认最新分析使用的 CodeQL 版本包含 2.26.0。旧 workflow 即使一直成功,也不代表已经执行新查询。使用 advanced setup 时,应保持标准 JavaScript / TypeScript query pack 为当前版本,避免长期固定在旧 CodeQL bundle。

需要验证覆盖能力时,可以在测试分支构造一条有代表性的最小数据流。使用合成输入,不要把生产 secret 或真实攻击载荷放入测试。

3. 沿完整路径分流,而不是只看高亮代码行

每条 js/system-prompt-injection 告警都记录四项证据:

证据 要回答的问题
Source 哪个请求、文件、数据库字段或检索结果可被攻击者控制?
Transform 中间只是拼接、格式化、解码,还是做了真正的固定值校验?
Sink 数据进入了 system/developer message、工具描述还是其他高权限字段?
Capability 模型行为被影响后,可以访问哪些数据或调用哪些工具?

Capability 决定优先级。一个没有敏感上下文的纯文本助手,和可以读私有文件、查客户数据、发消息或执行工具的 agent,爆炸半径完全不同。两者都要修,但后者需要更高优先级。

4. 根据数据形态选择修复方式

不要试图“清洗”任意自然语言,直接使用下面的决策表:

输入形态 优先修复 示例
开放式用户文本 移到 user message 问题、文档内容、用户指定 persona
很小的封闭集合 使用固定 allowlist 精确校验 teachereditorsupport
工具专用数据 工具描述保持静态,数据走类型化参数 topic、record ID、filename
租户策略 保存结构化策略字段,只渲染已审查模板 允许的语气、locale、approved tools
外部检索内容 明确标为不可信数据,并限制工具权限 网页、issue、邮件、RAG chunk

可以把代码审查原则压缩成一句话:可信提示词定义策略,不可信消息提供数据。 如果用户输入必须选择一种可信行为,应把 allowlist 中的标识映射到服务端模板,而不是直接拼接原始文本。

5. 同时修复相邻的运行时边界

消除静态数据流是必要条件,但还不够。CodeQL 告警消失后,继续检查:

  • system 和 developer prompt 中没有凭据或私密鉴权信息;
  • 工具描述是常量或服务端持有的模板;
  • 工具参数使用 schema 和服务端校验;
  • 鉴权由模型之外的确定性代码执行;
  • 每个工具只有完成任务所需的最小数据和操作范围;
  • 破坏性操作或外部副作用需要 approval gate;
  • 日志能够记录决策,但不会保存 secret 或不必要的完整 prompt。

只要模型可以请求敏感操作,就应假设未来的 prompt injection 可能影响这个请求。最终是否允许执行,仍由服务端决定。

告警分流矩阵

可以把这张表直接放进 PR 或安全 issue:

告警路径 优先级 关闭前必须具备的证据
请求值 -> system/developer prompt -> 带工具模型 关键审查 数据流修复、权限复核、对抗回归测试
检索内容 -> 工具描述 -> agent 关键审查 静态描述、类型化参数、工具鉴权测试
租户设置 -> system prompt 管理员信任模型、固定 schema 或 allowlist、租户隔离测试
用户值 -> system prompt -> 纯文本模型 移到 user role 或 allowlist、输出回归测试
常量 -> system prompt 不属于此漏洞 确认 source 不可变,并用证据关闭

不要因为当前模型拒绝了某个测试字符串就关闭告警。模型行为会变化,代码中的不安全 source-to-sink 关系仍然存在。

常见错误

  • 像处理 SQL injection 一样,只转义引号或大括号。
  • 在 system prompt 里增加“忽略恶意指令”,但仍把用户文本放在其中。
  • 把同一段不可信文本从 system prompt 移到动态工具描述。
  • 用子串匹配代替服务端固定值的精确 allowlist。
  • 模型拒绝一次测试后就关闭告警,没有修改数据流。
  • 因为内容来自数据库或 RAG,就把它当成可信输入。
  • 认为 CodeQL 能覆盖运行时鉴权、间接 prompt injection 和所有框架集成。

FAQ

CodeQL 2.26.0 会在运行时阻断 prompt injection 吗?

不会。CodeQL 做静态分析,报告它支持的 source-to-sink 路径。应用仍需自行实现鉴权、工具 schema、隔离、approval gate 和运行时测试。

所有动态 system prompt 都必须删除吗?

不是。服务端持有的模板,以及通过严格 allowlist 选择的固定值可以合理使用。危险的是开放文本或攻击者可控内容变成可信指令。

把内容移动到 user role 就彻底安全了吗?

它修复了本查询关注的权限边界错误,但不会让模型免疫 prompt injection。工具权限仍要保持最小化,所有安全决策都应由确定性应用代码执行。

CodeQL 不认识我的 AI framework 怎么办?

先人工审查相同的信任边界,再考虑用 CodeQL model pack 或自定义 query 补充缺失的 source / sink。干净的扫描结果,只能证明已建模代码和框架范围内没有命中。

来源

posted @ 2026-07-13 12:15  IndieSeek  阅读(11)  评论(0)    收藏  举报