Start with the artifact that actually runs
Internally written code is only one part of a production system. Package managers introduce direct and transitive dependencies, while container images add operating-system packages, language runtimes, certificates, and sometimes build tools. Reviewing a Git repository alone cannot reveal exactly what is running. When a dependency is compromised or a new vulnerability is disclosed, the useful question is not whether the package appears somewhere in source control, but which deployed artifacts contain it and where those artifacts are running.
Begin by mapping ownership and the delivery path. Each service should have an accountable team, source repository, build pipeline, image repository, and known deployment environments. A production artifact must be traceable back to its commit and build record. The reverse lookup is equally important: given a component and version, the team should be able to identify affected images, services, and environments. This bidirectional traceability is the foundation for useful vulnerability management, incident response, and audit evidence.
Balance reproducible dependencies with timely updates
Application dependencies should be resolved into a committed lockfile, and CI should install them in a mode that fails when the manifest and lockfile disagree. Broad version ranges may be convenient during development, but allowing production builds to resolve them again means the same source revision can produce different artifacts on different days. Pinning everything indefinitely creates the opposite problem: vulnerabilities and compatibility debt accumulate until an urgent upgrade becomes risky.
A practical approach is to pin production inputs while maintaining a predictable update cadence. Automated tooling can propose dependency changes, but tests and engineering review should decide whether they are accepted. Critical fixes may need an expedited path; routine upgrades can be grouped to reduce review overhead. For important systems, a controlled package proxy can retain approved versions and reduce dependence on public registry availability. That proxy is itself critical infrastructure, however, and needs access controls, integrity checks, availability planning, and a retention policy.
- Source: Restrict approved registries and block unplanned downloads from unknown locations.
- Version: Commit lockfiles, retain package hashes, and reject floating resolution during release builds.
- Review: Examine maintenance activity, licensing, release history, requested privileges, and transitive dependency cost before adding a library.
- Update: Separate immediately actionable fixes from upgrades requiring compatibility work or time-bound risk acceptance.
- Removal: Regularly eliminate unused and overlapping dependencies; a package that is not included cannot become part of the attack surface.
Treat a container image as an immutable release
Deploy images by digest rather than relying only on mutable tags. Once an image passes validation, promote that exact artifact through testing and production instead of rebuilding it for each environment. Rebuilding can silently change base-image or package contents even when the application commit is unchanged. Pin base images, use multi-stage builds to exclude compilers and temporary files, and run application processes as a non-root user wherever the workload permits.
Smaller images generally reduce attack surface and scanner noise, but minimalism has an operational cost. Distroless images work well for stable services with strong logging, metrics, and remote debugging practices. Workloads that require frequent on-host investigation may justify a limited diagnostic toolset or a separate ephemeral debugging container. The objective is not the smallest possible file size; it is a deliberate inventory in which every included component has a reason to exist.
Scan both operating-system and application packages, but do not make a severity score the only release decision. Engineers should also ask whether vulnerable code is present in an executable path, externally reachable, protected by compensating controls, and supported by an available fix. Block releases for exploitable issues with realistic remediation, while documenting an owner, deadline, and controls for accepted exceptions. Image signing and build provenance add another layer by proving that an artifact came from an approved pipeline and was not replaced after validation.
Operate the SBOM as response data, not paperwork
Generate an SBOM automatically for every build using a machine-readable format such as SPDX or CycloneDX. Bind it to the artifact digest, source revision, and build record, then store it in a searchable system with access and retention rules aligned to the artifact. A detailed SBOM that cannot be matched to a deployed image is little more than a compliance attachment. The association between inventory and immutable artifact identity is what makes the data operationally useful.
When a vulnerability is announced, the response workflow should query the affected component and version, locate related images and services, identify their environments and owners, and then assess exploitability. Scanner findings, runtime context, and VEX information can distinguish components that are merely present from those that create an actionable exposure. This avoids forcing every team to patch every theoretical finding immediately and directs attention toward systems with credible risk.
Finally, rehearse the workflow. Choose a dependency, trace it to production services, and confirm that the organization can rebuild, patch, sign, promote, and deploy the replacement. An SBOM does not prevent compromise by itself; its value depends on accuracy and on whether engineering, operations, and security teams can act on it. In environments spanning cloud services, ERP, CRM, LINE, or IoT platforms, an integration team can help establish shared artifact identities and workflows, while service-level risk ownership remains explicit.