Essay
Supply Chain Security using the example of a coffee machine: why your code is bitter
Hello, Habr! My name is Maxim Knyazev, senior systems engineer at K2 Cybersecurity. Today I want to talk about supply chain attacks using an example that everyone understands and loves....

Hello, Habr! My name is Maxim Knyazev, senior systems engineer K2 Cybersecurity . Today I want to talk about supply chain attacks using an example that everyone understands and loves.
Just imagine yourself ordering espresso from a trusted coffee shop. Beans from a famous roaster, an experienced barista, a million-dollar coffee machine. And it would seem that everything is perfect. But then it turns out that someone added something extra to the grains back on the plantation. It’s not your fault, it’s not the coffee shop’s fault, but you don’t want to drink it anymore.
In development, exactly the same thing happens, only npm packages act as seeds here. Plantation turns into GitHub, and suspicious impurities represent malicious code in a legitimate release. And you will learn about problems not by taste, but by an incident in production.
Let's continue this comparison and figure out how not to spoil the components that make up modern cybersecurity.
Ten years ago, software security looked like “roll up a patch and set up a firewall on time,” but today this scheme doesn’t really work in practice. Of course, we still continue to search for and eliminate various threats, but the problem is that modern attacks are less and less likely to break code head-on. Now hackers are more likely to attack through what this code is made of.
In 2025 According to Cyble, analysts recorded approximately 26–30 software supply chain attacks per month. This is almost twice as much as in 2024. More than 70% of organizations experienced serious Supply Chain incidents . The reason is quite simple:
Nowadays, almost no one writes complex software from scratch. Software is assembled like a LEGO set from dozens, hundreds, and sometimes thousands of foreign components. Open source libraries, container images, CI/CD toolchains, plugins, SDKs, scripts - all of this lives its own life: it is updated, changes, sometimes suddenly disappears or, what is much worse, suddenly begins to behave strangely.
And at this moment the attack surface expands, and at the same time an unpleasant realization comes. Even if our code is perfect (which is unlikely to be true, but let’s say), it still reaches the user through a long and unobvious supply chain. And in this chain we do not control everything. This is how the concept of Supply Chain Security, or supply chain security, appears. More about this can be read in the IBM publication .
That is why today they are talking not just about vulnerabilities, but about the origin of code, reproducibility of assemblies, signatures of artifacts, source control, SBOM and many other concepts. All this sounds logical in isolation, but it doesn’t fit well in your head when you start looking at the system as a whole. Direction of the set sleepy, and it makes your brain boil quickly. So let’s try to understand it using something tangible as an example.
A good image really helps to understand the concept, at least if it represents a comparison of relationships and structure . This is confirmed by many studies, for example, article by Mary L. Gick and Kate J. Holyoke. People are noticeably more likely to find a solution to a complex problem if they have previously encountered a similar story from another area. So let's go back to the supply chain and see what's already in the metaphor market.
Supply Chain Security at your fingertips
Let's take SBOM. It is most often compared to the list of ingredients on the product packaging, e.g. Palo Alto Networks article . This approach is promoted by communities like OpenSSF and OWASP , where SBOM is considered as a basic element of the supply chain.
At the same time, information security experts have repeatedly noted that such an analogy explains only part of the picture. It describes the composition well, but says almost nothing about the process, how exactly these components got into the product, where they could be replaced, and why problems arise long before the final assembly. This idea was well explained in articles on LinkedIn .
Sometimes coffee is used as an example, but in a different context. For example, in materials Dark Reading The journey of coffee from plantation to cup illustrates the risks of the physical supply chain: quality control, substitution of raw materials. This is clear but does not address the engineering side of supply chain security.
Inspired by all of the above, I decided to use coffee making as a model for the entire software supply chain. Because this analog process has a surprising amount in common with how modern software is actually put together (and we all love coffee).
The coffee process as a supply chain
Let's imagine an ordinary coffee machine. Not an industrial monster from a coffee shop, but a homemade one that every second person has. And if we are talking about IT specialists, then everyone has the first. It seems like everyone understands how to use it: pressed a button, got coffee, went to sort out the tasks. The process seems simple, until you try to figure out where the coffee comes from and what happens between pressing the button and taking a sip from the cup.
A coffee machine, at its core, like any device, is a system. This is how we will consider it.
Someone grew the grains, collected them, packaged them, transported them and roasted them. Then they came to you, went through millstones, filter, water, press, temperature. And only in the end you get a result that you trust so much that you are ready to drink the resulting drink. And we drink coffee not because we personally checked every stage and component, but because we trust the entire chain: manufacturer, suppliers, brand, standards (and in a coffee shop this chain also includes a third-party barista). We do not do chemical analysis of water and do not fly to check the plantation in Colombia. We just expect coffee to taste like coffee.
Modern software works in a similar way. Users The user presses a button, the service responds, and the business gets the result. And hidden inside is a long chain of components, processes and decisions that almost no one keeps in mind in its entirety.
Sources, dependencies, build, pipeline, infrastructure, environment, configuration... Each step seems logical and safe in itself. But the entire system becomes complex, fragile and dependent on a bunch of things.
The problem is that the coffee machine is at least physical. You can touch it, open it, take it apart. And the software supply chain has little to do with the tangible world. It is spread across repositories, registries, third-party services and people we have never met. This is why supply chain attacks are so often successful. The attacker does not try to mix the poison into the cup itself. He does this much earlier. Where there is no talk of a ready-made drink yet in principle.
Now let’s try to take the coffee machine apart and look inside this system. Let's start with the most obvious and most vulnerable component.
Grains: sources and dependencies
The coffee making process begins with the beans. You can talk as much as you like about the smart functions of the coffee machine and the design of the case, but if the beans turn out to be rotten, the taste of the coffee will be, to put it mildly, so-so.

In software, such grains are the source code and dependencies. Moreover, addictions most often take the lion's share. Your project may consist of a couple of thousand lines of your own code and tens of thousands of lines of someone else's. And that's okay. The problem is different. We almost never know where exactly these “grains” came from, or what happened to them along the way.
The open source library looks safe. Thousands of stars, active community, fresh releases. But who exactly uploaded the last commit? Why was the version updated this way? What else was included in the package besides the declared functionality? The answers to these questions are usually without clear answers.
Just look at the recent (albeit last year’s) example, when in September 2025 attackers gained access to maintainer accounts and introduced malicious code into legitimate releases of popular JavaScript packages, in particular the @ctrl/tinycolor library and other widely used dependencies. As a result, these modified versions were able to steal developer tokens and credentials, and then spread further along the dependency chain. Analysts even described the campaign as a self-propagating worm that affected hundreds of npm packages. And all this was through official releases, which seemed like ordinary updates.
In the case of coffee, this would look strange. Imagine buying beans without indicating the country, variety or roasting date. Just a bag with the word "COFFEE" written on it. Most people won't even open such a package, but in development we do this every day through npm install.
This is where classic supply chain problems arise. Package substitution, compromise of maintainer accounts, malicious versions that live for weeks before anyone notices them. Sometimes, one typo in the name of a dependency (typosquatting) is enough for something completely different to end up in the coffee grinder instead of the usual beans.
But that’s not even the worst thing. If the problem is in your code, it is limited to your product. If sample lem in a popular dependency, it is automatically distributed to thousands of projects. This is no longer an individual mistake, but a massive poisoning of the party.
And yes, at this moment the argument “well, we trust open source” is often heard. And this is true, but the phrase “trust, but verify” has not been canceled. Especially when not only the taste of coffee depends on these beans, but also the health of consumers along with the reputation of the business.
How to choose grains?
Supply chain security starts with understanding what beans you use, where they came from, and whether coffee brewed with those ingredients is even safe to drink.
In practice, this means quite mundane things:
-
Don't ban open source, but stop treating dependencies as something safe by default.
-
Check who maintains the library and how long ago it was updated.
-
Look not only at the stars, but also at the release history, frequency of commits and reactions to incidents.
-
Fix versions. Auto-updates to the latest look convenient, but in reality it’s a habit of buying a new package of beans without looking, because “last time it was fine.”
-
Control sources. Dependencies must come from trusted repositories. If it is possible to check signatures and hashes, then do so. Otherwise, you simply risk not noticing when the attack occurred at all.
And finally, it’s useful to know in advance the answer to a simple question: what do we actually use? Not at the time of the incident, not after a letter from the vendor, but in advance. Because when the coffee has already been poured into cups, it is usually too late (and quite strange) to find out the composition of the drink.
Okay, we've sorted out the grains. But even if the grains themselves are excellent, this is not the end of the story. They can be spoiled further down the chain, for example, at the roasting stage.
Roasting: assembly and CI/CD
Essentially, at this stage, raw materials are transformed into a product, but even the highest quality grains are easy to spoil. Too high a temperature will produce bitterness, too low will make the drink more sour. Roasting time also needs to be taken into account.

In the world of software, roasting can be compared to assembly and CI/CD. This is the very moment when the sources and dependencies turn into a binary, container or artifact that will go further along the chain. And at this stage you need to be especially responsible.
CI/CD is often perceived as a technical detail, like a kind of pipe between code and production. In fact, this is one of the most sensitive points of the entire supply chain. If an attacker controls the build step, he can add anything and it will look completely legitimate.
Compromising the build server does not require hacking your application. All you need is access to a runner, token, secret or plugin. The injection occurs before the release, and then the malicious code is distributed under your signature and your name.
In our analogy, this is very clear: the grains were excellent, but someone added some kind of impurity at the roasting stage. When it comes out, the coffee smells normal, looks normal, but the taste is different. And the consequences of tasting may not appear immediately.
There is another problem with CI/CD - automation. Pipelines work quickly, often without human intervention. This is their strength and their weakness. Error or compromise multiplies instantly ovno and leaves further along the chain even before anyone has time to notice it.
Let’s add here common runners, outdated plugins, “just in case” access, secrets that live for years, and we get an ideal environment for attacks. It’s no wonder that most high-profile supply chain incidents involve the assembly stage in one way or another. Also in 2025 attackers modified the popular GitHub Action tj-actions/changed-files, used in many CI/CD workflows. The malicious version allowed runners' memories to be leaked, potentially including secrets and tokens.
Therefore, control over the “roasting” is incredibly important: isolated assemblies, minimal access, reproducibility, control of what ended up in the artifact.
But even perfectly roasted coffee can be ruined in the next stages of preparing the drink. Sometimes it’s enough just not to know what exactly was put in it. And then the filter appears.
Filter: SBOM as ingredient list
Not every coffee machine has a separate filter that is easy to spot. Sometimes it is built into the structure, sometimes its role is played by the capsule itself. But the idea remains the same: between the raw material and the cup there is a mechanism that determines what exactly ends up in the drink.

In supply chain security, the role of a filter is played by SBOM . Essentially, this is a list of the ingredients of your product: what exactly is in it, in what versions, where it comes from, and how it relates to each other. Without SBOM, software is like coffee from a cardboard glass with a lid. It's hot, it smells familiar, it seems invigorating, but the contents remain a mystery. And at the moment of the incident, this mystery turns into a problem.
There is a vulnerability in a popular library. Or the package is compromised. Or version review. And here a simple question arises: “do we have it or not?” Without SBOM, the answer usually sounds like “let’s see now,” and then manual searches begin, grep for dependencies and attempts to reconstruct the picture retroactively.
With a filter everything is different. SBOM does not directly prevent the problem. It will not eliminate the vulnerability or stop the attacker. But it sharply shortens the path from the moment when it became clear that “something went wrong” to the moment when you at least understand whether it concerns you or not. In our analogy, this looks extremely clear. If we know the exact composition of a drink, we can quickly understand whether it is dangerous or not. But if we don’t know this, we can only hope that it will pass.
Therefore, SBOM is increasingly emerging as a mandatory component of the supply chain. Regulators and customers are beginning to demand it. Because without a list of ingredients, no one wants to drink what's in the cup anymore.
Okay. Let's say we are confident that our grains are of high quality. We fried them correctly. There is a filter. The composition of the ingredients is known. But that’s not all. And here we come to the next component, which seems to be the most obvious, but one of the most underestimated.
Water: environment and infrastructure
You can take the perfect beans, roast them correctly and carefully pass them through the filter. But if the water is bad, the coffee will still be disgusting: with a taste, smell or a strange aftertaste. And it seems like it’s not the grains or the coffee machine that are to blame, but the result still doesn’t make you want to drink it.

In the end In the software text, water is the environment and infrastructure: hosts, containers, base images, Kubernetes, registry, runtime, system libraries.
Infrastructure is rarely seen as part of the supply chain. It is considered something secondary, servicing, but in fact it directly affects the safety of the final product. A vulnerable base image, old OpenSSL, compromised registry or shared namespace can be a threat.
In our analogy this would look absurd. No one would brew coffee with water from a suspicious source, even if the beans were premium quality. This happens all the time in development. We take “some” basic image because it’s popular. Or “temporarily” disable checks. Or we use a common cluster for everything.
What makes infrastructure especially insidious is that it scales problems. One vulnerable image can be used by dozens of teams, and one insecure registry can be a source of trouble for hundreds of services.
Therefore, in my opinion, infrastructure is also part of the supply chain. It shapes the environment in which the code is executed and influences which dependencies are actually used, which libraries are picked up dynamically, and which vulnerabilities are available to an attacker in runtime. Therefore, supply chain security is not limited to code and assembly. It’s also about “clean water.” About image control, updates, minimizing environments and understanding what exactly your coffee is brewed on.
But even perfectly filtered water does not guarantee that the coffee machine will work, because there is another element that often becomes a source of unexpected problems.
Barista: people and processes
Even the smartest coffee machine doesn't work on its own. Someone fills in the beans, cleans the filter and decides when it’s time to service the machine.

In the supply chain, we can look at baristas as people and processes. Developers, DevOps engineers, security specialists, release managers. And also regulations, deadlines, access, agreements.
At this stage a paradox arises. Almost every supply chain incident looks like a purely technical problem on paper, but when you dig deeper, it almost always turns out that human error was involved. Let's say a secret that was "temporarily" committed, or a token that was issued "accidentally". Some kind of runner under root, because it’s faster and no one complained. A check that was disabled because it was slowing down the release.
In the process of making coffee, it would look like this: the barista decided not to wash the coffee grinder because he was too lazy. Or added something at my own discretion. Or he even allowed an outsider into the process because the person did not arouse suspicion. The taste of the drink may not change immediately, but the risk that something will go wrong increases immediately.
People get tired, make mistakes, rush, trust and overestimate their own control over the situation. Therefore, processes are as important as tools. And this needs to be controlled through minimal access, explicit processes, audits and a culture in which security is part of the product itself.
A bad barista can ruin even the perfect coffee. But a good one is able to save the situation, even if something went wrong at the previous stages.
And now that we have sorted everything out yu internal filling, it's time to look at the result.
Output cup: what the user ultimately drinks
The user never sees the grain. He doesn’t know exactly how they were roasted, what filter was used, or who brewed this coffee for him today. He just gets a cup of drink. Hot, fragrant and, he hopes, safe for health.

With software, everything happens in a similar way. The user interacts only with the final product. The application starts, the service responds, the data is processed. Everything that happened before this moment remains unclear to him. And this is not a problem, because the user is not required to understand your supply chain, but that is why the responsibility for this entire chain falls on you.
The user trusts the brand, service, company. He believes the product is safe by default. And every incident in the supply chain undermines this trust.
The most frustrating thing about this is that the outcome of a compromised supply chain often appears to be completely correct. The product can work normally, tests can pass confidently. Until it's too late. This is why supply chain attacks are so dangerous; they remain invisible for a long time at the cup level.
To continue our coffee analogy, it's like a batch of coffee that tastes okay but causes problems after a while. The user cannot determine this independently. He can only stop coming to this coffee shop.
In this case, a natural question arises. If the user only sees the cup, and all the problems are hidden earlier in the chain, then what do attacks on the coffee making process even look like? Let's get creative with the analogy and look at real supply chain incidents.
How is the supply chain broken?
The unfortunate thing about attacks on Supply Chain is that they rarely look like cyber attacks in the traditional sense. Nothing crashes, no alerts appear, services work correctly. The attacker does not break the entire system, but chooses the moment when he can infiltrate the process unnoticed. Sometimes even before the “grains” even get into the kitchen.
There is a wonderful phrase: “It takes a thief to catch a thief.” To catch a criminal, you need to think like a criminal. So let's think about how to attack the coffee making process:
-
Substitution of grains (Dependency Confusion / Typosquatting). If I wanted to spoil the coffee, I would replace the normal beans with bad ones. In software, this is a compromise of a popular dependency, takeover of a maintainer’s account, or a malicious update. On the outside everything is legitimate, but on the inside there is a surprise. Moreover, this is often done not for the sake of immediate hacking, but for the sake of a quiet presence in order to use the resulting loophole in the future.
-
Roasting attack (CI/CD Injection). I would try to get involved in the process of roasting the beans. These are attacks on build scripts, plugins, and runners. Malicious code gets into the component automatically and spreads itself. Think SolarWinds. Then the compromise of the build process led to the fact that the malicious the update has reached thousands of customers .
-
Water poisoning (Infra Compromise). The registry or base image can be compromised. The code is high quality , the assembly is correct, but in runtime the application receives extra features that were not planned.
-
Human factor. Token in public repo. Temporary access turned permanent. These things look like a targeted attack, but they are how supply chain problems are fully exploited.
How to protect your supply chain
After all these stories, the first reaction is usually the same for everyone. Urgently encrypt everything, sign everything and stop trusting anyone. The impulse is understandable, but in reality it often leads not to safety, but to stupor. This way you won’t be able to make coffee or develop software. The point of supply chain security is not to freeze the process. It's about making it understandable and manageable.
-
It all starts with the sources. From understanding where dependencies come from, which of them are acceptable and which are not at the level of specific repositories, owners and versions. This seems like something not particularly important until the first incident, after which suddenly everyone has questions.
-
Next comes the assembly. It should be isolated, reproducible and rely as little as possible on the environment. CI/CD here is not so much a convenient tool as an important part of the supply chain itself. As my calculus teacher used to say, “Don’t fool yourself.”
-
SBOM represents culture, not just reporting. Developers should refer to it regularly.
-
Infrastructure is like water in coffee. Base images, registry, clusters and runtime cannot be considered someone else's secondary area of responsibility. They are either a conscious part of the supply chain or a ready entry point for an attacker.
-
And, of course, people. Not even the most advanced tool or technology can save you if processes are built solely on trust. Minimal access and privileges, short-lived tokens and protection from random errors are needed because we are all alive and sometimes we make mistakes.
If you need a specific reference point and have no desire to reinvent wheels, look towards models like SLSA (Supply-chain Levels for Software Artifacts) . You may not learn how to brew coffee better, but you can make your supply chain much safer.
Next time you deploy, try to visualize a coffee machine. Beans, roasting, filter, water and barista. If at some stage you feel uneasy, then that’s where you should look first.
The supply chain doesn't end with this article. To your
coffee
the code remained without impurities,
subscribe to my TG channel
. There I analyze attacks on Supply Chain, new vulnerabilities, IoT security and share stories from practice.
Discussion
Comments
Comments are available only to confirmed email subscribers. No separate registration or password is required: a magic link opens a comment session.
Join the discussion
Enter the same email that you already used for your site subscription. We will send you a magic link to open comments on this device.
There are no approved comments here yet.