Software supply chain attacks are a practical risk for any organisation that builds, buys, or runs software. The issue is not limited to open source packages. It also includes source control, build systems, package registries, signing keys, release pipelines, and the suppliers that sit between your developers and your production environment.
For UK SMEs, the main challenge is that modern software delivery depends on trust. Developers trust package managers to fetch the right dependency. Build systems trust service accounts to compile and publish artefacts. Operations teams trust signed updates to be genuine. Attackers look for weak points in those trust relationships because a single compromise can affect many downstream systems at once.
This is why software supply chain risk deserves the same disciplined treatment as identity, endpoint, and network security. It is also why it helps to think in terms of control points rather than headlines. SolarWinds and npm are useful examples, but the lesson is broader: if an attacker can alter what you build, what you install, or what you distribute, they can often bypass traditional perimeter controls.
Key takeaways
- Software supply chain attacks target trusted build, dependency, signing, and release paths, not just the application code itself.
- The most effective SME controls are dependency governance, SBOMs, provenance, code signing, least privilege, and strong pipeline monitoring.
- Build and CI/CD systems should be isolated, tightly permissioned, and treated as high-value assets because they can publish trusted artefacts at scale.
- Detection should focus on unusual workflow changes, token use, package publication, and release activity across source control and pipeline tools.
What software supply chain attacks are and why they matter
A software supply chain attack is any attempt to compromise software before it reaches the user, or while it is being updated, built, signed, or distributed. That could mean tampering with source code, injecting malicious dependencies, stealing release credentials, or abusing a build server to produce trusted artefacts that contain attacker-controlled changes.
How attackers abuse trusted software paths
Attackers prefer trusted paths because they are efficient. A malicious update delivered through a legitimate mechanism is more likely to be installed, less likely to be blocked, and harder to distinguish from normal change. In practice, that means the attacker does not always need to break into every endpoint. They may only need access to one developer account, one CI/CD token, one package maintainer account, or one signing key.
Once inside that path, the attacker can target the software delivery process itself. That might involve changing a build script, replacing a dependency, publishing a lookalike package, or modifying release artefacts after testing but before distribution. The result is a compromise that arrives with the appearance of legitimacy.
Why dependency trust changes the risk profile
Dependency ecosystems create scale. A single library can be pulled into hundreds of applications through direct and transitive dependencies. Transitive dependencies are the packages your packages rely on, often without your team reviewing them directly. That makes the attack surface much larger than the codebase your developers can see in the repository.
For SMEs, this matters because the software estate is often a mix of in-house code, managed services, third-party components, and automation tooling. The more your delivery process depends on external packages and hosted services, the more important it becomes to verify provenance, restrict publishing rights, and monitor for unexpected change. If you want a broader view of how third-party software changes risk, it is worth reading our article on how third-party software introduces cyber risk for UK SMEs.
Common attack patterns seen in software supply chains
Software supply chain attacks tend to fall into a few repeatable patterns. The details vary, but the control failures are often similar.
Compromised build systems and CI/CD pipelines
Build systems are attractive because they sit close to source code, secrets, and release artefacts. If an attacker gains access to a CI/CD platform, they may be able to alter build steps, inject code during compilation, exfiltrate tokens, or publish a backdoored package. Common weaknesses include overprivileged runners, long-lived credentials, poor branch protection, and shared build environments.
In GitHub Actions, GitLab CI, Azure DevOps, or Jenkins, the risk often comes from trust that is broader than necessary. For example, a pipeline that can read production secrets when it only needs test credentials creates unnecessary blast radius. A self-hosted runner that can reach internal services and the internet at the same time may also become a pivot point if it is compromised.
Malicious or hijacked packages in public registries
Public registries such as npm, PyPI, and similar ecosystems are convenient, but they also create opportunities for package hijacking. A maintainer account can be compromised, a package can be transferred, or a new package can be published with a name designed to look legitimate. Once installed, the malicious package may run install-time scripts, collect secrets, or alter application behaviour.
For defenders, the important point is that package trust is not binary. Some packages are well maintained and widely used, while others are lightly reviewed and updated frequently. The more automated your dependency intake is, the more you need controls that detect unexpected package changes before they reach production. Our article on preventing dependency confusion in npm and PyPI pipelines goes into the mechanics of one common failure mode.
Dependency confusion and typosquatting
Dependency confusion happens when a build process pulls a package from the wrong source because the internal and public names overlap. Typosquatting is similar, but the attacker relies on a misspelt package name that developers or automation may install by mistake. Both attacks exploit assumptions about naming and source trust.
These are not sophisticated attacks in the traditional sense. They succeed because package resolution, repository configuration, and developer habits are often treated as convenience issues rather than security controls. The fix is usually straightforward, but it needs to be deliberate: explicit registries, pinned sources, and review of package provenance.
Tampered updates, signing failures, and poisoned artefacts
Even when source code is clean, the artefact delivered to users can still be altered. That can happen if signing keys are stolen, if the release process is not protected, or if artefacts are rebuilt outside a controlled environment. A poisoned artefact may pass through testing if the test and release paths are not aligned, or if the artefact tested is not the same one that is deployed.
This is where signing and provenance become important. A signature only helps if the private key is protected and the verification step is enforced. Provenance only helps if the build process records enough detail to prove where the artefact came from and whether it was built in a trusted environment.
What SolarWinds and npm teach defenders
SolarWinds and npm are often discussed together, but they illustrate different parts of the problem. One is a build and distribution compromise. The other is a dependency and registry risk example. Together, they show why supply chain security needs layered controls rather than a single product or policy.
The SolarWinds case as a build and distribution compromise
The SolarWinds incident showed what can happen when an attacker reaches into the software production process itself. The malicious code was inserted into a trusted update path, which meant customers received it through a mechanism they were already configured to trust. That is exactly why build integrity, release governance, and signing matter. If the release process can be altered, downstream trust collapses quickly.
For defenders, the lesson is not to assume that signed or vendor-managed software is automatically safe. It is to ask whether the vendor’s build and release process is sufficiently controlled, and whether your own environment has compensating controls such as allowlisting, monitoring, and rapid rollback capability.
The npm ecosystem as a dependency and registry risk example
npm demonstrates the scale of dependency risk. A small package can be pulled into many applications, and a compromise in the registry or maintainer account can spread quickly. In JavaScript ecosystems especially, the number of direct and transitive dependencies can become large enough that manual review is unrealistic without tooling.
That does not mean you should avoid public packages altogether. It means you need governance around what is allowed in, how it is pinned, how it is reviewed, and how changes are monitored. If you want a more detailed technical view of the control set, our article on implementing software supply chain assurance controls for technical teams is a useful companion piece.
What these incidents show about trust boundaries
The common thread is that trust boundaries in software delivery are wider than many teams assume. Source control, package registries, build runners, signing services, and deployment automation all sit on the same chain. If one link is weak, the whole chain can be affected.
That is why the right response is not just more scanning. Scanning helps, but it does not stop a compromised maintainer account, a stolen token, or a malicious build step. You need controls that reduce the chance of compromise, limit the impact if compromise occurs, and improve your ability to detect unusual activity early.
How to assess your own exposure
Before you add more tooling, map what you actually rely on. Many organisations have a rough idea of their applications, but a much weaker view of how those applications are built and released.
Map critical software, build paths, and external dependencies
Start with your most important services and work backwards. For each one, identify the source repository, build system, package manager, container base images, infrastructure as code, and deployment mechanism. Then list the external dependencies that matter most, including hosted services that your build or release process calls out to.
A simple spreadsheet is often enough to begin with, provided it captures ownership, criticality, update frequency, and whether the dependency is direct or transitive. If a dependency can affect authentication, payment flows, customer data, or production uptime, it deserves more scrutiny than a low-risk utility library.
Identify where code, packages, and artefacts are introduced
Look for every point where untrusted input enters the delivery chain. That includes package installation, container image pulls, build scripts, release jobs, and manual promotion steps. Pay attention to places where humans can override automation, because those are often the least visible control points.
It is also worth checking whether the same credentials are used across environments. A token that can publish to a registry, modify source control, and access cloud resources creates unnecessary coupling. Segregating those duties reduces the chance that one compromise becomes a full release compromise.
Prioritise internet-facing, privileged, and business-critical systems
Not every dependency needs the same level of control. Prioritise systems that are internet-facing, hold privileged access, or support revenue, regulated data, or operational continuity. For SMEs, this risk-based approach is usually more effective than trying to apply heavyweight controls everywhere.
If you already maintain a risk register or an ISMS, this is a good place to align supply chain risk with existing business impact analysis. That makes it easier to justify controls that protect the systems most likely to hurt the business if they are compromised.
Controls that reduce software supply chain risk
The most effective controls are the ones that reduce trust where it is not needed and verify it where it is. In practice, that means governance, provenance, signing, privilege reduction, and monitoring.
Dependency governance, pinning, and review of transitive packages
Use lock files, version pinning, and explicit repository configuration so builds resolve dependencies from the intended source. Review dependency updates rather than allowing uncontrolled drift. For high-risk applications, consider allowlisting approved packages and blocking direct pulls from public registries unless they have been reviewed.
Transitive dependencies are harder to manage, but they should not be ignored. Tools such as npm audit, pip-audit, Dependabot, Renovate, or Snyk can help surface changes, but the key is to define what triggers review. A package update that changes install scripts, introduces new maintainers, or adds network access deserves more attention than a routine patch release.
SBOM generation and artefact provenance
A software bill of materials, or SBOM, is a structured inventory of components in a software artefact. It helps you understand what is inside a release and whether a newly disclosed issue affects you. SBOMs do not prevent compromise, but they improve visibility and response speed.
Provenance goes a step further by showing how an artefact was built, from what source, and in which environment. For technical teams, this is where frameworks such as SLSA are useful because they encourage stronger build integrity and traceability. If you are building this capability, our article on why SBOMs matter for software buyers and regulators is a good starting point, alongside generating and verifying SLSA build provenance for artefacts.
Code signing, verification, and protected release processes
Sign release artefacts and verify signatures before deployment. Protect signing keys in hardware-backed or tightly controlled key management systems where possible. Separate build, sign, and release duties so no single account can alter the code, sign it, and deploy it without oversight.
Where practical, use immutable artefacts. Build once, then promote the same artefact through environments rather than rebuilding it at each stage. That reduces the chance of environment-specific drift and makes investigation easier if something looks wrong later.
Least privilege for build runners, tokens, and service accounts
Build runners should have the minimum access needed to do their job. Avoid long-lived credentials where short-lived tokens or workload identity can be used instead. Restrict what service accounts can read, write, or publish, and rotate secrets regularly.
In GitHub Actions or similar systems, treat repository secrets as sensitive production assets. Limit who can create or modify workflows, and use environment protection rules for deployments. If a workflow can be modified by a pull request from an untrusted branch, it should not be able to access high-value secrets by default.
Build and CI/CD hardening measures
Hardening the delivery pipeline is one of the highest-value investments you can make because it protects both source and release integrity.
Isolating build environments and reducing secret exposure
Use isolated build environments for sensitive projects. Ephemeral runners are preferable to long-lived shared hosts because they reduce persistence and make it harder for an attacker to maintain access. Keep build containers minimal, and avoid mounting unnecessary credentials or source trees into jobs that do not need them.
Do not expose secrets to steps that only need public dependencies or static analysis. Split jobs so that secret-bearing stages are tightly scoped. This reduces the chance that a compromised dependency or malicious build step can reach sensitive material.
Protecting source control and pipeline credentials
Source control is often the first place to harden. Enforce multi-factor authentication, branch protection, mandatory reviews for workflow changes, and restricted access to release branches. Review who can approve merges into protected branches and who can edit pipeline definitions.
Pipeline credentials should be treated as production credentials. Store them in a proper secrets manager, scope them narrowly, and monitor their use. If a token is used from an unexpected IP address, repository, or time window, that is worth investigating.
Using branch protection, approvals, and change control
Branch protection and approval workflows are not just process overhead. They are a practical control against unauthorised changes to code, build scripts, and release definitions. For higher-risk systems, require at least one independent reviewer for changes that affect build logic, dependency sources, signing, or deployment permissions.
Change control should also cover non-code artefacts such as infrastructure as code, container build files, and package publishing configuration. These files often have the same impact as application code but receive less scrutiny.
Scanning dependencies, containers, and infrastructure as code
Use software composition analysis for dependencies, container scanning for base images and packages, and infrastructure as code scanning for misconfigurations. Tools such as Trivy, Grype, Checkov, and tfsec can help identify known issues and insecure patterns early in the pipeline.
Scanning should be integrated into the release process, not bolted on afterwards. The goal is to stop obvious problems before they become artefacts, while recognising that scanning alone cannot prove a build is trustworthy.
Detection and monitoring for compromise
Even with strong controls, you still need detection. The aim is to spot unusual behaviour in source control, build systems, registries, and release activity before it becomes a wider incident.
Telemetry to watch in source control, CI/CD, and package managers
Monitor for changes to workflow files, package manifests, dependency lock files, signing configuration, and release permissions. In CI/CD systems, watch for new runners, unusual job failures, unexpected outbound connections, and changes to secret access patterns. In package managers, look for new package publications, maintainer changes, and dependency updates outside normal release windows.
Source control audit logs are particularly useful when they are retained long enough to support investigation. If you do not already have a logging strategy for development platforms, it is worth aligning it with your wider monitoring approach and the principles in our article on what security logs you actually need and why.
Alerting on unusual package publication, build changes, and token use
Build alerts should focus on meaningful anomalies, not every routine pipeline event. Good candidates include a new maintainer on a critical package, a release from an unfamiliar IP address, a workflow file modified outside normal change control, or a token used to publish artefacts when it should only read them.
Where possible, correlate events across systems. A package update followed by a new build failure, then a workflow change, then an unexpected release is more informative than any one event on its own.
Using MITRE ATT&CK to structure detection coverage
MITRE ATT&CK is useful here because it helps you describe attacker behaviour in a consistent way. For supply chain scenarios, map techniques such as initial access through trusted relationships, credential access, persistence in build systems, and command execution in CI/CD environments. That gives you a clearer view of what you can detect and where the blind spots are.
If you already use ATT&CK for endpoint or identity detections, extend the same logic to your delivery pipeline. Our article on supply chain attack modelling using MITRE ATT&CK for technical practitioners shows how to approach that mapping in more detail.
Incident response considerations for supply chain events
Supply chain incidents are awkward because the trusted path itself may be the problem. That changes how you contain and investigate.
Containment priorities when a dependency or build system is suspect
If you suspect a dependency, package, or build system is compromised, pause release activity for the affected path first. Revoke or rotate relevant tokens, disable suspicious workflows, and identify which artefacts were produced during the exposure window. If the compromise affects a shared build environment, assume multiple projects may be impacted until proven otherwise.
Do not rely on a single clean scan to clear the issue. Rebuild from known-good sources, verify signatures, and compare artefact hashes where possible. If the release process itself is suspect, treat the pipeline as part of the incident, not just the application.
Evidence to preserve for investigation and supplier engagement
Preserve logs from source control, CI/CD, package registries, identity systems, and cloud platforms. Keep copies of workflow definitions, build logs, dependency manifests, artefact hashes, and any relevant approval records. This helps both internal investigation and any discussion with the supplier or maintainer involved.
It is also useful to record who had access to the affected systems, when credentials were last rotated, and which artefacts were deployed to which environments. That information shortens triage and supports a more accurate impact assessment.
Communicating impact to internal stakeholders and customers
Keep communication factual and proportionate. Internal stakeholders need to know what is affected, what has been paused, and what the likely business impact is. Customers may need to know whether service delivery, data integrity, or update trust has been affected, but avoid speculation until the facts are clearer.
For SMEs, the main objective is to restore confidence in the delivery chain without overpromising. A clear explanation of what was contained, what was rebuilt, and what controls are now in place is usually more valuable than a technical deep dive.
A pragmatic control roadmap for UK SMEs
You do not need to implement every control at once. A staged approach is usually more realistic and more effective.
Quick wins for small teams
Start with the basics: enforce multi-factor authentication on source control and CI/CD, pin dependencies, review workflow changes, restrict publishing rights, and separate build from release permissions. Add SBOM generation for critical applications and begin logging key events from source control and pipeline platforms.
These steps are relatively low cost and can materially reduce risk. They also create a better foundation for later improvements such as provenance verification and stronger artefact signing.
Controls to phase in over time
Next, improve build isolation, adopt short-lived credentials, introduce stricter approval gates for release changes, and formalise dependency review thresholds. For higher-risk products, add provenance verification and enforce signed artefacts before deployment.
At this stage, it is worth aligning supply chain controls with your wider governance model, especially if you already operate an ISMS or are working towards one. That helps ensure the controls are owned, reviewed, and improved rather than left as isolated engineering tasks.
How to balance assurance with delivery speed
The goal is not to slow delivery unnecessarily. It is to remove avoidable trust from the pipeline and focus human review where it matters most. Automate the repetitive checks, keep approvals targeted, and reserve manual scrutiny for changes that affect build logic, signing, publishing, or privileged access.
That balance is usually achievable for SMEs if the controls are designed around risk rather than compliance theatre. In practice, a small number of well-chosen controls often provides more value than a large number of loosely enforced ones.
If you want help turning this into a practical programme, our team can advise on implementation planning, control design, and evidence collection as part of ISO 27001 Consultancy.
Conclusion
Software supply chain attacks are best understood as trust attacks. They target the places where software is assembled, signed, published, and updated, because those are the points where one compromise can affect many systems at once. SolarWinds and npm show different sides of the same problem, but the defensive response is consistent: know your dependencies, protect your build and release paths, reduce privilege, verify artefacts, and monitor for unusual change.
For UK SMEs, the most practical approach is to start with visibility and access control, then add provenance, signing, and stronger detection as the environment matures. That gives you a proportionate control set that supports delivery without ignoring the risk.
Frequently asked questions
What is a software supply chain attack?
It is an attack that compromises software before it reaches users, or while it is being built, signed, updated, or distributed, so that trusted software delivers malicious or altered code.
How can SMEs reduce the risk without slowing development too much?
Start with high-value controls such as MFA, dependency pinning, branch protection, least privilege, SBOMs, and targeted monitoring, then phase in provenance and stronger release governance for critical systems.


Comments are closed