CodeQL 2.26.3:Actions污点边界变了
CodeQL 2.26.3 这次更新里,我最关注的不是新增了多少查询,而是 GitHub Actions 的“可信输入边界”发生了几处很具体的调整。
官方列出的变化包括:
merge_group 事件中的 github.event.merge_group
现在会被识别为不可信数据来源
以及:
移除 codeql.actions.security.SelfHostedQuery
原因很直接:
Runner Label 不能可靠区分 Self-hosted Runner 和 Managed Runner。
这两条变化都在提醒同一件事:
CI 安全查询最容易犯的错误,就是把“看起来像可信”的元数据当成真正可信边界。
对写 GitHub Actions、自定义 CodeQL Query 和 Agent 自动修改 CI 的团队来说,这个版本值得认真过一遍。
merge_group为什么值得单独处理
很多团队现在开启 Merge Queue。
Workflow 可能监听:
on:
merge_group:
过去自定义查询如果只重点考虑:
pull_request
pull_request_target
workflow_dispatch
很可能漏掉 merge_group 的输入传播。
CodeQL 2.26.3 现在把:
github.event.merge_group
识别为不可信数据。
这意味着类似:
- run: |
echo "${{ github.event.merge_group.some_field }}"
如果进一步进入:
Shell
Path
Environment
就应该进入数据流分析。
不可信不是等于“恶意”,而是不能直接相信
这是安全建模里很重要的区别。
merge_group 数据不是说一定来自攻击者。
而是:
它受外部仓库事件影响
所以如果直接进入高权限步骤,就可能形成输入传播风险。
例如:
Untrusted Event Data
↓
env
↓
shell
↓
privileged step
这才是 CodeQL 真正在建模的东西。
SelfHostedQuery被删很值得注意
GitHub 明确说,codeql.actions.security.SelfHostedQuery 被移除,因为:
runner labels
不能可靠区分
self-hosted 和 managed runner
这非常现实。
很多 Query 会写:
if label == "self-hosted"
then high risk
问题是企业内部 Runner Label 往往是:
linux
x64
large
secure
gpu
internal
甚至 Managed Runner 也可能有类似标签。
所以:
字符串标签
不是可靠的安全身份。
如果你有自定义 Query 依赖这个模块,需要尽快改。
Runner身份最好来自确定性配置源
企业内部可以维护:
Runner Group ID
Runner Registration Source
Org Policy
Environment
而不是从 YAML Label 猜。
安全逻辑:
runner_is_trusted
最好来自:
组织配置
而不是:
名字里有没有 self-hosted
CodeQL 2.26.3还修了Actions缓存投毒判断
官方提到多条:
actions/cache-poisoning/code-injection
actions/cache-poisoning/direct-cache
actions/cache-poisoning/poisonable-step
现在会考虑低信任触发器对默认分支 Cache Scope 是否拥有:
read-only
如果低信任事件只能读取缓存,不能写:
不应该继续把它判成可投毒路径
这能减少误报。
安全扫描真正有用的前提不是“报得多”。
而是:
Source
→ Data Flow
→ Sink
→ 权限
都建模正确。
为什么Cache Poisoning特别容易误报
假设:
pull_request
只能读默认分支 Cache。
Query 如果只看到:
低信任事件
+
Cache
就报警:
Possible Poisoning
会产生大量无效告警。
真正投毒还需要:
attacker can write cache
所以权限语义必须进入数据流模型。
envvar injection也更严格了
2.26.3 调整:
actions/envvar-injection/critical
要求:
untrusted source
和
privileged context
来自同一个 trigger event
同时不再把 PR Head Label 当作可注入换行的来源,因为它不能包含换行。
这也是很典型的误报修正。
如果一个 Query 没理解:
字段实际字符约束
只因为它“用户可控”,就判注入,噪声会很大。
写自定义Query时,别只问“是否用户可控”
还要问:
可控到什么程度?
允许哪些字符?
在哪个事件里?
是否同一个信任边界?
最终Sink如何解析?
例如:
branch name
label
title
body
environment
虽然都可能是外部输入,但风险完全不同。
CodeQL还修了output clobbering的性能问题
官方说明:
actions/output-clobbering/high
不再对仍保持 JSON Encode 的简单 jq Path Filter 报警,同时修复了由未转义正则输入引起的性能问题。
这一条对大型仓库很重要。
静态分析如果一个 Query 自己跑得过慢:
扫描超时
CI排队
开发者关闭规则
最后安全收益反而下降。
所以 Query Performance 本身也是工程质量。
我会给自定义Query做性能基线
至少记录:
Repo Size
Query Time
Peak Memory
Result Count
每次 CodeQL 版本升级后重跑。
例如:
codeql-regression:
max-query-time-regression: 20%
max-alert-growth: 30%
如果某个 Query:
结果从 20 条变 1200 条
不要直接上线。
先看:
是真发现更多
还是模型变化制造噪声
JavaScript/Vue这次也补了几个真实数据流模型
官方新增:
ref
shallowRef
toRef
reactive
computed
等 Vue Composition API Helper 的 Flow Model。
同时 useRoute() 的:
query
params
path
fullPath
hash
被识别为客户端远程数据来源。
这会直接影响:
XSS
Path Injection
URL相关数据流
的发现能力。
如果你的前端大量使用 Vue 3,这个版本比单纯 Actions 更新更值得升级。
一个Vue Router例子
const route = useRoute()
const next = route.query.next
window.location.href = next
route.query.next 本质上来自 URL。
如果 Query 模型不知道:
useRoute()
是 Source,后面的数据流可能根本连不起来。
2.26.3 把这层模型补上以后,类似路径更容易进入分析。
Sails Action2也被补成Remote Source
声明的:
inputs
现在会被识别为远程数据源。
这可能影响:
js/path-injection
等查询。
如果你有 Sails 老项目,这类框架模型比新增一条泛化 Query 更有价值。
@fastify/rate-limit也被识别了
js/missing-rate-limiting 现在认识:
@fastify/rate-limit
这能降低一种常见误报:
实际上已经有Rate Limit
但分析器不认识框架
框架模型越准确,安全报告才越有用。
升级CodeQL前我会做两组回归
第一组:
Alert Regression
比较:
旧版
新版
每个 Query:
新增多少
消失多少
Severity变化
第二组:
Performance Regression
比较:
扫描时间
CPU
Memory
不要只看:
“新版支持更多规则”
一个升级报告
{
"from": "2.26.2",
"to": "2.26.3",
"new_alerts": 38,
"resolved_by_model_change": 12,
"query_time_delta": "+8.4%",
"critical_new": 2,
"custom_query_failures": [
"internal/self-hosted-runner-check"
]
}
尤其要找:
custom_query_failures
因为 SelfHostedQuery 这类 Breaking Change 会直接让内部 Query Pack 失败。
自定义Query必须固定CodeQL版本测试
如果你维护:
security/codeql-custom
CI 至少跑:
当前生产版本
+
目标升级版本
避免 GitHub.com 自动升级后,自定义 Query 才突然坏。
GitHub.com 会自动部署新版 CodeQL;GHES 则会在未来版本包含这些功能,旧 GHES 可以手动升级 CodeQL。
环境不同,升级节奏也要分开管理。
Agent自动改Workflow时,更应该先跑CodeQL
Coding Agent 很喜欢修改:
.github/workflows/*.yml
而 Workflow 本身就是高风险代码。
我会给 Agent 的 PR Gate 单独加:
Actions CodeQL
而且:
Workflow Change
一律提高 Review Risk。
if path.startswith(".github/workflows/"):
risk += 5
不要把 CI YAML 当普通配置。
一个最小CI Gate
security:
codeql:
version: "2.26.3"
required:
- actions
- javascript-typescript
block:
severity:
- critical
- high
如果有自定义 Query Pack,再锁:
pack version
避免环境漂移。
CodeQL 2.26.3 这次最值得关注的,不是“多支持了几个框架”。
而是它连续修正了几种:
信任边界建模
包括:
merge_group
runner identity
cache write capability
event source relation
Vue route source
这类变化决定静态分析到底是在:
理解真实攻击路径
还是只做字符串匹配。
对企业来说,升级 CodeQL 最重要的动作也不是点击“升级”。
而是跑一遍:
Query Compatibility
Alert Delta
Performance Delta
特别是内部自定义 GitHub Actions Query。
因为安全扫描器的版本变化,本身也应该像业务代码一样进入回归测试。
更多企业级 AI 应用、Agent、RAG 与模型工程化内容,我会继续整理在 智元界:
https://www.zyentor.com/