mitmproxy

Stars and mentions

Last 30 days, Oct 4 – Nov 2

GitHub stars793
mentions88
03672108144Oct 4Oct 18Nov 2
UTC days · repositories mitmproxy owns2 repositories

Package downloads

Cumulative recorded downloads · since 2026-04-08

crates.io—
PyPI64.2M
016M32.1M48.1M64.2MOct 4Oct 18Nov 2
Oct 30crates.io: 0/1 packages observed · PyPI: 1/5 packages observed

Across 6 known packages in repositories mitmproxy owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete. PyPI excludes known mirrors.

Top repositories

mitmproxy’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside mitmproxy’s account where mitmproxy opened or reviewed pull requests in the past 365 days.

Who noticed mitmproxy

Everyone who starred or forked mitmproxy’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

88posts
Nov 30 posts
  1. WeeklyReview#202643 Black October: the day people discovered Internet is a dangerous place this week. And what a week... It was absurdly hard days for the security world, and it's probably not done yet (because this note has been updated a lot). A huge amount of security issues and other crazy discoveries were announced in few hours/days. Good luck to all my sysadmin friends working to make their infrastructure safer. One of the very first big issue was due to a certificate authority problem. Many certificates generated by eMudhra (an Indian company) were totally unsafe. Indeed, their private keys were all an unique integer between 0 and 255 (uint8), instead of a long integer encoded on 384 bits. All started on 17th October, when "Wayne" (a security guy playing with new tools), discovered 8 odd certificates. A ticket was opened on Mozilla's Bugzilla. The thread is still very active. The consequences are concerning. Python is impacted and many packages must be updated. The Erlang Ecosystem Foundation did also a post about this issue explaining which modules must be upgraded as soon as possible. All Operating Systems are also impacted by this issue, and the certificates must be upgraded locally as well. The mitmproxy project already includes on its last version those certificates. More information below. - eMudhra emSign PKI Services: CP/CPS documents not updated for current requirements from Mozilla's Bugzilla thread; - eMudhra: Private key compromise of Intermediate Certificates from Mozilla's Bugzilla thread; - Information for Python users regarding eMudhra / emSign CA certificate security incident from Python's Discuss thread; - eMudhra CA Intermediate Certificates have been compromised, CA updates needed on all TLS components from the Erlang Ecosystem Foundation; - Alpine Linux 3.24.3 from Alpine Linux website; - OpenBSD 8.0 Errata 005 from the OpenBSD website; - FreeBSD -- TLS certificate store update due to eMudhra compromise from FreeBSD VuXML; - eMudhra TLS/SSL CA compromise from the NetBSD blog; - Debian ca-certificates security update, from the Debian mailing-list; - Eight eMudhra CA Keys Compromised, Triggering Emergency Fixes Across Browsers and Software from The Hacker News; - India's eMudhra exits website security business after flaws trigger global alarm from Reuters; - Oracle Security Alert Advisory - CVE-2026-91403 from Oracle/Java website. PHP is well known for Wikimedia, Drupal, Wordpress, Symphony and many other frameworks/projects widely used around the world. Unfortunately, PHP design is not the best, and during the past decades, many critical issues have been impacted it. This week, 2 huge security issues have been released with a CVE score greater than 9 and allowing remote code executions. What's crazy here is those vulnerabilities have been discovered in 2024 (!) during an audit. PHP was my first "real" language, like probably many of the developers and sysadmin of my generation. This language was - and still is - a big joke regarding design and consistency. During the week, PHP was also impacted by 2 big security issues with a score greater than 9 on the CVE scale. The whole story is just a pure mess. Called php2shell, the bug can execute arbitrary code on a remote server. Those bugs have been discovered in 2024 (!) during an audit. The PHP Foundation published a post on their blog explaining the whole process. Another crazy thing is, someone published an exploit few days before the official release, without any consideration of the companies being impacted by this news. - PHP Issues Emergency Patches for Two Critical PHP2Shell RCE Flaws as Exploit Attempts Emerge on The Hacker News; - PHP2Shell: What Actually Protects You Before the 14:00 UTC PHP RCE Patch, and What Doesn't on the Hacker News; - PHP2Shell: Two Unpatched Critical PHP RCE Flaws (CVSS 9.2) Trigger Emergency Security Alert on The Hacker News; - Two Critical PHP Flaws Leaked Ahead of the October 21 Security Release on WebHosting.today; - Today's PHP Security Release, and How We're Strengthening PHP Security on the Official PHP Foundation blog; - PHP2Shell: CVE-2026-109618 and CVE-2026-109619 exploits on Abraxas Labs; - php2shell/php2dos - php-stale-global-uaf exploit on Github; - php2shell - php-oom-longjmp exploits on Github; - Jesus Christ patch your shit now on xeiaso.net. A second breach in PHP has also been announced, not related to PHP2Shell, linked to the Session process. - Informational advisory: Session upload progress from PHP official website; - CVE-2026-115560 — PHP session upload progress mitigation At the same time, QUIC/HTTP/3 was also impacted by another 0day vulnerability called quiche, causing a DoS and eventually an OOM on many implementation of this protocol. - Header Accordions: QPACK amplification attacks against HTTP/3 servers on Foxio.io; - headeraccordions exploit/poc on Github. It's not over... Gitlab also released emergency patches for Gitlab Community and Enterprise Edition containing 12 fixes, including one critical vulnerability allowing an unauthenticated user to execute arbitrary code remotely. - GitLab Critical Patch Release: 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10, 18.11.13 on Official Gitlab Documentation: - Critical GitLab Flaw (CVSS 10.0) Could Allow Unauthenticated RCE Across 12 Years of Releases on The Hacker News. Signal released also a series of patch to fix a critical security issue, allowing someone to keep the micro and the camera active after a call. - Signal bug could keep your mic - and camera - on after hangup - Signal v2.72.0 on Gitlab; - CWE-754: Improper Check for Unusual or Exceptional Conditions on Common Weakness Enumeration website. NodeJs, as usual, is always there to offer us more vulnerabilities, even when we don't need them. Nodejs team released a long series of patches fixing dangerous security issues, 4 of them with high level risks. - Wednesday, October 21, 2026 Security Releases on NodeJS official blog; - Node.js security advisory: Brotli decoder RCE (CVE-2026-111497) on Vercel; - "No way to prevent this" say users of only language where this regularly happens on Xeiaso.net. Do you think it's over? Not at all! Apache traffic HTTP server released a new released to fix 15 vulnerabilities, including remote code execution and many other crazy holes. - "No way to prevent this" say users of only language where this regularly happens on xeiaso.net; - [[SECURITY] Multiple vulnerabilities fixed in Apache Traffic Server 9.2.16, 10.1.5 and 10.2.1](lists.apache.org) on apache traffic mailing-list. A dangerous memory corruption bug on Bind9 can lead an attacker to execute remote code. Again, high severity issue, needs to be patched as soon as possible. - CVE-2026-94300: Concurrent GSS-TSIG messages corrupt memory on ISC.org; - "No way to prevent this" say users of only language where this regularly happens on Xeiaso.net. Tor - which is becoming less and less trusted due to many design flaws and unfixed security issues - has also been impacted by a serious attack. 333 exit nodes on the tor network have been compromised and were used to do man in the middle attack on SSH connections. In case of success, the attackers were able to watch the commands and install backdoors. - Attackers Hijacked Over 300 Tor Exit Relays to Intercept SSH Connections from the Hacker News; - [[tor-relays] Re: Ebury 1.8.3 on two Quetzalcoatl relay servers: timeline, lessons, open questions](lists.torproject.org) from the Tor project mailing list. The French provider OVH has been victim of a supply chain attack, replacing the binaries of many versions of their CLI tool. - OVH supply chain compromise on Twitter. The LiteLLM Python package has been compromised with a supply chain attack as well, injecting malwares via Pypi and Docker images. - LiteLLM, a Python package for connecting to AI model providers with 92M+ monthly downloads, has been compromised. on Twitter; - LiteLLM supply chain attack hoovers up passwords and secrets on The Register. PHP, NodeJS, and... Ruby. This language requires to be patched due to remote code execution vulnerability related to the Regexp module (integer overflows and double free issue). All versions of Ruby are impacted. - Regexp compilation fixes related to GitLab's CVE-2026-89078, CVE-2026-93577, CVE-2026-97229 and CVE-2026-110264 from the official Ruby news. Kubernetes will also have a bad time, with 4 critical CVEs released very soon, including an issue on Azure Kubernetes, allowing remote code execution. - CVE-2026-83938 - Azure Kubernetes Configuration Service Elevation of Privilege Vulnerability I don't even think it's done... And to be honest, I am not the only one to do a summary of all those security issues. Here few of them from Twitter: - THE INTERNET BROKE TODAY - This is the most serious 48 hours in cybersecurity history. - October has been an absolute nightmare for software - We can call it Black October for the security breaches: - 33 security incidents in the news this October, sorted by size. 7 ran on a stolen key (K), 4 abused a trusted channel (T). - This week the internet’s core infrastructure got hit harder than most people realize ---- While writing my article on the libsodium library port on Dart using FFI, I also checked the Erlang driver called erlang-libsodium. Sadly this package was kinda old (version 1.0.18+ released in 2019). Few issues and PRs have been opened to fix the library, but the project seems to be dead. Anyway, I wanted to use is to test the interoperability with the Dart implementation, and decided to fork it. libsodium has been updated to version 1.0.22 (the latest), the PRs have been merged, and I'm working on doing a lot of test cleanup. After that, I will - perhaps - ports the missing features from the latest release. The project can be found here: niamtokik/erlang-libsodium on Github. ---- What's happening in the economy right now is interesting -- and also terrifying. During the week, most of the big players just started to fall, as well as the Asian market. > The Semiconductor (SOX) Index was hammered 11.4% [...] Supporting the bursting Bubble thesis, the semi equipment stocks were under notable pressure. Applied Materials lost 19.3%, Lam Research 17.2%, and KLA 15.3%. Coherent dropped 25.5%, Lattice Semiconductor 17.8%, and Marvell Technology 17.2%. Nvidia slumped 6.1%, down a quick 12% in eight sessions. Broadcom fell 9.1% to a six-month low. Micron sank 14.6%, Intel 14.2%, and AMD 13.1%. South Korea’s KOSPI Index was hammered 14.5% this week, with a seven-session drop of 18.3%. [...] Japan’s Nikkei Index fell 5.4%. > -- Credit Bulletin Report In fact, this situation is a direct result of something I saw many time in the past. Most of the current companies are not really companies anymore, but they look like sects. They are selling dreams, and faith to people without having an ounce of the knowledge or the experiences required to understand the bare minimum. You don't even need to give big proofs to make them pay, you know the aphorism "fake it until you make it". You just need one small miracle to make your company grows exponentially. The result? Some "expert" will also fall in the trap, and will start to preach. It will attract more people, blindly believing in them and in fine, in the technology sold by the company. The reality is harsh, and every actions produce reactions. > Investors are losing confidence that revenues from the AI boom will be sufficient to support the vast debt piles financing data centres, pushing bonds backing some of the largest US infrastructure projects into increasingly stressed territory. > -- Credit Bulletin Report The recent message(s) from Linus Torvalds are hilarious. Torlvads has a strong reputation to be against a lot of new/modern technologies, but for LLMs, that's okay, that's just another tool. It's fascinating to see someone like him using LLMs and trashing other people opinions on this subject when you know the [Open Secure AI Alliance](aiwiki.ai/wiki/open_secure_ai_alliance) joined the Linux Foundation in September. What kind of companies are present in this alliance? NVIDIA, Microsoft, Cisco, CrowdStrike, Hugging Face, IBM, Palantir, Red Hat and many others. It's not done yet, nvidia is also giving money to Linux Foundations in many other ways. They are LVFS sponcors and they are supporting many other open-source projects (including the Linux Foundation). In fact, we don't even know the amount of money nvidia is giving to the Linux Foundation because it is not public. In doubt, follow the money, even a monk can be corrupted with gold. Anyway, the LLM buzz is like the blockchain/crypto-currency one. They have both been created to do what fraudsters do the best: steal the money from your pocket by selling you a dream. The sects are doing the same with their victims. The result? What will happen when investors will discover all of these companies are selling snakeoil? They will simply ask their investment back. With $71 billions debt for Anthropic, and the small revenue generated by the company, it will become hard to explain that to investors. In short: this is a bubble, it will pop one day, probably very soon (if it's not already the case). To my brainwashed IT colleagues, please stop be part of these frauds... ---- Coding 🏗️ DOOM on the Aspire PIXO — natively System 📝 Introducing uncm(4): finally! a replacement for urndis driver working with recent version of Android! Say hello to uncm, providing support for the USB Network Control Model Ethernet devices. 📝 The hidden design compromises of Docker layers 📝 dbupdate(8) added to -current 🌐 exe.dev: Computers for developers and agents (Durable Sandboxes that are fast, secure, and sharable). Database 🏗️ credcheck: provides few general credential checks, which will be evaluated during the user creation, during the password change and user renaming. 🏗️ pg_hint_plan: makes it possible to tweak PostgreSQL execution plans using so-called "hints" in SQL comments. Security 📝 PwnEscape: Guest-to-Host KVM Escape (CVE-2026-99999) 📑 FloatDoor: Platform-Triggered Backdoors in LLMs 🌐 Private key compromise of eMudhra Intermediate Certificates: the thread from mozilla regarding the corrupted certificate. 🌐 eMudhra Intermediate CA Compromise: a longer post with solutions to apply after the CA corrupted certificate. 📝 How I got over 300 Tor exit nodes removed: a huge attack on tor network, where 333 nodes have been deployed to do MITM attack on SSH connections. 📝 Dumping Encrypted Viltrox Lens Firmware - two times 📝 One Parser, Two Bugs, Many Routers: Exploiting Broadcom WiFi Across eCos and Linux 🌐 ExploitGrid: Get notified when a CVE hits the software you run. 📝 Several Linux Kernel Vulnerabilities Accidentally Posted To Public Kernel Mailing List 📝 Scoop: Unvetted AI agents are accessing U.S. bank accounts Security/cryptography 📑 Claude reveals ECDSA curve origins: 📝 How were the NIST ECDSA curve parameters generated? 📝 Can You Slop Out High-Assurance Cryptography? Update/Upgrade 🔄 OpenBSD 8.0: another release of OpenBSD. 🔄 RabbitMQ 4.4.0 🔄 Phoenix 1.8.6 Misc 📝 Theo de Raadt: The Man Who Built the Internet's Locks 🐦 Meta just got hit with the largest penalty ever imposed on the company.: Meta will pay $25 bn for misleading Facebook users about how their data was protected. Leaks of the week French Communist Party: 183000 users impacted. La France Insoumise: leaks about campaigns and organization. ADMR: 4.5 millions people impacted, the leak include data about health and daily habits. AMSAM: 922GB of data stolen including invoices, bills, many kind of internal documents about 400 people. ---- {% embed x.com %} ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) !Image description ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ![Image description](x.com) ---- !Image description !Image description !Image description !Image description !Image description !Image description !Image description !Image description !Image description !Image description !Image description !Image description !Image description !Image description ---- Cover image by <a href="unsplash.com">Matthew Hamilton</a> on <a href="unsplash.com">Unsplash</a>

  2. Reddit · · r/blueteamsec · u/digicat · mitmproxy/mitmproxy

    Add `--emudhra` option to mitmproxy

    4 points
  3. I mean, CA compromise (well, "compromise") is definitely not a thing that happens often, as evidenced by the new dedicated mitmproxy option github.com/mitmproxy/mitmproxy/commit/16923449908…

    1 like
  4. Fantastic -- one good side effect of this eMudhra carry on is that we will be able to easily MITM traffic from old IoT devices for years now! mitmproxy has added a --emudhra command line switch to […] github.com/mitmproxy/mitmproxy/commit/16923449908…

    2 likes
  5. alas their name is gonna live on until the late 2030s mitmproxy#8500

    1 like
  6. A CA private key was the number 4. Your curl still trusts it (CVE-2026-111943) --- title: A CA private key was the number 4. Your curl still trusts it (CVE-2026-111943) published: true tags: security, infosec, tls, pki description: "Eight eMudhra intermediate CA keys were mis-generated — recoverable from the public certificates since April 2025. I recovered one in 4 guesses. Browsers are safe; your curl, git and CI may not be." series: black box --- > The private key of a certificate authority — a chain of trust rooted in the Mozilla, Microsoft, Apple and Chrome root programs — is the number 4. Not a metaphor: the EC scalar is literally 4, on a P-384 curve where it should be a 384-bit random number. It has been recoverable from the public certificate since April 2025. I recovered it in 4 guesses and 2 milliseconds. And as of this morning, my Mac's curl still happily connects to servers impersonated with it. The disclosure landed last week, the weaponization landed last night: mitmproxy now ships the actual compromised key behind a --emudhra flag, and CVE-2026-111943 got its number today. Browsers are safe. A very large amount of everything else is not — maybe including your terminal. What happened Eight eMudhra (emSign brand) intermediate CA certificates have incorrectly generated private keys — the top 376 bits of the P-384 scalars are all zeroes, leaving tiny integers you can brute-force from the certificate's public key alone. The intermediates chain to roots trusted by every major root program, and carry Sectigo cross-signs (through the old "AAA Certificate Services" root) as a second trust path. They were created in April 2025 with a validity stretching to 2040. On Oct 17, a reporter known as Wayne reported it to the root programs with an undeniable proof: he signed the message "We have a problem here - Wayne" with each of the eight private keys. - Oct 17: Firefox and Chrome block the intermediates - Oct 19: Apple platforms block them; downstream trust stores notified - Oct 20: Microsoft platforms block them; the disclosure site goes public - Oct 21, 23:51 UTC: mitmproxy merges --emudhra — the compromised key, shipping in a pentest tool - Oct 22, morning: CVE-2026-111943 is assigned The CA has revoked the certificates, and browsers push the blocks through their fast revocation channels (OneCRL, CRLite, CRLSets). But revocation only protects clients that consume revocation information. That is a much shorter list than you'd hope. Why your browser is fine (the trust fabric held — again) Two independent systems saved the browsers: 1. Certificate Transparency: these intermediates have zero CT log entries for their entire 18-month lifetime. CT-enforcing clients — Firefox, Chrome, Edge, Safari — could not have been attacked, because a leaf cert chaining through an unlogged intermediate is rejected outright. The attack surface never existed for them. 2. Fast revocation: OneCRL / CRLite / CRLSets block the intermediates directly. We keep arriving at the same conclusion: the web PKI survives its worst incidents not because CAs don't fail, but because the ecosystem around them assumes they will. (Same lesson as Let's Encrypt's multi-perspective validation — witnesses, not promises.) Who is not fine Everything that validates certificates without CT and without consuming revocation: - curl, wget, git (HTTPS remotes), package managers, CI/CD runners - Language runtimes with bundled trust stores: Go 1.27.3 / 1.26.10 fixed it, Node (22.23.4 / 24.22.1 / 26.12.1), Python certifi 2026.10.19, Rust rustls-webpki 0.103.16, Java, Deno, Electron… Claude Code shipped a fix (2.1.303) — your AI tooling's bundled roots were in the blast radius too. Bun and Erlang certifi are still "pending". - macOS is its own special case: the built-in curl, git, python3, perl, ruby and openssl validate against /etc/ssl/cert.pem without checking revocation — and that file has not been updated. I ran the disclosure's official self-check on my machine today: $ curl https://dv-g3b-emudhra.we-have-a-problem.com/ Your client successfully connected to the site. That's bad! $ curl https://dv-g3b-aaa-emudhra.we-have-a-problem.com/ Your client successfully connected to the site. That's bad! Both trust paths — emSign root and the Sectigo/AAA cross-sign — still validate on stock macOS. The second server's certificate is issued by EM DV TLS CA - G3B, one of the eight compromised intermediates. My terminal accepted it. A "certificate error" would have meant I'm safe. And the exposure is not theoretical: the disclosure's checker servers count every client that still connects successfully, per user-agent and JA4 fingerprint. There is live traffic. There are also live results. Run it yourself: recover a CA private key from its public certificate You need nothing but a public file. The certificates are in the disclosure's proof.zip (and impacted-intermediates.json lists all eight). Then: # recover.py — the private key from the public certificate alone import sys from cryptography import x509 from cryptography.hazmat.primitives.asymmetric.ec import derive_private_key cert = x509.load_pem_x509_certificate(open(sys.argv[1], "rb").read()) pub = cert.public_key().public_numbers() for d in range(1, 1_000_000): if derive_private_key(d, cert.public_key().curve).public_key().public_numbers() == pub: print(f"private key recovered: d = {d}") break Real run, on the EM OV TLS CA - G3C intermediate: $ python3 recover.py EM-OV-TLS-CA-G3C.crt.pem private key recovered: d = 4 Four guesses. Two milliseconds. From 1,240 bytes of fully public data. A CA private key that should take longer than the age of the universe to brute-force fell to a loop that didn't even reach its first coffee. The verification is one command away, and Wayne's proof ships exactly that way: openssl x509 -in EM-DV-TLS-CA-G3B.crt.pem -noout -pubkey | diff - EM-DV-TLS-CA-G3B.pub.pem openssl dgst -sha384 -verify EM-DV-TLS-CA-G3B.pub.pem -signature EM-DV-TLS-CA-G3B.sig message.txt Then the weaponization, for the lab only: mitmproxy --emudhra makes the proxy sign interception certificates with the real compromised key, so any client that still trusts the chain — say, a stock macOS curl — accepts an impersonated site without a single warning. One flag. That's how undramatic this failure is to exploit. The fix 1. Patch the trust stores — the disclosure maintains the exact list. Headlines: Ubuntu/Debian/Alpine/Fedora/Arch ca-certificates (all shipped this week), Go 1.27.3 / 1.26.10, Node 22.23.4+, Python certifi 2026.10.19 (then pip install -U certifi), Rust rustls-webpki 0.103.16, Deno 2.9.8, Docker Desktop 4.96.2, Claude Code 2.1.303, curl CA bundle 2026-10-20. 2. macOS, today, without waiting: strip the two affected roots from the file the built-in tools actually read (official workaround): sudo cp -p /etc/ssl/cert.pem /etc/ssl/cert.pem.bak && sudo awk '/^(###|===) /{skip=0} /^=== .*\/CN=(AAA Certificate Services|emSign ECC Root CA - G3)$/{skip=1} !skip' /etc/ssl/cert.pem.bak | sudo tee /etc/ssl/cert.pem > /dev/null Then re-run the two curl self-checks. "Certificate error" is the sound of being safe. 3. Linux servers: the disclosure ships sed-based workarounds for Debian/Ubuntu, Alpine, Fedora/RHEL-family, Arch, NixOS — they distrust emSign ECC Root CA - G3 and Comodo AAA Services root until the distro's ca-certificates update lands. The cross-sign path is the one people forget: blocking only the emSign root leaves the AAA path wide open — my second curl proved exactly that. 4. Offline Windows machines: Microsoft ships the block through automatic trust-list updates; air-gapped fleets need the Block-EmudhraCompromisedCA.ps1 script (16 intermediates and cross-signs into the Disallowed store). The nuance worth keeping Your microcontroller probably escaped. Embedded devices don't ship 150-root bundles — they pin one root per connection, so the compromised chain simply isn't in their firmware. The flip side is scarier: those bundles are frozen until 2039. The next mis-generated CA whose root is pinned in firmware will have no such luck. The real exposure was never the constrained devices — it's the desktops, the CI runners, and everything written in Go. TL;DR A trusted CA shipped eight private keys that were guessable small integers, and they sat in the wild for 18 months. Browsers were saved by Certificate Transparency — again. Your terminal tools were not: check with the two curl one-liners, patch your trust stores, and on macOS apply the cert.pem workaround today. And if you want to feel it viscerally: recover the key yourself — it's four guesses. Sources: official disclosure + self-checks + patched list · Mozilla bug tracker incident report · MCU analysis — Daniel Mangum · mitmproxy --emudhra commit · CVE-2026-111943

    5 reactions · 2 comments
  7. 过河拆桥,而且还是连号 mitmproxy#8499 mitmproxy#8500 t.co

    15 likes · 2,979 views
  8. Now the option to sign certificates with #eMudhra CA is built into #mitmproxy directly: mitmproxy#8500

    112 favourites · 4 comments · 76 boosts
  9. Eight CA private keys under 256: checking every EC key in CCADB with the Python standard library On 17 October, someone told the browser root programs they could recover the private keys of eight intermediate CA certificates issued by eMudhra. Mozilla's incident report, Bugzilla 2083449, explains how that was possible in one line: > The 8 impacted keys all used integers less than 256. A P-384 private key should be a random number about 384 bits long. These were one byte. Every signature they made was valid and every chain built on them validated. Anyone could find the keys by trying 255 numbers. I wanted to see that myself without installing anything, so I wrote a check that uses only the Python standard library. It reads the public key out of every certificate in CCADB's public reports, compares it with the public keys for private keys 1 to 65,535, and matches SPKI hashes against the list Go shipped on 19 October. Then I pointed a second script at the trust store on the machine I ran it on, and found the distrusted root still in it. Everything below was run on 22 October 2026. What the incident report says From the report and its comments, attributed to whoever said it: - The report reached Mozilla at 20:06 UTC on 17 October with proof of key control for all eight. Mozilla says it recovered the keys independently by 21:48 UTC. - Six are TLS intermediates trusted by Chrome, Mozilla, Microsoft and Apple. Two are code-signing intermediates trusted by Microsoft. - eMudhra revoked all eight on 18 October with the reason cACompromise. Sectigo revoked its cross-signatures of the same keys on 19 October. - eMudhra says the keys came from one key ceremony on 30 April 2025, only one of the eight was in production, and no end-entity certificates were issued from any of them. Its preliminary assessment points at a flaw in the key-generation script during a wrap/unwrap test that departed from its usual ceremony. It says it is still assessing. - On 20 October, Mozilla wrote that "multiple individuals have independently recovered the private keys" and removed trust in the whole emSign ECC Root CA - G3. Chrome said it would take a similar path. Go's fix landed a day earlier. Go 1.26.10 and 1.27.3 add a distrustedSPKIHashes map of eight SHA-256 hashes to crypto/x509 and drop any chain containing one of them. The commit names no CA. My reading of why Go needed its own list comes from verify.go itself. The doc comment on Verify says "this function doesn't do any revocation checking", and on Linux the roots come from the OS bundle (root_linux.go tries /etc/ssl/certs/ca-certificates.crt first). With no CRL check and no control over the OS bundle, a list of bad keys is the one thing Go can enforce everywhere, and the same commit adds the check to the macOS and Windows verifier paths too. Finding a small private key without any discrete-log maths An EC public key is the point d·G, where d is the private key and G is the curve's generator. Recovering d from a properly random key is the hard problem the whole scheme rests on. Recovering it when d is below 256 is a loop: compute G, 2G, 3G and so on, and compare each one with the public key. Here is the curve arithmetic for P-256 and P-384, in affine coordinates with Python's built-in modular inverse. The self-test matters more than it looks. A typo in the generator or the prime would make the table silently useless, and checking that G is on the curve and that n·G is the point at infinity catches a typo in any of the four constants. import csv, hashlib, re, sys from base64 import b64decode # NIST P-256 and P-384: field prime, curve b (a = -3 on both), generator, order CURVES = { "P-256": dict( oid=bytes.fromhex("2a8648ce3d030107"), p=2**256 - 2**224 + 2**192 + 2**96 - 1, b=0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B, g=(0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296, 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5), n=0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551), "P-384": dict( oid=bytes.fromhex("2b81040022"), p=2**384 - 2**128 - 2**96 + 2**32 - 1, b=0xB3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF, g=(0xAA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7, 0x3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F), n=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973), } def ec_add(c, P, Q): """Affine point addition on y^2 = x^3 - 3x + b. None is the point at infinity.""" p = c["p"] if P is None: return Q if Q is None: return P if P[0] == Q[0] and (P[1] + Q[1]) % p == 0: return None if P == Q: lam = (3 * P[0] * P[0] - 3) * pow(2 * P[1], -1, p) % p else: lam = (Q[1] - P[1]) * pow(Q[0] - P[0], -1, p) % p x = (lam * lam - P[0] - Q[0]) % p return x, (lam * (P[0] - x) - P[1]) % p def ec_mul(c, k, P): R = None while k: if k & 1: R = ec_add(c, R, P) P = ec_add(c, P, P) k >>= 1 return R def self_test(c): x, y = c["g"] assert (y * y - (x**3 - 3 * x + c["b"])) % c["p"] == 0, "G is not on the curve" assert ec_mul(c, c["n"], c["g"]) is None, "n*G is not the point at infinity" def small_key_table(c, limit): """Public points for private keys 1..limit-1, keyed by point.""" table, P = {}, None for d in range(1, limit): P = ec_add(c, P, c["g"]) table[P] = d return table Pulling the public key out of a certificate Go hashes RawSubjectPublicKeyInfo, the complete DER-encoded SubjectPublicKeyInfo, so the script has to cut out exactly those bytes. A certificate is a SEQUENCE containing the to-be-signed SEQUENCE, and the SPKI is the sixth field of that once the optional [0] version tag is skipped. A minimal DER reader is enough: def tlv(buf, i): """Read one DER tag-length-value. Returns (tag, value_start, value_end).""" tag, length = buf[i], buf[i + 1] i += 2 if length & 0x80: n = length & 0x7F length = int.from_bytes(buf[i:i + n], "big") i += n return tag, i, i + length def children(buf, start, end): out = [] while start < end: tag, vs, ve = tlv(buf, start) out.append((tag, start, vs, ve)) start = ve return out def spki_der(cert): """The raw SubjectPublicKeyInfo bytes, the thing Go hashes.""" _, vs, ve = tlv(cert, 0) _, tvs, tve = tlv(cert, vs) # tbsCertificate fields = children(cert, tvs, tve) if fields[0][0] == 0xA0: # explicit [0] version fields = fields[1:] _, start, _, end = fields[5] # serial, sigAlg, issuer, validity, subject, spki return cert[start:end] def ec_public_point(spki): """(curve name, (x, y)) for an EC key, or (None, None) for anything else.""" _, vs, ve = tlv(spki, 0) (_, _, avs, ave), (_, _, bvs, bve) = children(spki, vs, ve) params = children(spki, avs, ave) if len(params) < 2: return None, None curve_oid = spki[params[1][2]:params[1][3]] point = spki[bvs + 1:bve] # skip the unused-bits byte for name, c in CURVES.items(): if c["oid"] == curve_oid and point[0] == 4: half = (len(point) - 1) // 2 return name, (int.from_bytes(point[1:1 + half], "big"), int.from_bytes(point[1 + half:], "big")) return None, None def pem_to_der(text): m = re.search(r"-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----", text, re.S) return b64decode("".join(m.group(1).split())) if m else None Running it over CCADB The last part holds Go's eight hashes, copied from verify.go at tag go1.27.3, and walks a CCADB CSV. The three CCADB reports below are Mozilla's revoked intermediates, all intermediates, and included roots, each with a PEM column. GO_DISTRUSTED = { # crypto/x509/verify.go at go1.27.3, lines 1417-1426 "ebed6475c2c2d80fcb199f3fe8dd6e6b3ce60b77eb15d4e42c3dec0c6f5b5105", "49dd353dc2b919a3770645117d0e60c16115e7d1bc259eefe734b00ea434fe5f", "e0254c7fcdc265e2f0f8a428dabb75ab4ae039b4872d62f5ee57f0877d5a8a41", "5c0660a2b164910d8ff589c18e14552e9e0ec237dcefe2cb736d41a4811f81a0", "43bffa19d6ef651451f6841e019931e96f6f2eaeff28ab4b6f1ce4576de2717b", "63ecefee431d49523bc1136c4e72d0206a477086caf606cd5cf025686c109cf8", "ec4ffa1ad0ac88081314b7aaffef6a91f97cd57291bb5ba686c5415f5eb4f6b6", "92c063d67e8f14db71d288e11266ffdaf69cbf115f7bab14f3bc2f68d25e0e30", } LIMIT = 2**16 # private keys 1..65535: covers "below 256" with room to spare def scan(path, tables): csv.field_size_limit(sys.maxsize) rows = list(csv.DictReader(open(path, encoding="utf-8"))) pem_col = next(k for k in rows[0] if "PEM" in k) name_col = next(k for k in ("Certificate Subject Common Name", "Common Name or Certificate Name") if k in rows[0]) counts = {"rows": len(rows), "P-256": 0, "P-384": 0, "go_match": 0} hits = [] for r in rows: der = pem_to_der(r[pem_col]) if der is None: continue spki = spki_der(der) spki_hash = hashlib.sha256(spki).hexdigest() in_go = spki_hash in GO_DISTRUSTED counts["go_match"] += in_go curve, point = ec_public_point(spki) if curve is None: continue counts[curve] += 1 d = tables[curve].get(point) if d is not None or in_go: hits.append((r[name_col], r.get("Certificate Issuer Common Name", ""), curve, d, spki_hash[:16], in_go)) return counts, hits if __name__ == "__main__": tables = {} for name, c in CURVES.items(): self_test(c) tables[name] = small_key_table(c, LIMIT) print(f"self-test passed; tables hold private keys 1..{LIMIT - 1} on P-256 and P-384") for path in sys.argv[1:]: counts, hits = scan(path, tables) print(f"\n{path.split('/')[-1]}: {counts['rows']} rows, " f"{counts['P-256']} P-256 keys, {counts['P-384']} P-384 keys, " f"{counts['go_match']} certificates whose SPKI hash is in Go's list") for subj, issuer, curve, d, h, in_go in sorted(hits): size = f"{d.bit_length()}-bit key" if d else "not small" print(f" {subj:<20} issuer={issuer:<26} {curve} {size:<10} spki={h}... in_go={in_go}") curl -s -o ccadb.csv 'https://ccadb.my.salesforce-sites.com/mozilla/PublicIntermediateCertsRevokedWithPEMCSV' curl -s -O 'https://ccadb.my.salesforce-sites.com/mozilla/PublicAllIntermediateCertsWithPEMCSV' curl -s -O 'https://ccadb.my.salesforce-sites.com/mozilla/IncludedCACertificateReportPEMCSV' mv PublicAllIntermediateCertsWithPEMCSV PublicAllIntermediateCertsWithPEMCSV.csv mv IncludedCACertificateReportPEMCSV IncludedCACertificateReportPEMCSV.csv python3 tinykey_check.py ccadb.csv PublicAllIntermediateCertsWithPEMCSV.csv IncludedCACertificateReportPEMCSV.csv self-test passed; tables hold private keys 1..65535 on P-256 and P-384 ccadb.csv: 2977 rows, 114 P-256 keys, 243 P-384 keys, 16 certificates whose SPKI hash is in Go's list EM DV TLS CA - G3B issuer=AAA Certificate Services P-384 8-bit key spki=ebed6475c2c2d80f... in_go=True EM DV TLS CA - G3B issuer=emSign Root TLS CA - G3 P-384 8-bit key spki=ebed6475c2c2d80f... in_go=True EM DV TLS CA - G3C issuer=AAA Certificate Services P-384 8-bit key spki=49dd353dc2b919a3... in_go=True EM DV TLS CA - G3C issuer=emSign Root TLS CA - G3 P-384 8-bit key spki=49dd353dc2b919a3... in_go=True EM EV TLS CA - G3B issuer=AAA Certificate Services P-384 7-bit key spki=e0254c7fcdc265e2... in_go=True EM EV TLS CA - G3B issuer=emSign Root TLS CA - G3 P-384 7-bit key spki=e0254c7fcdc265e2... in_go=True EM EV TLS CA - G3C issuer=AAA Certificate Services P-384 6-bit key spki=5c0660a2b164910d... in_go=True EM EV TLS CA - G3C issuer=emSign Root TLS CA - G3 P-384 6-bit key spki=5c0660a2b164910d... in_go=True EM OV CS CA - G3B issuer=AAA Certificate Services P-384 7-bit key spki=ec4ffa1ad0ac8808... in_go=True EM OV CS CA - G3B issuer=emSign Root CS CA - G3 P-384 7-bit key spki=ec4ffa1ad0ac8808... in_go=True EM OV CS CA - G3C issuer=AAA Certificate Services P-384 8-bit key spki=92c063d67e8f14db... in_go=True EM OV CS CA - G3C issuer=emSign Root CS CA - G3 P-384 8-bit key spki=92c063d67e8f14db... in_go=True EM OV TLS CA - G3B issuer=AAA Certificate Services P-384 8-bit key spki=43bffa19d6ef6514... in_go=True EM OV TLS CA - G3B issuer=emSign Root TLS CA - G3 P-384 8-bit key spki=43bffa19d6ef6514... in_go=True EM OV TLS CA - G3C issuer=AAA Certificate Services P-384 3-bit key spki=63ecefee431d4952... in_go=True EM OV TLS CA - G3C issuer=emSign Root TLS CA - G3 P-384 3-bit key spki=63ecefee431d4952... in_go=True PublicAllIntermediateCertsWithPEMCSV.csv: 2517 rows, 420 P-256 keys, 374 P-384 keys, 0 certificates whose SPKI hash is in Go's list IncludedCACertificateReportPEMCSV.csv: 169 rows, 3 P-256 keys, 48 P-384 keys, 0 certificates whose SPKI hash is in Go's list The whole run took about four seconds. Sixteen revoked certificates carry the eight keys, because each key was certified twice: once by eMudhra's own emSign root and once by Sectigo's AAA Certificate Services cross-sign. All eight of Go's hashes are there, and every one of the eight keys is between 3 and 8 bits long. I print the bit length rather than the number. The smallest is EM OV TLS CA - G3C, whose private key is 4. That value is already public: mitmproxy's main branch has a new --emudhra option, listed under "Unreleased" in its changelog, that lets the proxy sign the certificates it generates with this key. I parsed the PEM from that commit with openssl pkey, and it is 47 zero bytes followed by 04, with an SPKI hash of 63ecefee..., the sixth entry in Go's map. The other seven values are just as easy to print. I left them out because there is no reason to copy them around. The other two reports are the control group. Among the 794 EC keys in CCADB's all-intermediates report and the 51 EC roots in Mozilla's included-roots report, nothing has a private key under 65,536. The revoked list also holds a second batch of eMudhra cross-signs that Sectigo revoked on 21 October with the reason cessationOfOperation, and none of those keys is small either. This test catches one specific failure: a key that is a small integer. A key drawn from a broken random number generator would pass it. The part that applies to your machine Revoking an intermediate only protects clients that check revocation. OpenSSL's verify does not by default, and neither does Python's ssl module. Here is the G3C intermediate from the CCADB CSV, checked against the system bundle on the Ubuntu 24.04 container I ran all of this in. The certificate linking emSign Root TLS CA - G3 to emSign ECC Root CA - G3 is not in either CCADB intermediate report I downloaded, so I took it from the same mitmproxy commit. BUNDLE=/etc/ssl/certs/ca-certificates.crt # 1. Path validation only (openssl verify does not check CRLs by default) openssl verify -CAfile "$BUNDLE" -untrusted emsign-root-tls-g3-cross.pem em-ov-tls-g3c.pem # 2. Same chain, with the issuer's CRL checked curl -s --retry 3 -A Mozilla/5.0 -o roottlscag3.crl 'http://crl.emsign.com/?roottlscag3.crl' openssl crl -inform DER -in roottlscag3.crl -out roottlscag3.pem openssl verify -CAfile "$BUNDLE" -untrusted emsign-root-tls-g3-cross.pem \ -crl_check -CRLfile roottlscag3.pem em-ov-tls-g3c.pem em-ov-tls-g3c.pem: OK C = US, O = eMudhra Inc, CN = EM OV TLS CA - G3C error 23 at 0 depth lookup: certificate revoked error em-ov-tls-g3c.pem: verification failed Path validation alone says OK. The CRL says revoked. When I ran this, the CRL host answered curl's default user agent with a 403, so the script sends a different one. Python's default context on the same container: import ssl ctx = ssl.create_default_context() crl_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_CRL_CHECK_CHAIN print("CRL checking on by default:", bool(ctx.verify_flags & crl_flags)) for cert in ctx.get_ca_certs(): name = dict(rdn[0] for rdn in cert["subject"]).get("commonName", "") if name.startswith("emSign"): print("trusted root:", name) CRL checking on by default: False trusted root: emSign Root CA - C1 trusted root: emSign ECC Root CA - C3 trusted root: emSign Root CA - G1 trusted root: emSign ECC Root CA - G3 So on this container, a Python client with default settings trusted the root above the revoked intermediates and did not look at the CRL. The fix for that is the trust bundle, and different bundles took different routes. This script checks a bundle by the root's SPKI hash rather than its name: import hashlib, re, sys from tinykey_check import pem_to_der, spki_der # SPKI SHA-256 of emSign ECC Root CA - G3, as listed in rustls/webpki-roots PR 133 G3_ROOT = "8d417db2dd8bf5e3084d1e3f196d583849d81bdd4c00c70b9d39369e96b8c782" for path in sys.argv[1:]: pems = re.findall(r"-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----", open(path).read(), re.S) hashes = {hashlib.sha256(spki_der(pem_to_der(p))).hexdigest() for p in pems} print(f"{path}: {len(pems)} certificates, emSign ECC Root CA - G3 present: {G3_ROOT in hashes}") for v in 2026.07.22 2026.10.18 2026.10.19; do curl -s -o certifi-$v.pem https://raw.githubusercontent.com/certifi/python-certifi/$v/certifi/cacert.pem done python3 bundle_check.py /etc/ssl/certs/ca-certificates.crt certifi-2026.07.22.pem certifi-2026.10.18.pem certifi-2026.10.19.pem /etc/ssl/certs/ca-certificates.crt: 121 certificates, emSign ECC Root CA - G3 present: True certifi-2026.07.22.pem: 121 certificates, emSign ECC Root CA - G3 present: True certifi-2026.10.18.pem: 117 certificates, emSign ECC Root CA - G3 present: False certifi-2026.10.19.pem: 120 certificates, emSign ECC Root CA - G3 present: False Three different answers: - Ubuntu published ca-certificates 20260816ubuntu0.24.04.1 to noble-security on 20 October. Its changelog blacklists emSign ECC Root CA - G3 "due to intermediate cert compromise". My container still had 20260601~24.04.1 because nobody had upgraded it since. The fix existed and it was not on the machine. - certifi 2026.10.18 removed all four emSign roots. Universities whose services chain to other emSign roots reported breakage in certifi issue 439, and 2026.10.19 put three back and kept G3 out. A maintainer explained in that thread why the first release went wider than the intermediates: "there's no facility for revoking an intermediate only." - rustls webpki-roots 1.0.10 (PR 133) removed only G3 and printed its SPKI hash, 8d417db2...c782. That is the same hash bundle_check.py computes from Ubuntu's copy of the root, which is how I know the script is matching the right certificate. What I am keeping from this A root bundle is the only lever most clients have, and a machine can hold several copies: the OS package, a pinned certifi in a lockfile, a container image built before 20 October, and Go binaries built with a toolchain older than 1.26.10 or 1.27.3. Each needs its own update or rebuild. The SPKI-hash check above takes a few seconds per bundle. The small-key test is cheap enough to run on any EC public key you generate yourself, as a smoke test. It would have flagged these eight on the day of the ceremony. It says nothing about keys that are bad in subtler ways. And a valid signature tells you nothing about how the key behind it was made. Every chain here validated, and that was the problem. Written with AI assistance from my own notes and test results. I checked every fact and command before publishing.

  10. @brokenpacifist mitmproxy#8497 😭

    80 likes · 1 repost · 5,572 views
Trending awards, every completed day and week
Gold
01st place finishes
Silver
12nd place finishes
Bronze
03rd place finishes
Awarded repositories
1Owned by mitmproxy now

Repositories

Ordered by gold, then silver, then bronze.

  1. mitmproxyBest: 2nd by stars, 205 stars010

Every award

Top-three finishes of these repositories in completed trending days and weeks, newest first.

  1. #2 by starsDaily trending
    205 starsas cortesi/mitmproxy
    mitmproxy

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.