The Decision I Never Thought I'd Make
A few days ago I told my team something that, even as the words came out, I couldn't quite believe I was saying: We're going to kill all external dependencies and bring all code in house.
Not some of them. Not the risky ones. All of them.
If you've built software in the last two decades, you know how insane that sounds. Open source dependencies are the bedrock of modern development. They share features and workloads. They handle security hardening you don't have time to do yourself. They give you capabilities that would take months or years to build from scratch. The entire ecosystem of software development is built on the assumption that you trust the code other people wrote.
And that assumption is exactly the problem.
The Supply Chain Problem That Just Got Real
Somewhere in your dependency stack, right now, a bad actor can inject poisoned code that goes unnoticed. This isn't theoretical. It's happened several times to devastating effect. SolarWinds. Log4Shell. The Log4J response alone consumed weeks of work across our industry.
But those were prologues. What happened the week before we started this initiative was something different entirely.
On March 19, 2026, a threat group called TeamPCP compromised Trivy, a widely used open source security scanner. They rewrote Git tags and force-pushed malicious binaries, turning a tool that organizations trust to protect their supply chain into the attack vector itself. Four days later, the same group hit Checkmarx KICS using the same infrastructure. Then on March 24, five days before we began our fork, the cascade reached LiteLLM.
LiteLLM is a unified API wrapper for LLM providers (OpenAI, Anthropic, Azure, others). It sits between applications and AI services, which means it typically has access to every API key, every environment variable, every credential in the system. It pulls roughly 97 million downloads per month and is present in an estimated 36% of cloud environments. Many teams don't even know they have it because it comes in as a transitive dependency through other AI frameworks.
Here's how the domino fell: LiteLLM's CI/CD pipeline ran Trivy as part of its build process. The compromised Trivy exfiltrated LiteLLM's PyPI publishing token. TeamPCP used that token to upload two backdoored versions (1.82.7 and 1.82.8) directly to PyPI, bypassing the project's normal release workflow. The malicious code used a .pth file that executes automatically on Python interpreter startup. You didn't need to import LiteLLM. You just needed it installed. The payload harvested SSH keys, cloud credentials, Kubernetes secrets, database passwords, and environment variables, then established persistent backdoor access.
The compromised packages were live for about three hours before PyPI quarantined them. When security researchers raised the alarm on GitHub, the attackers (who still had maintainer access) closed the issue as "not planned" and deployed 88 bot comments from 73 compromised developer accounts in a 102-second window to bury the discussion. Researchers documented an AI agent called "hackerbot-claw" being used operationally in the attack. This was one of the first observed cases of AI being used as part of a supply chain attack's execution, not just its preparation.
Read that chain again. A security scanner was compromised. That compromised scanner was used to steal credentials from an AI library's build pipeline. Those credentials were used to publish poisoned code to a package registry that serves millions of downloads per month. The attackers used AI agents and bot armies of previously compromised developer accounts to suppress disclosure. A security tool designed to find supply chain attacks became the delivery mechanism for one.
This is the world we're building software in now.
The same AI capabilities that let me build an entire cybersecurity platform with Claude are available to adversaries. And they're not just using them to write malicious code. They're using AI agents operationally in the attack chain itself. The volume and sophistication of supply chain attacks just jumped by orders of magnitude, and our traditional defenses (code review, automated scanning, trust-but-verify) weren't designed for a world where the security tools themselves are compromised.
I wrote about the hazards of automating broken processes earlier this year. If your dependency pipeline is a trust-based system operating in a world where trust is being actively weaponized, making that pipeline faster doesn't make it safer. It makes the failure faster. And if the tools you use to verify trust are themselves compromised? You don't have a supply chain problem. You have a supply chain collapse.
So I started thinking about what it would look like to just... stop. Stop trusting. Stop updating. Stop pulling code from public registries at build time. Bring it all in house, scan it, own it, and maintain it ourselves.
The Before Picture
Before I tell you how it went, let me show you what we were looking at.
Our analytics repository contained 7,352,179 lines of code across 32,708 files. WitFoo's own code was 183,363 lines across 737 files. Let that sink in for a moment. Roughly 97.5% of the code running in our product was code we didn't write and didn't control.
The Go side had 295 unique external modules feeding into 34 go.mod files. Some packages (like golang.org/x/sys and klauspost/compress) were shared across 23 to 26 modules each, creating a deep interdependency web. The frontend had 1.37 GB of node_modules spread across four projects. That's more than half the repository by weight, all third-party code sitting there waiting to be trusted at build time.
We had 318 MB of compiled binaries, 10,157 Go tests running in under 14 seconds, and detailed performance baselines from our PR166 experiments: API latency profiles, engine benchmarks, memory footprints, throughput numbers. We captured all of it before we started so we'd know exactly what changed.
The supply chain pre-state was telling. Zero forked packages. Zero npm offline caches. Five vendor scripts (scaffolding only). We had never verified that our code could build with GOPROXY=off. In other words, we were entirely dependent on the internet and the goodwill of strangers every time we compiled our software.
For a cybersecurity company, that's a particularly uncomfortable realization.
The Instructions
Here's what I told Claude:
Due to supply chain problems created by AI, we want to import all packages and dependencies into analytics. We recognize this will be a monster amount of work. We need to create PR tasks that will cover many sessions to accomplish all the work. We should minimize and optimize the packages to our needs after fork. We should align the packages with the WitFoo Way. We should deeply scan the packages and patch all vulnerabilities. We will not merge new updates from the packages. We will maintain features ourselves, but may reference the changes in expanding our use cases. We will allow updates to Golang and its core packages but no others.
I estimated it would take "a few billion tokens" and several weeks. I was wrong on both counts. Spectacularly wrong, as it turns out.
Two Days
The entire initiative was completed on March 29 and 30, 2026.
In two days, we internalized 450 Go packages (227 analytics, 223 conductor suite), built offline npm caches for 4 frontend projects totaling 693 MB, created 14 vendor scripts, wrote a brand new pkg/supplychain Go library (using only stdlib, because the irony of adding external dependencies to a supply chain security tool was not lost on us), ran security scans across all 27 Go modules and 4 npm projects, found and remediated 14 npm vulnerabilities, set up a weekly CI scan, added a pre-commit hook that blocks any new external dependencies, and generated a CycloneDX SBOM for compliance.
Total token cost: approximately 305,000. Not billions. Not millions. Three hundred and five thousand.
I wrote in The Closing Window about AI's value-to-cost ratio shifting. This project is the counter-argument to my own pessimism. At ~305K tokens, the v:c ratio for this initiative was astronomical. We eliminated an entire class of existential risk from our product for the cost of a nice dinner.
What We Found on the Way In
This is the part that justifies everything.
When we forked the code and ran our security scans, we found 14 npm vulnerabilities sitting in our dependency stack. Eight of them were high severity. They were there before the fork. The fork is what made us find them.
The Go side was clean (zero CVEs across 27 modules, zero issues from gosec SAST, zero crashes from 8.6 million fuzz test executions). But the npm ecosystem told a different story: high-severity advisories in flatted, happy-dom, picomatch, and cookie across multiple projects. All 14 were remediated the same day they were discovered.
I can't help but notice the irony here. We undertook this initiative to protect against future supply chain attacks. What we actually did was discover vulnerabilities that were already present and would have remained invisible under normal operations. The threat we were guarding against had already partially materialized, and we just hadn't looked.
Zero Regression
This was the risk that kept me up at night. Forking 450 packages and rerouting all module resolution through replace directives is the kind of change that could silently break everything. Here's what actually happened:
Binary sizes: 318 MB before, 318 MB after. Zero bytes of change. The replace directives are purely a compile-time concern. Same code, different resolution path, identical output.
Test counts: 10,157 before, 10,157 after. Not a single test lost or broken.
Test duration: 13,862ms before, 13,117ms after. The 5.4% improvement is within normal variance, but the point is it didn't get worse.
API latency, memory footprint, throughput benchmarks: all unchanged. Runtime behavior is identical because the code paths are identical.
Offline build time: 8.1 seconds for all 8 core services with GOPROXY=off. Our product now builds without touching the internet. Period.
The Bloat Nobody Sees
The cleanup phase (PR302) was arguably the most revealing part of the entire initiative.
When you fork everything, you get to look inside the box. And what we found was staggering. google.golang.org/api was consuming 363 MB of our forked third-party directory. It contained 368 Google service API clients (YouTube, Drive, Analytics, on and on). We needed exactly 8 core packages: option, transport, internal, iterator, googleapi, support, idtoken, and impersonate. One package was responsible for 37.7% of our entire third-party footprint, and we used approximately 2% of it.
Docker's SDK had bundled its entire daemon. Prometheus shipped its full server as a transitive dependency when we only needed prompb and a few model packages. golang.org/x/tools contained 58 CLI tools we never called.
After removing dead code (CLI tools, documentation, benchmarks, examples, unused service clients), we took third_party/go/ from 964 MB down to approximately 576 MB. A 40% reduction. We removed 13,060 test files and over 315 testdata directories that had no business being in a production dependency.
None of this was visible before the fork. It was all just... there. Silently expanding our attack surface, inflating our builds, and consuming resources for code that existed in our pipeline doing absolutely nothing.
The Three Acts
Looking back, the work fell naturally into three phases that tell the story of what it means to take ownership of your code.
PR300: Bring It In. Fork all 450 packages, build offline npm caches, update Dockerfiles and CI pipelines, verify everything builds with no network access. The foundational act of saying "this is ours now."
PR301: Build the Watchtower. Create pkg/supplychain (stdlib only), implement upstream CVE monitoring, SBOM generation, vulnerability database, weekly CI scanning, air-gapped scanning for disconnected networks. Because owning the code means owning the responsibility to watch it.
PR302: Clean the House. Audit everything. Remove 388 MB of dead code. Verify license compliance. Scan for suspicious patterns. Document what remains and why. Ownership means knowing exactly what you have.
Three PRs. Two days. One principle: if it runs in our product, we should be able to answer for every line of it.
Lessons Learned
The threat you're guarding against might already be inside. We went in looking for future risk and found 14 present-day vulnerabilities. Scan first. Scan everything.
AI creates the problem and enables the solution. The same AI capabilities that make supply chain attacks more dangerous are what made a two-day internalization of 450 packages feasible. Six months ago this initiative would have been a quarter-long project. The tooling that creates the urgency also provides the capability to respond. That's a new dynamic and one worth understanding deeply.
The trust chain is only as strong as its weakest link, and the links are multiplying. The TeamPCP cascade (Trivy to Checkmarx to LiteLLM) showed that compromising one tool gives you the keys to compromise the next. Your security scanner can become the attack vector. Your CI/CD pipeline can become the exfiltration channel. When the tools you trust to verify trust are themselves compromised, the entire model fails. Reducing the number of external trust relationships is the most direct mitigation available.
Your dependency footprint is probably worse than you think. 97.5% of our codebase was code we didn't write. One Google API package contained 368 service clients we didn't use. These aren't edge cases. This is what modern software looks like when you actually look.
Overestimate the work, let AI surprise you. I told my team "a few weeks" and budgeted billions of tokens. It took two days and 305K tokens. This is becoming a pattern in my work with Claude. The gap between human estimation and AI-assisted execution is still widening. That gap is where the value lives.
Build the guardrails, not just the fork. The fork itself was the easy part. The pre-commit hooks, CI workflows, vulnerability monitoring, SBOM generation, and air-gapped scanning capability are what make it sustainable. Without those, you're just creating a different kind of maintenance burden.
Replace directives are invisible. This was a pleasant surprise. Go's replace directive in go.mod lets you reroute module resolution without changing a single import statement in your application code. Identical binaries. Identical tests. Zero regression. If you're considering this approach, the mechanical risk is genuinely low.
The Policy Going Forward
Here's what the world looks like now for WitFoo's analytics platform:
Go stdlib updates are allowed. The Go team maintains backward compatibility and we trust that process. golang.org/x/* packages are forked and frozen, along with every other external package. No upstream merges. We may reference upstream changes for inspiration when expanding our use cases, but we implement independently.
Every commit is checked by a pre-commit hook that blocks new external dependencies. Every Monday at 7 AM UTC, a CI workflow scans for upstream CVEs published against our forked versions. The pkg/supplychain library handles SBOM generation, manifest parsing, and vulnerability tracking, all built with zero external dependencies of its own.
The capabilities of AI code development offset the feature availability we lose by freezing our dependencies. We can maintain and extend any package in our stack. The Wizard, Warrior, and Poet in us don't need a bazaar of strangers' code anymore. We just need clear requirements and a good AI partner.
Wrap Up
I've been writing about the tension between people and machines for nearly a decade. About the hypnosis of our own technology. About broken processes that we automate instead of fix.
The Nuclear Code Fork is all of those themes converging in a single initiative. We were hypnotized by the convenience of open source dependencies. We had automated a trust-based process in an environment where trust is being actively weaponized. And we needed the human judgment to say "stop, this isn't working" before we could use the machine capabilities to fix it.
Five days before we started, TeamPCP demonstrated exactly what happens when you don't. A security scanner became the attack vector. An AI library became the payload. Compromised developer accounts became the suppression mechanism. The open source supply chain, as Wiz put it, is "collapsing in on itself."
Two days. 305K tokens. 450 packages. 14 vulnerabilities found and fixed. Zero performance regression. Full air-gapped build capability.
I never would have imagined making this decision a few months ago. I'm glad I did.
Charles Herring is co-founder and CEO of WitFoo, a cybersecurity company building collective defense solutions. He is a US Navy veteran and speaks regularly at security conferences including DEFCON, GrrCON, and Secure360. You can find him on LinkedIn.