flawopen.com/Teardowns/cve-2026-102422-shell-quote-comment-line-terminator-injection
CVE-2026-102422:shell-quote 注释令牌注入
在 shell-quote 1.11.0 之前,注释令牌后跟含有行终止符的字符串时,若将引用后的输出交给 POSIX shell,输出含义可能改变。该问题要求攻击者能影响令牌、应用调用 quote(),并由 shell 执行其输出;请升级到 1.11.0 或更高版本。
标签上的注释可以隐藏本行后面的内容。如果标签的下一部分含有换行符,注释会提前结束,后面的内容又会显现。这个缺陷使后续令牌能在供 shell 解析的引用输出中造成这种效果。
核心概念与专有名词
shell-quote- 用于解析和引用 shell 风格令牌的 JavaScript 软件包;其输出仍是 shell 语法,不是通用安全字符串格式。
注释令牌- 表示 shell 注释语法的令牌,其作用可延续到后续文本,直到遇到行终止符。
行终止符- CR、LF、U+2028 或 U+2029 等行边界;shell 可能将其视为注释结束。
CWE-78- 未正确中和操作系统命令中的特殊元素。
框架映射
- 本指南所述弱点的 CWE 参考: CWE-78
根本原因剖析 (Root Cause)
受影响的 quote() 路径会拒绝注释令牌本身包含行终止符的情况,却没有记录注释是否已经输出。因此,后续字符串令牌仍可包含行终止符。当攻击者可影响的令牌传入 quote(),且返回文本由 POSIX shell 执行时,行边界会结束注释,shell 随后把后续文本解析为语法。上游修复会记录注释状态,并拒绝所有后续字符串令牌中的行终止符。这与 CVE-2026-9277 不同:后者的修复针对注释令牌自身的行终止符。维护者评为 High,CVSS 3.1 8.1;Ubuntu 另行给出 CVSS 4.0 9.2 Critical 评估。两者使用不同 CVSS 版本,不能直接互换。
攻击执行流程分解
令牌进入引用函数
应用构造包含注释令牌及后续字符串的序列;攻击者必须能够影响该序列。
函数输出注释语法
在 1.11.0 之前,quote() 会检查注释文本,却不会记住后面还有字符串令牌。
后续令牌含有行边界
CR、LF、U+2028 或 U+2029 可结束 shell 注释。
应用通过 shell 执行输出
文档所述的 shell 解释仅适用于将该输出交给 POSIX shell 的调用方。
升级后拒绝危险序列
1.11.0 会记录注释状态;如果后续字符串含行终止符,就抛出错误。
源代码对比:漏洞与安全实现
有缺陷的代码片段会检查注释令牌中的行终止符,但不会为后续字符串记录状态。上游修改会记录注释已输出,并拒绝包含行终止符的后续字符串。此片段用于说明解析与引用的边界,不是漏洞利用代码或 shell 命令。
源码摘录: quote.js — focused upstream diff hunks
// commit 6002b2e 之前的 quote.js——注释令牌相关片段
if ('comment' in s && typeof s.comment === 'string') {
if (LINE_TERMINATORS.test(s.comment)) {
throw new TypeError('`comment` must not contain line terminators');
}
return '#' + s.comment;
}
// commit 6002b2e 之后的 quote.js——新增校验和注释状态的精确片段
var sawComment = false;
return xs.map(function (s) {
if (sawComment && typeof s === 'string' && LINE_TERMINATORS.test(s)) {
throw new TypeError('a token after a `comment` must not contain line terminators');
}
if ('comment' in s && typeof s.comment === 'string') {
if (LINE_TERMINATORS.test(s.comment)) {
throw new TypeError('`comment` must not contain line terminators');
}
sawComment = true;
return '#' + s.comment;
}
});
工程与系统安全加固清单
- ✓将直接及间接依赖的
shell-quote升级至 1.11.0 或更高版本;检查锁文件和部署产物中的实际解析版本。 - ✓不要把
quote()当成适用于任意上下文的安全函数,也不要用它替代避免调用 shell。 - ✓尽可能使用
shell: false,通过参数数组启动固定可执行程序,并按目标程序要求校验每个参数。 - ✓若必须使用 shell,应固定命令结构,并在调用前拒绝注释令牌后跟行终止符的序列。
- ✓为后续字符串中的 CR、LF、U+2028、U+2029 添加回归测试,也覆盖由
parse()生成的令牌。 - ✓检查将攻击者可影响令牌传给
quote()并执行输出的调用点;仅使用该软件包并不能证明可利用。 - ✓不要根据 npm 版本推断 Ubuntu 软件包状态;请核对对应发行版公告。