<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>证书 on Trevor's Blog</title><link>http://mings.in/tags/%E8%AF%81%E4%B9%A6/</link><description>Recent content in 证书 on Trevor's Blog</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Tue, 03 Nov 2026 09:10:00 +0800</lastBuildDate><atom:link href="http://mings.in/tags/%E8%AF%81%E4%B9%A6/index.xml" rel="self" type="application/rss+xml"/><item><title>eMudhra 证书链出事，我把 JetBrains 全家体检了</title><link>http://mings.in/posts/emudhra/</link><pubDate>Tue, 03 Nov 2026 09:10:00 +0800</pubDate><guid>http://mings.in/posts/emudhra/</guid><description>八张中间证书私钥可还原，四张根证书要拉黑。跟着 JetBrains 公告自查之后我发现：官方 workaround 只删两把，我机器上四把都在，三个 JVM 一个都没修。</description><content:encoded><![CDATA[<p>十月十七号，一个安全研究员报告：eMudhra 签发的八张中间证书，私钥可以还原出来，因为它们生成时用的熵有问题。</p>
<p>这意味着任何能插你网络的人，都能拿这几把私钥签一张「看起来可信」的证书，冒充 JetBrains 的工具要连的服务。</p>
<p>十月三十号 JetBrains 发了两篇公告。一篇讲 IDE 怎么办，一篇是全线产品的状态表。我看了一圈中文转载，基本都是转述，没人真去机器上查。</p>
<p>这篇就是那份自查手册。全程本机命令，不改任何配置。</p>
<h2 id="官方到底说了什么">官方到底说了什么</h2>
<p>受影响的是用 Java 跑的东西。IDE、Toolbox、Gateway、ReSharper，因为它们信任的是随包分发的 JetBrains Runtime 的信任库，不是你 macOS 系统的钥匙串。</p>
<p>公告里写得很直白：更新操作系统对这一类问题没有保护作用。</p>
<p>修复版 JBR 不再信任这四张根证书：emSign ECC Root CA G3、emSign Root CA G1、emSign Root CA G2、AAA Certificate Services。</p>
<p>拆开看是四个 CVE：CVE-2026-91403 和 CVE-2026-114820 是 Oracle 在 JBR 里做的修复，CVE-2026-118696 是内置浏览器 JCEF 拿 Chrome 的证书更新列表，CVE-2026-118697 是后台服务 jetbrainsd 自己那份内置清单。</p>
<p>三层，各自修。</p>
<p><img alt="一条事件，三层修复：JBR、JCEF、jetbrainsd" loading="lazy" src="/images/emudhra/fig1.png"></p>
<h2 id="第一步先看版本对不对得上">第一步：先看版本对不对得上</h2>
<p>别急着删证书，先确认你装的是哪个版本。JetBrains 的 <code>.app</code> 里有个 Info.plist，构建号就在里面。</p>
<pre tabindex="0"><code>/usr/libexec/PlistBuddy -c &#39;Print :CFBundleShortVersionString&#39; \
  &#34;/Applications/Android Studio.app/Contents/Info.plist&#34;
/usr/libexec/PlistBuddy -c &#39;Print :CFBundleVersion&#39; \
  &#34;/Applications/Android Studio.app/Contents/Info.plist&#34;
</code></pre><p>把路径换成你装的 IDE 就行，Toolbox 装的在 <code>~/Applications</code> 下面。</p>
<p>我机器上的结果：</p>
<ul>
<li>IntelliJ IDEA 2026.2.3，构建 IU-262.10968.63，打包的 JBR 是 25.0.4+1-508.27</li>
<li>Android Studio 2026.2，构建 AI-262.9437.185.2621.16467767，JBR 25.0.3</li>
<li>JetBrains Toolbox 3.9.1，构建 3.9.1.89198</li>
</ul>
<p>对照公告的修复列表：IDEA 要 2026.2.4 才算修，我这是 2026.2.3，差一个补丁。Toolbox 3.9.1 在修复名单里，这项过了。</p>
<p>Android Studio 是个空白。它不在 JetBrains 那张表里，Google 侧我没找到对应公告，只能自己看 JBR 版本：25.0.3，而修复的 JBR 25 是 635.79、508.41、329.142 这几个构建。25.0.3 显然是老的。</p>
<p><img alt="四个组件，谁修了谁没修" loading="lazy" src="/images/emudhra/fig2.png"></p>
<h2 id="第二步直接问信任库还剩几把">第二步：直接问信任库还剩几把</h2>
<p>版本号会骗人，信任库不会。每个 JBR 自带一份 cacerts，用它的 keytool 就能列。</p>
<pre tabindex="0"><code>&#34;/Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/keytool&#34; \
  -list -cacerts -storepass changeit | grep -iE &#34;emsign|comodo&#34;
</code></pre><p>Android Studio 里出来四行：</p>
<ul>
<li><code>comodoaaaca [jdk]</code></li>
<li><code>emsigneccrootcag3 [jdk]</code></li>
<li><code>emsignrootcag1 [jdk]</code></li>
<li><code>emsignrootcag2 [jdk]</code></li>
</ul>
<p>四张全在。IntelliJ IDEA 那份也一样，四张全在，证书总数 111。</p>
<p>这里有个坑我必须先说，因为我踩了：别名的字面带一个空格加方括号的后缀，<code>emsigneccrootcag3 [jdk]</code>。你只写 <code>emsigneccrootcag3</code> 去删，keytool 会告诉你这个别名不存在，但它明明就在列表里。</p>
<h2 id="第三步证明你的处置真的生效">第三步：证明你的处置真的生效</h2>
<p>这是官方文档里没有的一步。</p>
<p>官方的临时方案是：把 cacerts 复制一份，删掉受影响的根，然后用 VM option 把 IDE 指向这份副本。问题是，你怎么知道那个 <code>-Djavax.net.ssl.trustStore</code> 真的被读进去了？路径写错、少写一个斜杠、用了 <code>~</code>，它都会静默失效。</p>
<p>我写了个三十行的小程序，直接问 JVM：你现在到底还信几张。</p>
<p><img alt="同一个信任库，三种状态：未修、官方 workaround、全删" loading="lazy" src="/images/emudhra/fig3.png"></p>
<p>关键在于 <code>tmf.init((KeyStore) null)</code> 这一句，它让 JVM 用默认信任库，也就是会响应 <code>javax.net.ssl.trustStore</code> 的那个。然后数一遍 <code>getAcceptedIssuers()</code> 里有多少张证书的颁发者叫 emSign 或者 AAA Certificate Services。</p>
<p>跑出来是这样：</p>
<p>不带 VM option 时，它报 109 张、命中 4。指向官方清理版，107 张、命中 2。四把全删，105 张、命中 0。</p>
<p>三行数字，把「我以为我修了」和「确实修了」分开了。</p>
<h2 id="官方没写的两件事">官方没写的两件事</h2>
<p>第一件，官方 workaround 只删两把：<code>comodoaaaca [jdk]</code> 和 <code>emsigneccrootcag3 [jdk]</code>。</p>
<p>但我在机器上查到的是四把都在，G1 和 G2 也还在信任库里。删完那两把之后，我的探针仍然报告「命中 2」。也就是说，按官方那两步走，这台机器上还留着两张 eMudhra 根证书。</p>
<p>我没有立场替 JetBrains 解释为什么只列两把，可能是修复版运行时对 G1、G2 另做了处理，也可能只是保守。但就「机器现状」这件事，数字是 4 不是 2。你要更彻底，就把四张一起删，我实测删完是 105 张、命中 0。</p>
<p>第二件，macOS 自己的系统根库里，这两张还躺着：</p>
<p><code>emSign ECC Root CA - G3</code> 的 SHA-1 是 3043FA4FF257DCA0C380EE2E58EA78B23FE6BBC1，<code>emSign Root CA - G1</code> 是 8AC7AD8F73AC4EC1B5754DA540F4FCCF7CB58E8C。</p>
<p><code>security dump-trust-settings</code> 在系统和用户两个域里都没有给它们单独加「不信任」策略。这不等于 macOS 就没拦它们，TLS 层还有别的机制，但至少从钥匙串这一侧看，它们还在。</p>
<h2 id="顺手把机器上其他-jvm-也扫一遍">顺手把机器上其他 JVM 也扫一遍</h2>
<p>这一条是我觉得最容易被漏掉的。</p>
<p>JetBrains 只说了自家产品。可你的 Gradle 守护进程跑在某个 JDK 上，命令行编译 Kotlin 也用着某个 JDK，Homebrew 又装了一份，每一个都有自己的 cacerts，跟 IDE 那份一点关系没有。</p>
<p>我把机器上所有能跑 keytool 的 JVM 都过了一遍：</p>
<ul>
<li>Homebrew OpenJDK 21.0.10，109 张，四把全在</li>
<li>Android Studio 打包 JBR 25.0.3，109 张，四把全在</li>
<li>IntelliJ IDEA 打包 JBR 25.0.4，111 张，四把全在</li>
</ul>
<p>一个都没修。</p>
<p>JetBrains 的修复版 JBR 也给到了 jbr21 的两条线，21.0.11b1163.125 和 21.0.9b1038.91。上游 OpenJDK 什么时候跟上，我没有一手出处，不能替你下结论，只能说本机这把 21.0.10 里四张还在。</p>
<h2 id="该怎么做">该怎么做</h2>
<p>优先级很清楚，能升级就别折腾临时方案。</p>
<p>IDEA 2026.2.4 已经在十月三十号发了，我从 JetBrains 的发布接口核过日期。Toolbox 3.9.1 已经装好，jetbrainsd 我也查了，跑的是 0.9.9728，就是修复版本。所以剩下要动的只有 IDE 本身。</p>
<p>如果暂时不能升，官方的三步是：复制 cacerts、用 jbr 里的 keytool 删别名、在 Help 的 Edit Custom VM Options 里加一行 <code>-Djavax.net.ssl.trustStore=</code> 指向副本。</p>
<p>路径必须写全，不许带 <code>~</code>，不许带引号。写错它不会报错，只会静默失效。然后在 Settings 的 Server Certificates 里确认「自动接受非可信证书」是关的。</p>
<p>还有一个细节：内置浏览器 JCEF 那份证书列表改不了，2025.2.6.4 及更早版本要直接关掉它，注册表键是 <code>ide.browser.jcef.enabled</code>。关掉之后 Markdown 预览和 notebook 输出会受影响，升级回修复版记得打开。</p>
<p><img alt="三条处置路径：升级、临时方案、只修后台服务" loading="lazy" src="/images/emudhra/fig4.png"></p>
<h2 id="我的判断">我的判断</h2>
<p>这件事最值得记的不是哪个版本修了，是信任边界在哪。</p>
<p>你更新了 macOS，你以为你安全了。你更新了 Chrome，你以为你安全了。但 IDE 里面有一份自己的信任库，Gradle 又有一份，命令行那把 JDK 还有一份。每一份都要单独修。</p>
<p>安全公告是写给所有人的，它不会替你回答「我这台机器现在到底是什么状态」。那个答案只能自己跑出来。</p>
<p>你机器上现在有几个 JVM？扫一下吧，我猜不止一个还剩着那四张。</p>
]]></content:encoded></item></channel></rss>