Software Supply Chain
The Hidden Security Risks of Third-Party Software Dependencies
Custom software is assembled from runtimes, packages and build tools maintained by other people. Dependency security requires an accurate inventory, trusted sources, contextual triage and a tested route to replace components.

Bespoke does not mean built from nothing
A modern application may depend on the .NET or Node runtime, framework libraries, NuGet or npm packages, container base images, operating-system packages, JavaScript delivered to browsers and external services. This reuse makes professional software economical. It also imports other organisations' defects and release decisions.
Direct dependencies are only the first layer. A logging package may require a parser, which requires another utility. The vulnerable component can be transitive and absent from the project file a developer reads. Multiple top-level packages can also pull incompatible versions of the same library.
The goal is not zero dependencies. Reimplementing mature cryptography, identity or file-format code can increase risk. The goal is intentional dependency, with enough evidence to update or remove it.
Known vulnerability is only one supply-chain risk
A package may contain an accidental security defect published as a CVE. It may also be malicious, abandoned, taken over by a new publisher or confused with an internal package name. A compromised build account can distribute valid-looking releases before a scanner has advisory data.
Typosquatting targets developer selection. Dependency confusion exploits package-source precedence. Install scripts can execute during restore. Build plugins and CI actions may have access far beyond their apparent task.
Therefore “the scan is green” means no matched advisory under that tool's data and configuration. It does not prove provenance, maintainability or absence of unknown defects.

Start with an inventory you can reproduce
A software bill of materials records the components in an artefact, normally with versions and identifiers. It can accelerate the question “where do we use this?” when an advisory arrives. Formats such as CycloneDX and SPDX support exchange and automation, while the OWASP Software Component Verification Standard provides a broader component-control reference.
An SBOM is useful only when it represents the deployed build. A repository inventory may omit dynamically restored tooling, container packages or a production artefact built from another commit. Generate and retain provenance near the build where possible.
An SBOM also is not a vulnerability report. It tells you what is present; intelligence and context tell you what matters. Protect the inventory appropriately because detailed component information can help both defenders and attackers.
NuGet and npm have different shapes, not different obligations
NuGet projects often have fewer packages than JavaScript applications, but one package can still introduce vulnerable native assets, build targets or transitive libraries. Central package management and lock files can make versions more deliberate where configured correctly.
npm graphs are frequently deep and lifecycle scripts may execute code during installation. Lock files are essential for reproducibility, but locking a compromised or vulnerable version makes the bad result reliably repeatable. Review package changes, scripts and source settings rather than treating the lock file as approval.
Use private feeds deliberately. Define source mapping or precedence so an internal name cannot silently resolve from a public registry. Protect publishing identities with strong authentication and minimal scope.
What automated scanning does well
Tools can compare component versions with security advisories, alert on newly disclosed issues and open update proposals. Integrating this into builds shortens the interval between disclosure and awareness. Repository services and package managers can provide useful first signals.
Scanning also creates false confidence and noise. Version matching can be wrong when vendors backport fixes without changing upstream-looking versions. A package may be present but the vulnerable function unreachable. Conversely, a scanner may miss copied source, bundled binaries or an emerging malicious release with no CVE.
Use scanning to start a decision. Record affected deployments, reachability, exposure, available fixes and verification. Suppressions need a reason, owner and expiry.
Prioritise exploitability and consequence
| Question | Why it matters | Evidence |
|---|---|---|
| Is it deployed? | Development-only packages may have a different boundary | Artefact inventory and SBOM |
| Is affected code reachable? | Presence is not identical to exploitability | Call paths, configuration and vendor detail |
| Is the system exposed? | Internet input changes urgency | Architecture and runtime routes |
| What privilege exists? | Worker rights shape consequence | Identity and network permissions |
| Is exploitation active? | Threat intelligence changes response time | Authoritative advisories |
| Can it be replaced safely? | Fix risk may require staged rollout | Tests, compatibility and rollback |
A severity score is a property of a generic scenario. Your priority is the interaction between the defect and the deployed system.
Updates can introduce risk too
Installing the newest version without review can import breaking behaviour, a compromised release or a new maintainer. Check release notes, publisher continuity, signatures or provenance where available, and the size and purpose of the change.
Prefer small regular updates. A package left untouched for years may require several framework and API changes at once. Automated tests should cover the behaviour that dependency supplies, including parsers, authentication, data access and failure handling.
Roll out with observability and a recovery path. Pinning back to an old version may restore availability but reintroduce the known vulnerability, so document temporary decisions and expiry.
Reduce dependency attack surface
- Remove packages and build actions that are no longer used.
- Prefer mature, maintained components with clear release and disclosure practices.
- Use the platform library when it meets the need rather than adding a package for trivial functionality.
- Pin build tools and CI actions, not only application libraries.
- Restrict package sources and publishing identities.
- Build in isolated workers with minimal secrets and network access.
- Separate runtime identity from build and deployment identity.
- Retain immutable artefacts and component inventories.
Fewer dependencies reduce the review surface, but raw package count is not a security metric. One unmaintained parser at a hostile boundary may matter more than hundreds of build-time utilities.
Prepare for a package you cannot update immediately
Sometimes the fixed release breaks compatibility or no fix exists. Establish whether the vulnerable feature can be disabled, input blocked, component isolated or privilege reduced. Follow vendor mitigations and state their limitations.
Forking a library transfers maintenance to your organisation. It may be necessary, but it is not free: you must track upstream changes, protect publishing and eventually converge or replace it. A private patched binary without provenance can become the next unknown dependency.
Set a time limit and remediation owner. Temporary controls that have no expiry become undocumented architecture.
Questions to ask a software supplier
- Can you produce an inventory for the deployed artefact?
- Which package sources and publishers are trusted?
- How are transitive and container dependencies included?
- Who receives new vulnerability alerts after launch?
- How are findings prioritised and exceptions approved?
- What tests and rollout controls support updates?
- How quickly can a package be removed or replaced?
- What happens when a maintainer abandons a critical component?
These questions test an operating capability rather than requesting a one-off clean report.
Provenance matters before a CVE exists
Ask where an artefact came from, who produced it and whether it is the same one that passed testing. Package signatures, repository attestations and build provenance can strengthen that chain, but only when identities and verification policies are protected.
Do not let release automation fetch mutable scripts directly from the internet. Pin CI actions and build images to reviewed versions or immutable identifiers. A compromised build component can steal deployment credentials even if it never becomes part of the runtime SBOM.
Separate untrusted pull-request builds from protected release jobs. Forked code should not automatically receive production secrets. Use short-lived credentials and restrict outbound access where practical so a malicious build has fewer places to send data.
When a publisher account, registry or build system is compromised, version-based vulnerability scanning may remain silent. Provenance, unusual package behaviour and independent advisories then become essential signals. Supply-chain defence therefore combines component intelligence with control of the path that creates and promotes artefacts.
Make dependency governance part of ordinary delivery
Software supply-chain security is strongest when inventory, review, testing and update are routine. The emergency advisory then enters an existing path rather than creating a new project under pressure.
Related C3 guidance covers post-launch security ownership, unsupported software reviews and security by design.
Keep the inventory current
Regenerate component evidence for every release and retain it with the artefact. A yearly spreadsheet cannot represent software that changes weekly.
Frequently asked questions
Does an SBOM prove software is secure?
No. It supports inventory and response. Security still depends on provenance, vulnerability intelligence, architecture, configuration and maintenance.
Should every vulnerable package be updated immediately?
Every finding needs timely triage. Urgency depends on deployment, reachability, exposure, consequence, exploitation and the safety of the fix.
Are open-source dependencies inherently riskier?
No. Evaluate governance, maintenance, provenance and your update capability. Commercial and internally built components can have the same classes of weakness.
Know which components your custom software inherits
If a business application has an opaque dependency graph or no update route, talk to C3 Software about a focused technical and modernisation review.