August 29, 2026 / custom-software, security, open-source, utah-business
Software Supply Chain Risk: What Is Inside Your Custom App
Most of the code running your custom software came from strangers on a public registry. Here is what changed in the past year, and the five questions worth asking.

The part of the build nobody itemizes
When you commission software, you picture a developer writing your software. Some of that happens. Most of what ends up running in production is code neither of you wrote, fetched automatically from a public registry by the build process, and it arrives without a human reading a line of it.
Here is a number you can check for yourself. This site, the one you are reading, declares twelve direct production dependencies. The lockfile resolves those twelve into 264 packages. That ratio is ordinary, and 264 is on the small end for a business application. The practical meaning is that 264 separate parties can change what your website does the next time it builds, because a new version of any of them flows straight into your app unless something stops it.
That is not an argument against open source. Writing everything from scratch would be worse in every dimension including security. It is an argument for knowing which of your defaults are switched on.
This post is narrower than our piece on AI generated code security, which asks whether the code your developer produced holds up. It sits beside who owns your custom software, which asks whose it is on paper. The question here is different and more mechanical: what is in there, and how did it get in.
What actually happened, in order
The reason this stopped being a specialist concern is a specific sequence of events, and the dates matter.
In September 2025, attackers compromised the accounts of maintainers behind widely used JavaScript packages and published poisoned versions. Days later the same technique produced something new. CISA issued an alert on September 23, 2025 describing a self replicating worm, publicly called Shai-Hulud, that had compromised over 500 packages.
Read what the malware did, because it explains why a small business is exposed. It scanned the machine it landed on for credentials. It targeted GitHub personal access tokens and API keys for Amazon Web Services, Google Cloud Platform, and Microsoft Azure. It sent what it found to an attacker controlled endpoint, then published the stolen credentials into a public repository. Then it authenticated to the registry as the developer it had just robbed and injected itself into further packages.
The vehicle was a package install script, the kind that runs automatically the moment a dependency is added. Nobody had to open a file or click a link. Installing was the whole attack.
A year of data puts that incident in context. Sonatype's 2026 State of the Software Supply Chain report counted more than 454,600 new malicious packages during 2025, bringing the cumulative total it has identified and blocked to over 1.233 million across npm, PyPI, Maven Central, NuGet, and Hugging Face. Over 99 percent of that open source malware landed on npm, which is the registry behind most modern websites and web applications.
The registry then changed its own rules, and those changes are the clearest signal of how serious this got. GitHub, which operates npm, disabled creation of classic access tokens on November 5, 2025 and capped write capable granular tokens at a ninety day maximum lifetime. After one extension of the deadline, all remaining classic tokens stopped working permanently on December 9, 2025. The replacement npm now points maintainers toward is trusted publishing, which uses short lived identity issued by the build system instead of a long lived secret sitting in a settings page.
Why this reaches a business with six employees
Because you were never the target. That is the part owners have backwards.
Nobody selected your company. These campaigns run on volume: publish malicious versions at scale, wait for automated builds to pull them in, harvest whatever credentials sit on the machines that ran the install. Your application is one of tens of thousands of doors, and the attacker never learned your name.
Which also means the damage is rarely defacement. You will probably not see it happen. The blast radius is credentials: your hosting account, your cloud storage keys, your payment processor's API key, the mail service that sends your receipts, the database holding your customer list. A compromise that starts in a package you have never heard of ends in an account you use every day.
The five questions to ask your developer
None of these require you to evaluate the answers technically. You are listening for whether a considered decision exists behind them.
1. Is there a lockfile committed, and does the build install from it?
A lockfile pins the exact version of all 264 packages, not just the twelve you asked for. Without one, two builds a week apart can produce different software from identical instructions. CISA's own remediation list for the npm compromise begins with checking lockfiles to identify affected packages, including ones nested deep in the tree. The follow up question is whether the build installs strictly from that file rather than resolving fresh versions each time. A good answer names a specific command. A vague answer is the finding.
2. Do installs run package scripts?
This is the mechanism from the incident above. Install scripts execute code from the package the moment it is added, before anyone has looked at anything. Turning them off by default breaks a small number of legitimate packages, which then get allowed individually and deliberately. That tradeoff is worth hearing your developer articulate out loud.
3. Who updates dependencies, and how often?
Two wrong answers exist and they are opposites. Never updating leaves known vulnerabilities in place for years and turns a routine patch into a rewrite, which is how a three year old application arrives early at legacy software modernization. Auto merging every update the minute it publishes is how you install a poisoned version at machine speed. What you want is scheduled updates, a short holding period before adopting brand new releases, and a person who reads what changed.
4. Can you produce a list of everything in the application?
That list has a name, a software bill of materials, and CISA maintains public guidance on it. For a small business build this is not a compliance project. It is a file your developer can generate in about a minute from the lockfile that already exists. Its value shows up on the bad day: when the next incident is announced with a list of affected packages, you can answer in five minutes instead of five days.
5. Where do the deploy credentials live, and when were they last rotated?
Every token that can publish or deploy your software is a token worth stealing. Ask where they are stored, who can read them, and what the rotation schedule is. The registry itself now enforces ninety day lifetimes on write capable tokens, which is a reasonable floor to hold your own setup to.
What this looks like on a real small build
Our default is boring on purpose. Dependency counts stay deliberately low, because every package you decline to add is one you never have to patch, audit, or explain later. Lockfiles are committed and builds install from them. Updates happen on a schedule with a human reading the change, not on a webhook.
The Doggy Den site we built runs today under an ongoing care plan, and this is most of what that care plan actually consists of: keeping the dependency tree current and unremarkable so nothing ever becomes urgent. For As You Wood we completed the website work and continue on ecommerce SEO, where the same discipline matters more, because a storefront sits next to payment credentials.
We are building a healthcare analytics dashboard for a residential treatment provider, and there the dependency conversation happened before the first line of code, because the credentials in scope are the kind you cannot rotate quietly after an incident. We are also building a site for a private practice therapist here in Salt Lake City, where a smaller dependency surface was worth giving up two conveniences for.
What to do this month
Three things, in this order.
Ask your developer question one and question five. Those two cover the mechanism and the consequence, and the answers fit in a single email.
Ask for the dependency list and save it somewhere you can find it again. Not for reading. For the day a name in the news needs matching against something.
Then look at where else those same credentials are used. If the token that deploys your website is also the token that reaches your customer database, that is a larger finding than anything in your dependency tree, and you can fix it without touching code. That separation is part of what we set up in every custom software engagement, and it costs nothing extra at the start.
If you are not sure which of these already apply to your build, we will look and tell you plainly.
Frequently asked questions
Should I ask my developer to stop using open source packages?
No, and a developer who agreed would be doing you harm. Rewriting a date library or an authentication flow from scratch produces code that is less reviewed, not more. The goal is a smaller and better understood dependency tree, not an empty one.
My site is on a website builder, not custom software. Does any of this apply?
Less directly, and that is a genuine advantage of hosted platforms. Your vendor absorbs this problem, which is one of the honest points in favor of buying, covered in our post on buy vs build. What still applies to you is question five: the credentials connecting that platform to your other systems are yours to protect.
How would I even know if something like this hit us?
Usually through an announcement rather than a symptom, which is exactly why the dependency list is worth having in advance. The secondary signal is credential misuse: logins you cannot account for, unexplained cloud charges, mail sent from your domain that nobody at your company sent.