GlassWorm供应链攻击深度分析:433个组件被植入恶意代码,不可见Unicode技术首次大规模应用

2026年3月,GlassWorm供应链攻击活动在16天内感染了GitHub、npm和VSCode/OpenVSX平台上的433个组件。攻击者使用不可见Unicode字符隐藏恶意代码,窃取开发者的Git、npm和GitHub凭据,并清空加密货币钱包。这是有记录以来最大规模的同时针对三大开发平台的供应链攻击。
攻击规模与时间线
GlassWorm攻击活动于2026年3月3日至3月19日期间展开,攻击者以高度协调的方式同时渗透了GitHub、npm和VSCode/OpenVSX Extensions三个核心开发平台。
攻击规模统计:
| 平台 | 受感染数量 | 类型 | 时间窗口 |
|---|---|---|---|
| GitHub | 151+ | 代码仓库 | 2026-03-03至03-09 |
| npm | 210+ | 包 | 2026-03-05至03-19 |
| VSCode/OpenVSX | 72 | 扩展 | 2026-01-31起持续 |
| 合计 | 433+ | 组件 | 约7周 |
这次攻击的独特之处在于其跨平台协调性。传统的供应链攻击通常针对单一包管理器(如npm或PyPI),而GlassWorm同时在三个平台上部署了相互配合的恶意载荷,形成了一个完整的攻击生态链。
Grand Linux的安全研究人员指出,GlassWorm并非全新的攻击活动——它是2025年末首次出现的同名攻击的升级版本。2026年3月的这次活动在攻击规模、技术复杂度和隐蔽性上都有显著提升。
不可见Unicode:恶意代码的隐身术

GlassWorm最引人注目的技术特征是使用不可见Unicode字符来隐藏恶意代码。这种技术利用了Unicode标准中大量不产生可见输出的字符,如零宽空格(U+200B)、零宽连接符(U+200D)、从右到左标记(U+200F)等。
技术原理:
正常的JavaScript代码:
// 看起来是一个普通的工具函数
function processData(input) {
return input.trim().toLowerCase();
}
被注入不可见Unicode后:
function processData(input) {
// 下一行包含不可见的恶意代码(用[ZWSP]表示零宽空格)
// [ZWSP][ZWSP][ZWSP]eval(atob("恶意Base64载荷"))[ZWSP][ZWSP]
return input.trim().toLowerCase();
}
在代码编辑器和GitHub的代码审查界面中,这些不可见字符完全不可见,审查者无法通过肉眼发现异常。但在JavaScript运行时中,这些字符会被正常解析和执行。
BleepingComputer的技术分析显示,GlassWorm使用的不可见Unicode技术包括:
- 零宽字符注入:在合法代码的间隙插入零宽字符,组成隐藏的恶意语句
- 同形异义字符替换:使用外观相似的Unicode字符替换ASCII字符(如用西里尔字母"а"替换拉丁字母"a")
- 方向控制字符:利用RTL/LTR标记改变文本显示顺序,使恶意代码在编辑器中看起来是正常的注释
攻击载荷分析
GlassWorm的恶意载荷是一个多阶段攻击链,具有以下功能:
第一阶段:信息窃取
- 窃取Git凭据(.gitconfig、.git-credentials)
- 窃取npm认证令牌(.npmrc)
- 窃取GitHub个人访问令牌(PAT)
- 窃取SSH私钥(.ssh/)
第二阶段:加密货币盗窃
- 扫描本地加密货币钱包文件
- 替换剪贴板中的加密货币地址为攻击者地址
- 注入浏览器扩展以拦截Web3交易
第三阶段:持久化与传播
- 使用窃取的npm令牌向更多包发布恶意版本
- 使用窃取的Git凭据向更多仓库提交恶意代码
- 形成自我传播的"蠕虫"效应
// GlassWorm恶意载荷的行为特征(简化示例)
// 警告:仅供安全研究,切勿在生产环境运行
// 检测运行环境
const isDev = process.env.NODE_ENV !== 'production';
const isCI = process.env.CI === 'true';
// 信息收集
const collectCredentials = () => {
const paths = [
`${process.env.HOME}/.gitconfig`,
`${process.env.HOME}/.git-credentials`,
`${process.env.HOME}/.npmrc`,
`${process.env.HOME}/.ssh/id_rsa`,
];
// 读取并外传...
};
// 剪贴板地址替换
const replaceClipboard = () => {
// 监控剪贴板,将加密货币地址替换为攻击者地址
};
开源生态的信任危机

GlassWorm事件暴露了开源软件供应链中的深层信任问题。npm每周下载量超过数十亿次,GitHub托管着全球最大的代码仓库集合,VSCode是使用最广泛的代码编辑器——当这三个平台同时被攻陷时,影响范围几乎无法估量。
npm生态的脆弱性: npm的去中心化设计意味着任何人都可以发布包,而包的维护者账户安全完全依赖个人。GlassWorm利用窃取的维护者令牌直接向合法包发布恶意版本,绕过了所有的代码审查机制。
GitHub的信任模型缺陷: GitHub的Fork和Pull Request机制建立在"代码可审查"的前提上,但不可见Unicode技术从根本上打破了这个前提——代码审查者无法审查他们看不见的东西。
VSCode扩展市场的安全隐患: VSCode扩展拥有与本地应用程序几乎相同的权限,可以访问文件系统、执行命令、发起网络请求。72个被感染的扩展意味着数百万开发者的开发环境可能已被渗透。
检测与清理方法
# 检查npm包是否包含不可见Unicode字符
find node_modules -name "*.js" -exec grep -Pl '[\x{200B}\x{200C}\x{200D}\x{FEFF}]' {} \;
# 使用npm audit检查已知恶意包
npm audit --json | jq '.vulnerabilities | to_entries[] | select(.value.severity == "critical")'
# 检查Git仓库中的异常提交
git log --all --oneline --since="2026-03-01" --until="2026-03-20" \
--author="$(git config user.name)" --diff-filter=A -- "*.js"
# 检查VSCode扩展列表
code --list-extensions --show-versions | while read ext; do
echo "$ext"
done
# 扫描npmrc中的令牌
cat ~/.npmrc 2>/dev/null | grep -i "authToken\|_auth"
#!/usr/bin/env python3
"""GlassWorm Invisible Unicode Scanner"""
import os
import re
import sys
# 零宽和不可见Unicode字符的正则表达式
INVISIBLE_CHARS = re.compile(
'[\u200b\u200c\u200d\u200e\u200f\u202a\u202b\u202c\u202d\u202e'
'\u2060\u2061\u2062\u2063\u2064\ufeff\u00ad\u034f\u061c\u115f'
'\u1160\u17b4\u17b5\u180e\u3164\uffa0]'
)
def scan_file(filepath):
"""Scan a single file for invisible Unicode characters"""
findings = []
try:
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
for lineno, line in enumerate(f, 1):
matches = INVISIBLE_CHARS.findall(line)
if matches:
findings.append({
'file': filepath,
'line': lineno,
'count': len(matches),
'chars': [f'U+{ord(c):04X}' for c in set(matches)]
})
except Exception as e:
pass
return findings
def scan_directory(path):
"""Recursively scan directory for JS/TS files with invisible chars"""
all_findings = []
for root, dirs, files in os.walk(path):
# Skip node_modules internals for speed
dirs[:] = [d for d in dirs if d != '.git']
for f in files:
if f.endswith(('.js', '.ts', '.jsx', '.tsx', '.mjs')):
filepath = os.path.join(root, f)
findings = scan_file(filepath)
if findings:
all_findings.extend(findings)
return all_findings
if __name__ == "__main__":
target = sys.argv[1] if len(sys.argv) > 1 else "."
print(f"Scanning {target} for invisible Unicode characters...")
results = scan_directory(target)
if results:
print(f"\n[!] Found {len(results)} suspicious locations:")
for r in results[:50]:
print(f" {r['file']}:{r['line']} - {r['count']} invisible chars: {', '.join(r['chars'][:5])}")
else:
print("[+] No invisible Unicode characters detected")
防御建议
开发者层面:
- 立即检查并轮换所有npm、GitHub和Git凭据
- 启用npm的双因素认证(2FA)
- 使用npm的
--ignore-scripts安装依赖,减少安装时执行恶意代码的风险 - 在代码编辑器中启用"显示不可见字符"功能
- 使用工具(如上述Python脚本)定期扫描项目中的不可见Unicode字符
组织层面:
- 建立私有npm镜像,只同步经过审查的包
- 实施依赖锁定(package-lock.json)并验证哈希值
- 在CI/CD流水线中集成供应链安全扫描
- 对VSCode扩展实施白名单管理
- 定期审计开发者的访问令牌和凭据
# 启用npm的审计签名验证
npm config set audit-signatures true
# 使用npm ci替代npm install(严格依赖锁定文件)
npm ci --ignore-scripts
# 锁定npm版本并启用2FA
npm profile enable-2fa auth-and-writes
对软件供应链安全的长远影响
GlassWorm标志着供应链攻击进入了一个新阶段。不可见Unicode技术的首次大规模应用意味着传统的代码审查方法已经不足以保证代码安全。开发工具链需要引入新的检测机制来识别这类隐蔽威胁。
更重要的是,GlassWorm展示了供应链攻击的"蠕虫"特性——一旦一个维护者账户被攻陷,其发布的恶意代码可以自动传播到所有依赖该包的项目,形成指数级扩散。这种攻击模式对现有的软件分发信任模型构成了根本性挑战。
数据来源与参考文献:
- BleepingComputer. "GlassWorm malware hits 400+ code repos on GitHub, npm, VSCode OpenVSX." bleepingcomputer.com, 2026-03.
- Grand Linux. "Supply Chain Attack 2026 — GlassWorm Embeds Malware in 400+ Projects." grandlinux.com, 2026-03-28.
- CinchOps. "GlassWorm Malware Hits 400+ Code Repos with Invisible Payloads." cinchops.com, 2026.
- The ByteDive. "Supply Chain Attack 2026: $81B Threat Evolution." thebytedive.com, 2026-03-11.
- LinkedIn/Bob Miller. "Chris and Bob Quick Pick - #013 Glassworm Returns." linkedin.com, 2026.
评论