ARTICLE · 1280607
8 个 AI 工具,0 个补丁:你的登录态明文躺在自家目录
1你硬盘上最值钱的文件,是工具为了记住你才写的
今天 GitHub 日榜上有个项目叫 claude-mem,十万多 star,一天涨了四百多。它的官方介绍我读了两遍:把你 agent 在会话里做的每件事都抓下来,用 AI 压缩,再把相关内容注入到下一次会话里。
同榜还有个 superpowers,三十万 star,今天涨一千多;impeccable 九万五,一天涨两千八。
榜上这几家今年都在干同一件事,给 agent 装记忆。
记忆存在哪?存在磁盘上,落到硬盘里的形态就是文件。
这就是今天这个话题的入口。Symantec 十月十五号发了一份报告,讲一个叫 Aoki 的信息窃取器。这东西最近新加了一项本事,专门去翻 AI 编程工具的凭证文件。报告原文列了张单子:.claude.json、Claude 桌面版的 cookies、ChatGPT 的 cookies、Codex 的 config.toml 和 .env,此外还有 GitHub Copilot、Cursor、Google Gemini、JetBrains AI Assistant、Kiro 的 token,以及 AWS 凭证。
数一下点了几家:Claude、ChatGPT、Codex、GitHub Copilot、Cursor、Google Gemini、JetBrains AI Assistant、Kiro,8 个 AI 工具。它们的登录态全在你自己的用户目录里,有的直接在 ~ 下面,有的在 macOS 的 ~/Library/Application Support 或 Windows 的 %APPDATA% 里。位置不一样,共同点是都在你这台机器上,在你名下。
报告里有一句话写得很清楚:它偷的是凭证、令牌和会话文件,不是源码。唯一的例外是 Cursor 的本地状态数据库,那个库会缓存对话上下文和代码片段。
所以你担心的「AI 把我的代码传到哪去了」,跟这个木马关系不大。它要的是「你是谁」的证明。
2这个洞补不了,因为没有哪个地方坏了
有人第一反应肯定是,那我等 Cursor 出个补丁、等 Claude 出个更新不就完了。
补不了。这些文件之所以在那儿,是因为工具必须记住你是谁。你今天打开编辑器不用重新登录,是因为你昨天登过,那份登录凭证落在了盘上。把这条抹掉,工具就得每次开机问你一遍密码。产品逻辑上它不能那么做。
按 Check Point 同月另一份报告的说法,这类木马走的是扫本地应用存储这条路,没有去利用这些产品本身的漏洞。Symantec 那份的描述也一样,它只是把能找到的文件挨个带走。这里没有一个 CVE 编号能堵,因为没有哪个环节是坏的。
前几天我写过,agent 的 deny 规则不是安全边界,那说的是 agent 被允许做什么。今天说的是 agent 必须记住的东西存在哪。一个讲权限,一个讲存放,两件事,别混着看。
时间点也不能略过。报告原话是,早期版本的木马完全不碰 AI 相关文件,这说明针对 AI 助手是一个此前没被报告过的新动向。翻成普通话就是:过去两年你把这些文件搁在那儿一直没事,不是因为安全,是因为没人惦记。现在有人惦记了。
3一把 AI key 是账单,一把私钥是服务器
这里得给那些觉得「key 泄露了换一个就行」的人泼一盆冷水。
Aoki 那一次扫描带走的东西,AI 凭证只占很小一块。
同一份报告还列了这些:几十种浏览器的 cookie、自动填充、信用卡和历史记录;加密钱包的浏览器扩展和桌面客户端;Discord 和 Telegram 的会话文件;FileZilla、WinSCP、CoreFTP 这些 FTP 工具的站点配置;OpenVPN、NordVPN、ProtonVPN 的配置;KeePass、Bitwarden、1Password、Dashlane 这些密码管理器的数据。
它还专门记了一笔,你机器上装了哪些安全产品。
Check Point 那边补了一条:Windows 版本里有个模块专收 Git 凭证、.ssh 目录下的私钥,以及 AWS、Azure、Google Cloud 的凭证文件。
这就不是一个量级的损失了。一把 AI key 漏出去,最坏结局是有人拿你的额度跑 LLMjacking,你月底看账单心跳加速,换 key,止损。一把 .ssh 私钥漏出去,是有人能登进你的服务器。WinSCP 里存的那份站点密码,是你三年前图省事勾的一下「保存密码」。
报告里还有一句我印象很深,它把攻击者的算盘说透了:AI 凭证可以像卡数据一样直接变现,但跟卡数据不一样的地方在于,它还能给攻击者一条通往这个开发者整个环境的通道。
4它从 HTTP 换成了 HTTPS,跟你的处境没关系
报告里有个细节,转述的文章基本都没提。
早期样本怎么传数据?一个 IP 地址,8080 端口,明文 HTTP。新样本换成了一个域名,走 /gate 这个路径,其中两个新样本还各自用了自己的域名。
看到这个变化,第一反应往往是它升级了、更难防了。方向反了。这个变化说明它开始用域名躲检测,传输这一段也加密了。但它加密的是从你机器到它服务器的那一段,跟它能不能读你硬盘上的 .claude.json 一点关系都没有。你在自己机器上装十张证书,也不会让它少读一个字节。
另一条更值得记住:这个木马没有后门指令列表。报告原话是,它把能拿到的数据都收走,然后发回 C&C 服务器。没有指令列表意味着,对面没有人在敲键盘挑东西,这是一台收割机,路过就全割。你没法赌「我这点东西人家看不上」。
还有几件事这份报告没说,我觉得这恰恰是它可信的地方。它没说这个木马是怎么进到你机器里的,没给受害数量,也没把它归到任何已知家族,原话是不知道背后是哪个组织。这几项空着就是空着。谁要是给你补上一套传播途径的说法,那不是这份报告写的。
5今晚二十分钟能做完的三件事
下面三件都不用装任何软件。
第一件,清点。你连自己盘上有什么都不知道,谈防护是空的。这段脚本纯标准库,不联网、不打开文件、不读内容,只干四件事:看这些文件在不在、权限位是什么、有没有被 git 跟踪、有没有躺在同步盘目录里。存成 查凭证暴露.py,python 查凭证暴露.py 直接跑。
#!/usr/bin/env python3
# 查凭证暴露.py
# 只 stat 不读内容 / 不联网 / 纯标准库 / Windows macOS Linux 通用
# 用法: python 查凭证暴露.py
import os
import stat
import subprocess
import sys
H = os.path.expanduser("~")
WIN = os.name == "nt"
def app(*p):
# 各平台的「应用数据」目录
if WIN:
b = os.environ.get("APPDATA", os.path.join(H, "AppData", "Roaming"))
elif sys.platform == "darwin":
b = os.path.join(H, "Library", "Application Support")
else:
b = os.environ.get("XDG_CONFIG_HOME", os.path.join(H, ".config"))
return os.path.join(b, *p)
# 分类, 名称, 默认路径(装在别处就改这里)
T = [
("AI", ".claude.json", os.path.join(H, ".claude.json")),
("AI", "Codex config.toml", os.path.join(H, ".codex", "config.toml")),
("AI", "Codex .env", os.path.join(H, ".codex", ".env")),
("AI", "Claude 桌面版 cookies", app("Claude", "Cookies")),
("AI", "Cursor state.vscdb", app("Cursor", "User", "globalStorage", "state.vscdb")),
("AI", "VS Code state.vscdb", app("Code", "User", "globalStorage", "state.vscdb")),
("云", "AWS credentials", os.path.join(H, ".aws", "credentials")),
("云", "AWS config", os.path.join(H, ".aws", "config")),
("云", "GCP 应用默认凭证", os.path.join(H, ".config", "gcloud",
"application_default_credentials.json")),
("云", "Azure CLI 登录态", os.path.join(H, ".azure", "accessTokens.json")),
("运维", "SSH 私钥 id_rsa", os.path.join(H, ".ssh", "id_rsa")),
("运维", "SSH 私钥 id_ed25519", os.path.join(H, ".ssh", "id_ed25519")),
("运维", "SSH config", os.path.join(H, ".ssh", "config")),
("运维", ".git-credentials", os.path.join(H, ".git-credentials")),
("运维", "FileZilla sitemanager.xml", app("FileZilla", "sitemanager.xml")),
("运维", "WinSCP.ini", app("WinSCP.ini")),
]
SYNC = ("onedrive", "dropbox", "google drive", "icloud drive", "nutstore",
"坚果云", "baidunetdisk", "百度网盘", "syncthing", "pcloud", "megasync", "微云")
def git_tracked(p):
# 文件是否被所在 git 仓库跟踪: True / False / None
d = os.path.dirname(os.path.abspath(p))
while True:
if os.path.exists(os.path.join(d, ".git")):
rel = os.path.relpath(os.path.abspath(p), d).replace(os.sep, "/")
try:
r = subprocess.run(
["git", "-C", d, "ls-files", "--error-unmatch", "--", rel],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=10)
return r.returncode == 0
except (OSError, subprocess.SubprocessError):
return None
up = os.path.dirname(d)
if up == d:
return None
d = up
found = 0
for cat, name, p in T:
if not os.path.exists(p):
print("[无] %-4s %s" % (cat, name))
continue
found += 1
st = os.stat(p)
if WIN:
risk = "win 权限位不可信,用 icacls 看 ACL"
elif st.st_mode & stat.S_IROTH:
risk = "其他用户可读"
elif st.st_mode & stat.S_IRGRP:
risk = "同组可读"
else:
risk = "仅本人可读"
g = git_tracked(p)
sync = next((m for m in SYNC if m in p.lower().replace("\\", "/")), None)
print("[有] %-4s %s" % (cat, name))
print(" %s" % p)
print(" %d 字节 %s %s" % (st.st_size, stat.filemode(st.st_mode), risk))
print(" git: %s" % ("已被跟踪,别提交" if g else ("未跟踪" if g is False else "判断不了")))
print(" 同步盘: %s" % ("命中 %s,会同步到云端和其他设备" % sync if sync else "无"))
print("")
print("命中 %d / %d 项" % (found, len(T)))
print("有是常态,不是中招。看三样:权限、是否被 git 跟踪、是否落在同步盘。")
跑完你会得到一张表,比任何安全建议都具体。看到「其他用户可读」就先改掉,看到「已被跟踪」就 git rm --cached 再加进 .gitignore,看到「落在同步盘」就要知道,这份凭证现在同时在云端和你登录过的每台设备上。
第二件,把 AI key 和私钥分开处置。AI key 的处置很简单:去各家后台看用量、设额度上限、该轮换就轮换。私钥要认真一点,.ssh 下没口令的先加口令,能换成短期凭证的换成短期凭证。Check Point 给企业用户的建议就是朝这个方向,减少端点上的长寿命密钥。这条对个人同样成立。
第三件,把「保存密码」这个勾从 FTP 和 VPN 客户端里去掉。FileZilla 和 WinSCP 的站点配置是这次的重点目标之一,而你当年勾那个框,只是为了少打一次密码。
顺手提一句这套动作的边界。它不会让你变成打不穿的机器,它只做一件事,假设明天这台电脑上的文件全被带走,你今晚能少损失多少。
6今天的干货
公众号正文不支持外链跳转,下面这些地址点不开。长按选中整条,复制到浏览器就能进。最该先看第 1 条:Symantec 那份报告的原文,文件路径那张表就在里面,本篇所有事实都从那两句原话出来;第 2、3 条是你要动手轮换 key 的两个后台,都需要先登录。
1、Symantec 原始报告(10-15) —— Aoki 到底翻了哪些文件、原话怎么说「偷的是凭证不是源码」、为什么说这是此前没被报告过的新动向。十分钟能读完。
https://www.security.com/threat-intelligence/aoki-infostealer-ai-targeting
2、Anthropic 后台的 API key 页 —— Claude / Claude Code 用的 key 在这页轮换。顺手看一眼创建时间,两年前的今天就换掉。需登录。
https://console.anthropic.com/settings/keys
3、OpenAI 平台的 API key 页 —— Codex / ChatGPT 相关的 key 在这页。轮换前先看 Usage,异常用量比任何告警都直接。需登录。
https://platform.openai.com/api-keys
十年前我们这行防的是代码被偷,于是有了私有仓库、密钥管理和代码审计。今天这些工具为了帮上忙,必须记住我们是谁、看过什么、想干什么,然后把那些东西写成了硬盘上的一堆明文文件。这件事不会有补丁,因为它不是错误,它是产品长成这样的结果。















































































