🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)
🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)

🔧 Programmierung 🕛 kürzlich 8 Min Lesezeit
0

Two AI reviews passed my change. The correct architecture was documented one file away.

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

Two separate models — one writing the code, one reviewing the diff — shipped a one-word bug to staging. Both ran local checks. Both came back green. The fix they missed was not exotic or subtle. It was written down, in plain English, in a file sitting in the same directory as the change.



That last detail is the one worth staying with. This is not a story about a model being wrong. Both models were, within the job they were given, correct. It is a story about where verification stops looking — and why stacking two reviewers that stop looking in the same place feels like safety and isn't.






What broke



While fixing a cron timeout, I had Claude Opus pull a small JSON-parsing helper into its own file so it could be unit-tested in isolation. Reasonable instinct. It named the file jsonExtract.mjs and imported it from autoPublish.js:




CODE
import { _firstJsonObject } from './jsonExtract.mjs'; // looks perfectly legal






The whole incident lives in that one letter — the m.



autoPublish.js is an ES module. On my machine, Node happily lets one ESM file import a .mjs file, so every local check passed. The deployed runtime took a different path:




CODE
Local:     ESM importer → .mjs ES module → works
Deployed: CommonJS require() → .mjs ES module → ERR_REQUIRE_ESM






I want to be precise about what I actually know here, because it matters. I did not instrument Vercel's build. What I observed is that the deployed function reached the helper through a CommonJS require(), while local Node exercised a compatible ESM path. Whatever transformation produced that, the consequence is fixed by the language spec: a .mjs extension forces a file to be an ES module, and require() of an ES module is barred. The result was an invocation-time crash:




CODE
Error [ERR_REQUIRE_ESM]: require() of ES Module
/var/task/.../jsonExtract.mjs
from /var/task/.../autoPublish.js not supported.






Not a syntax error. Not a logic error. A packaging error that only becomes real once your platform rewrites the module system underneath your repository.






The seam nobody owned



Every check you run has a scope, and a green result only ever means "clean within that scope." We forget this because green is rendered the same color regardless of how much it actually covered.



Walk the checks that ran on this change and read them as scopes rather than as pass/fail:





  • node --check — scope: syntax. The file parsed. True, and useless here.


  • The test suite — scope: the code paths the tests exercise, in the local runtime. All green. Also true; the tests never invoked the module across the deploy boundary.


  • The AI review — scope: logic correctness, as framed by the prompt. Race conditions, variable scoping, whether the extraction logic was sound. All fine. The reviewer was asked "is this logic correct," and it answered that question well.


  • The deployed runtime — scope: the real module system. The only scope in which this bug exists at all.



The bug did not slip past the checks. It lived in the seam between two of them — the gap between "local ESM resolution" and "deployed CJS resolution" — and no check on the board had that seam inside its scope. ERR_REQUIRE_ESM is an invocation-level error, so the build logs stayed green by definition: nothing executes at build time to trip it.



This is where the "documented one file away" detail turns from irony into the actual lesson. In the same directory sat a sibling helper, cluePrompts.js, carrying a prominent header comment saying it was CommonJS on purpose — written that way specifically to be default-imported from ESM consumers and dodge this exact rewrite. Project docs reinforced the convention. The correct architecture was not unknown. It was passive — encoded as prose, and prose is outside every automated scope above. A human skimming the diff wouldn't see it unless they already knew to look. Neither would a model. The knowledge existed and propagated to no one.






Why two reviews is not two reviews



Here is the trap that made me write this up, because it's the part that generalizes past Node and Vercel.



Two independent green stamps — one from the author model, one from a separate reviewer model running the tests itself — feels like defense in depth. It reads like redundancy. It is not. Redundancy only buys you coverage when the reviewers fail independently. These two shared a scope: both were evaluating logic correctness in the local runtime. When two checks share a scope, they share a blind spot, and stacking them multiplies your confidence without moving your coverage an inch.



That is the quiet danger of multi-model pipelines. Adding a second model that thinks about the code the same way the first one did doesn't widen the net; it just gets you a more confident wrong answer. Real defense in depth requires checks whose scopes are uncorrelated — one that reads a completely different signal than the others.






The one check with a different scope



I run a deterministic local hook while I build, and EraPin. This one was caught the instant the cron executed on Vercel staging, and fixed forward within the hour.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Hackers Just Poisoned the Rust Supply Chain | Threat Wire
1 Quelle
Hackers Found a Way Into Humanoid Robots | Threat Wire
1 Quelle
Bits und so #1021 (Passwort für Laufwerk)
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Two AI reviews passed my change. The correct architecture was documented one file away.

Thematisch verwandte Begriffe: reviews, passed, change, correct · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...