# Dependency Management Policy: [Organisation or product line]

> Policy for adding, sourcing, pinning, updating, monitoring and removing third-party dependencies: open source and commercial libraries, container base images, build plug-ins and CI actions. It sets intake criteria, approved sources, lock and integrity rules, update cadence with a release-age cooldown, vulnerability and malicious-package response, licence gates, vendoring and removal. It is based on NIST SP 800-218 SSDF version 1.1 practice PW.4 (reuse existing, well-secured software) and uses OpenSSF Scorecard v5 checks and the OpenSSF Open Source Project Security Baseline (OSPS Baseline, release v2026.08.28) as evaluation signals, with the CISA Known Exploited Vulnerabilities (KEV) catalog as an exploitation signal. Replace every `[bracketed]` value and every row marked *Example*.

<!--
Guidance: How to use this template
- This policy governs how dependencies are chosen and kept healthy. The
  enterprise remediation SLAs for vulnerabilities belong to the
  Vulnerability Management Policy (`security/vulnerability-management-policy`);
  SBOM production and VEX belong to the SBOM and VEX Policy
  (`security/sbom-vex-policy`); the periodic supply chain assessment is
  Software Supply Chain Security (`security/supply-chain-security`).
  Link to them instead of repeating their rules.
- Fill section 4 (ecosystems and tiers) first. Intake depth, update
  cadence and exception authority all scale with the tier.
- Set the cooldown (section 7.2) with the security team: it trades a
  short delay on new versions for protection against compromised
  releases that are usually detected and pulled within days.
- The worked example is the fictional SaaS company Corvid Commerce.
  Package names in examples are fictional.
- Main pitfall: a policy that only covers application libraries and
  forgets CI actions, base images and build plug-ins, which run with
  more privilege than most application code.
-->

## Document control

<!-- Guidance: Identify the policy, its owner and scope. Changes to tiers, cooldown periods or licence categories are minor versions; changes to approved sources or mandatory gates are major versions. -->

| Field | Value |
|---|---|
| Document ID | [POL-DEP-001] |
| Version | [0.1] |
| Status | [Draft / Approved / Superseded] |
| Owner | [@platform-engineering-lead] |
| Approvers/reviewers | [@vp-engineering], [@appsec-lead], [@legal-open-source-counsel], [@architecture-board-chair] |
| Last updated | YYYY-MM-DD |
| Classification | [Internal] |
| Applies to | [All repositories, build pipelines and images owned by Organisation] |
| Ecosystems in scope | [npm/pnpm, Maven, PyPI, Go modules, container images, GitHub Actions, Terraform providers] |
| Effective from | YYYY-MM-DD |
| Next scheduled review | YYYY-MM-DD |

### Approvals

| Role | Name | Decision | Date |
|---|---|---|---|
| VP Engineering | [@name] | [Approve / Approve with conditions / Reject] | YYYY-MM-DD |
| Application security lead | [@name] | [Decision] | YYYY-MM-DD |
| Open source counsel | [@name] | [Decision] | YYYY-MM-DD |
| Architecture board chair | [@name] | [Decision] | YYYY-MM-DD |

### Revision history

| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [@name] | First draft |
| 1.0 | YYYY-MM-DD | [@name] | *Example:* Approved; 7-day cooldown made mandatory for Tier 1 services |
| 1.1 | YYYY-MM-DD | [@name] | *Example:* CI actions pinned by commit SHA added to section 6 |

## Contents

<!-- Guidance: Keep this list aligned with the headings. -->

1. [Purpose, scope and principles](#1-purpose-scope-and-principles)
2. [Roles and responsibilities](#2-roles-and-responsibilities)
3. [Policy statements](#3-policy-statements)
4. [Ecosystems, dependency types and tiers](#4-ecosystems-dependency-types-and-tiers)
5. [Intake of a new dependency](#5-intake-of-a-new-dependency)
6. [Sourcing, pinning and integrity](#6-sourcing-pinning-and-integrity)
7. [Updates and cooldown](#7-updates-and-cooldown)
8. [Vulnerable and malicious dependencies](#8-vulnerable-and-malicious-dependencies)
9. [Licence compliance](#9-licence-compliance)
10. [Forks, vendoring and patches](#10-forks-vendoring-and-patches)
11. [Removal and end of life](#11-removal-and-end-of-life)
12. [Exceptions and risk acceptance](#12-exceptions-and-risk-acceptance)
13. [Compliance measurement](#13-compliance-measurement)
14. [Review cycle](#14-review-cycle)
15. [Glossary and references](#15-glossary-and-references)

## 1. Purpose, scope and principles

<!-- Guidance: Explain why dependencies need a policy. Questions: how many direct and transitive dependencies do your products have? Which incidents (compromised package, abandoned library, licence surprise) has the organisation already had? Pitfall: a scope that excludes build-time tools, so the most privileged code escapes review. -->

### 1.1 Purpose

Most of the code [Organisation] ships was written by someone else. This policy makes sure that code is chosen deliberately, comes from where we think it comes from, is the exact version we tested, stays patched, is legally usable, and is removed when it is no longer needed. It implements SSDF practice PW.4 (reuse existing, well-secured software): task PW.4.1 (acquire well-secured third-party components and keep them maintained), task PW.4.4 (verify that third-party components keep meeting our requirements over their life cycle) and, for shared components built in-house, task PW.4.2.

### 1.2 Scope

In scope: every third-party component that is compiled into, bundled with, loaded by or used to build software we ship or operate. This covers direct and transitive library dependencies, container base images, OS packages installed in images, build plug-ins and compilers, CI actions and reusable workflows, infrastructure-as-code modules and providers, AI models and datasets pulled from public hubs, and commercial SDKs.

Out of scope: SaaS services consumed over the network (covered by supplier security assessment) and developer desktop tools that do not take part in builds.

### 1.3 Principles

- Fewer, better dependencies. Every dependency is attack surface, licence obligation and maintenance cost.
- Reproducible resolution. A build resolves the same bits today and in a year.
- Trust is checked, not assumed. Provenance, signatures and integrity hashes are verified where the ecosystem provides them.
- Updates are routine, small and automated, so that urgent security updates are not also large migrations.
- The owning team owns its dependencies, including transitive ones.

## 2. Roles and responsibilities

<!-- Guidance: Name who approves new dependencies and who is on the hook for keeping them current. Questions: does a central team approve every package, or only high-risk ones? Pitfall: a central approval queue so slow that teams vendor code to avoid it. -->

| Activity | Owning team | Platform engineering | AppSec | Open source counsel | Architecture board |
|---|---|---|---|---|---|
| Propose and evaluate a new dependency | R | C | C | C | I |
| Approve a Tier 1 or restricted-licence dependency | R | C | A | A (licence) | C |
| Operate registry proxy, update bots and scanners | I | A/R | C | I | I |
| Keep dependencies within update targets | A/R | C | I | - | - |
| Triage vulnerable or malicious dependency alerts | R | C | A | - | - |
| Maintain licence allow and deny lists | C | C | I | A/R | I |
| Approve forks and vendored copies | R | C | C | C | A |
| Approve exceptions (section 12) | R | C | A | C | C |

R = responsible, A = accountable, C = consulted, I = informed.

## 3. Policy statements

<!-- Guidance: Number each rule so pull request checks, audits and exceptions can cite it. MUST is mandatory, SHOULD needs a recorded reason to skip. Pitfall: rules nobody automates, which decay within a quarter. -->

| ID | Statement | Enforced by |
|---|---|---|
| DEP-01 | New direct dependencies MUST pass the intake review in section 5 for their tier before merge. | Dependency review check on pull requests |
| DEP-02 | Builds MUST resolve dependencies only through approved sources (section 6.1). | Network egress policy of build runners; registry configuration |
| DEP-03 | Every repository MUST commit a lock file, and CI MUST install in frozen-lockfile mode. | CI lint |
| DEP-04 | CI actions and reusable workflows MUST be pinned by full commit SHA; container base images MUST be pinned by digest. | Scorecard Pinned-Dependencies check; policy as code |
| DEP-05 | Non-security version updates SHOULD respect the cooldown in section 7.2. | Update bot configuration |
| DEP-06 | Dependencies MUST stay within the currency targets in section 7.1. | Dependency dashboard |
| DEP-07 | Known vulnerable dependencies MUST be remediated within the SLAs of the Vulnerability Management Policy; KEV-listed vulnerabilities take the fastest SLA. | SCA scanner, ticketing |
| DEP-08 | A dependency confirmed malicious MUST be treated as a security incident (section 8.3). | Incident process |
| DEP-09 | Dependencies MUST have a licence in the allowed list, or an approved review, before release (section 9). | Licence scanner |
| DEP-10 | Forked, vendored or patched third-party code MUST be registered (section 10). | Repository audit |
| DEP-11 | Unused dependencies SHOULD be removed within one release cycle of detection. | Unused-dependency report |
| DEP-12 | Products MUST produce an SBOM covering all shipped dependencies, as set by the SBOM and VEX Policy. | Release pipeline |

## 4. Ecosystems, dependency types and tiers

<!-- Guidance: Classify so that effort goes where risk is. Questions: which repositories build customer-facing or regulated products? Which dependencies run with secrets or network access at build time? Pitfall: treating a test-only dependency and a payment-path parser the same way. -->

### 4.1 Dependency types

| Type | Examples | Main risks |
|---|---|---|
| Runtime library | Parsers, HTTP clients, crypto wrappers | Vulnerabilities reachable in production; licence obligations on distribution |
| Build and test tooling | Compilers, bundlers, test runners, linters | Code execution in CI with access to secrets and signing keys |
| CI actions and workflows | Checkout, cache, publish actions | Direct access to repository tokens and release credentials |
| Container base image and OS packages | Distroless or minimal OS images | Large inherited vulnerability surface; drift |
| Infrastructure modules and providers | Terraform providers, Helm charts | Cloud credentials at apply time |
| Models and datasets | Pretrained models, tokenizers | Unsafe serialisation formats, provenance and licence |
| Commercial SDK | Payment or analytics SDKs | Closed source, vendor support lifecycle |

### 4.2 Tiers

Tier is set per repository by the highest-risk product it feeds.

| Tier | Applies to | Intake review | Update target | Exception approver |
|---|---|---|---|---|
| Tier 1 | Customer-facing production services, shipped products, release and signing pipelines | Full review (5.2) with AppSec sign-off | Section 7.1 strict column | AppSec lead |
| Tier 2 | Internal production services, shared libraries | Standard review by a second engineer | Section 7.1 standard column | Engineering manager |
| Tier 3 | Prototypes, test fixtures, internal scripts not deployed | Self-check against 5.1 | Best effort; security fixes still mandatory | Team lead |

| Repository | Tier | Ecosystems | Direct deps | Transitive deps |
|---|---|---|---|---|
| corvid-checkout-api *(Example)* | 1 | Maven, container | 48 | 312 |
| corvid-storefront *(Example)* | 1 | npm (pnpm), container | 61 | 1,204 |
| corvid-ops-scripts *(Example)* | 3 | PyPI | 9 | 37 |
| [Repository] | [Tier] | [Ecosystems] | [N] | [N] |

## 5. Intake of a new dependency

<!-- Guidance: Decide whether a new dependency is worth its cost. Questions: could the standard library or an existing approved dependency do this? Is the project maintained and does it follow basic security practices? Pitfall: adding a large framework to use one function. -->

### 5.1 Questions for every intake

1. Need: what does it do that the standard library, the platform or an existing approved dependency does not?
2. Size: how many transitive dependencies does it add? Does it run install scripts?
3. Maintenance: are there releases and responses to issues in the last 12 months? More than one active maintainer?
4. Security practices: does it publish a security policy, sign releases or publish provenance, and have a reasonable OpenSSF Scorecard result?
5. Vulnerability history: open known vulnerabilities, and how fast past ones were fixed.
6. Licence: is the declared licence in the allowed list, and do file-level licences agree with it?
7. Identity: is this the genuine package (not a typosquat or a namespace confusion), from the expected publisher?
8. Exit: how hard would it be to replace?

### 5.2 Full review criteria (Tier 1)

| Criterion | Signal | Pass threshold *(Example)* | Weight *(Example)* |
|---|---|---|---|
| Maintenance | Scorecard Maintained check; release and commit activity | Score 5 or more; release within 12 months | 20 |
| Code review and branch protection | Scorecard Code-Review and Branch-Protection checks | Score 5 or more | 15 |
| Release integrity | Signed releases or build provenance; Scorecard Signed-Releases | Present, or compensating hash pinning | 15 |
| Known vulnerabilities | SCA scan of the candidate version; Scorecard Vulnerabilities check | No open High or Critical | 20 |
| Security policy and disclosure | Security policy file (Scorecard Security-Policy check); OSPS Baseline Level 1 security contacts in project documentation (OSPS-VM-02.01), and preferably the Level 2 private vulnerability reporting route (OSPS-VM-03.01) and CVD policy with a response timeframe (OSPS-VM-01.01) | Security contacts present; private reporting route for full credit | 10 |
| Footprint | Number of new transitive packages; install scripts | Under 20 new packages; no install scripts, or reviewed | 10 |
| Licence | SPDX identifier in allowed list | Allowed | 10 |

Decision rule: a candidate passes with a weighted score of at least 70 and no failed Known vulnerabilities or Licence criterion. A criterion that meets its threshold earns its full weight and one that fails earns 0; a reviewer may award partial credit on a criterion with a written reason in the intake log. Scorecard scores run from 0 to 10 per check, and a check can return -1 when the result is inconclusive: treat -1 as a fail until the reviewer has checked the signal manually. Record the Scorecard version used, because checks and probes change between releases.

### 5.3 Intake log

| ID | Package and version | Repository | Tier | Score | Decision | Reviewer | Date |
|---|---|---|---|---|---|---|---|
| DEP-INT-014 *(Example)* | `example-csv-stream` 3.4.1 | corvid-checkout-api | 1 | 85 | Approved | [@appsec-reviewer] | 2026-09-30 |
| DEP-INT-015 *(Example)* | `example-color-utils` 0.2.0 | corvid-storefront | 1 | 45 | Rejected: single maintainer, no release in 26 months, install script; use existing CSS utility | [@appsec-reviewer] | 2026-10-06 |
| [DEP-INT-NNN] | [Package version] | [Repo] | [Tier] | [Score] | [Decision] | [@name] | YYYY-MM-DD |

Worked score for DEP-INT-014 *(Example)*: Maintenance 20, Code review 15, Release integrity 15, Known vulnerabilities 20, Security policy 10, Footprint 0 (24 new packages, over the threshold), Licence 10. Total 20 + 15 + 15 + 20 + 10 + 0 + 10 = 90. The reviewer reduced Release integrity to 10 because only some releases carried provenance, giving 85, and approved it with a note to track the footprint.

## 6. Sourcing, pinning and integrity

<!-- Guidance: Make sure the bits you build with are the bits you reviewed. Questions: can a build runner reach public registries directly? Could an internal package name be claimed on a public registry? Pitfall: pinning application libraries but leaving CI actions on moving tags. -->

### 6.1 Approved sources

| Ecosystem | Approved source | Notes |
|---|---|---|
| npm *(Example)* | Internal registry proxy at [registry URL] mirroring the public npm registry | Internal scope `@corvid` resolves only from the internal registry |
| Maven *(Example)* | Internal proxy of Maven Central | Group IDs `com.corvid.*` blocked from upstream |
| PyPI *(Example)* | Internal proxy of PyPI | `--index-url` set to proxy; no `--extra-index-url` |
| Container images *(Example)* | Internal mirror of approved base images, rebuilt weekly | Only images from the golden base list |
| CI actions *(Example)* | Allow list of organisations and actions in the CI settings | Third-party actions reviewed like Tier 1 dependencies |
| [Ecosystem] | [Source] | [Notes] |

Build runners MUST NOT reach public registries directly except through the proxy. Internal package names MUST be reserved or scoped so that a public package with the same name cannot be substituted (dependency confusion).

### 6.2 Pinning and lock files

- Commit the lock file for every application and service. Libraries that are published SHOULD also commit a lock file for their own CI, while declaring compatible ranges for consumers.
- Install with the frozen or immutable lock option so CI fails when the lock file and manifest disagree.
- Pin CI actions and reusable workflows to a full commit SHA, with the version in a trailing comment for readability, and let the update bot propose SHA updates.
- Pin container base images by digest in Dockerfiles and deployment manifests.
- Lock files record integrity hashes; review hash changes in pull requests that do not change versions, because they can indicate a re-published artefact.

### 6.3 Verification

| Control | Where | Tier |
|---|---|---|
| Integrity hash check on install | Package manager, enforced by frozen install | All |
| Signature or provenance verification where the ecosystem supports it | Install or admission step | Tier 1 |
| Install scripts disabled by default, enabled per package after review | Package manager configuration | Tier 1 and 2 |
| Base image signature verified at deploy admission | Cluster admission policy | Tier 1 |
| Typosquat and malicious package check on new dependencies | Dependency review check | All |

## 7. Updates and cooldown

<!-- Guidance: Keep dependencies current in small steps. Questions: how far behind is acceptable? Who merges update pull requests? Pitfall: update bots that open 80 pull requests a week that nobody merges, which trains teams to ignore them. -->

### 7.1 Currency targets

| Measure | Strict (Tier 1) *(Example)* | Standard (Tier 2) *(Example)* |
|---|---|---|
| Patch and minor updates of direct dependencies merged | Within 30 days of availability (after cooldown) | Within 60 days |
| Major versions behind latest | At most 1 major behind; plan to adopt within 6 months of release | At most 2 majors behind |
| Runtime (language, OS) | Never on an upstream end-of-life version | Upgrade plan within 3 months of upstream EOL |
| Base images | Rebuilt at least weekly from the patched golden image | Rebuilt at least monthly |

### 7.2 Cooldown (minimum release age)

A newly published version is not adopted for normal updates until it has been public for the cooldown period. Compromised releases and accidental breakages are often found and withdrawn within days, so a short delay removes much of that risk at low cost.

| Update kind | Cooldown *(Example)* |
|---|---|
| Patch and minor, Tier 1 | 7 days |
| Major, all tiers | 14 days |
| Patch and minor, Tier 2 and 3 | 3 days |
| Security update fixing a vulnerability that affects us | No cooldown; follow section 8 |

Configure the cooldown in the update tooling, for example the `cooldown` option of Dependabot, the `minimumReleaseAge` option of Renovate or the `minimumReleaseAge` setting of pnpm; check each tool's documentation for units and defaults, which differ. Dependabot's cooldown applies to version updates only and never delays its security updates; pnpm's `minimumReleaseAge` is expressed in minutes, so 7 days is 10080.

### 7.3 Update process

```mermaid
flowchart LR
  A["New version published"] --> B{"Cooldown elapsed or security fix?"}
  B -- "No" --> A
  B -- "Yes" --> C["Update bot opens grouped pull request"]
  C --> D["CI: build, tests, SCA, licence, diff of lock file"]
  D --> E{"Checks pass?"}
  E -- "No" --> F["Owning team investigates or pins with reason"]
  E -- "Yes" --> G{"Major version?"}
  G -- "No" --> H["Auto-merge allowed for Tier 2 and 3; review for Tier 1"]
  G -- "Yes" --> I["Planned upgrade with release notes review"]
```

- Group related updates (for example all patch updates of test tooling) to limit pull request volume. Keep runtime-critical packages in their own pull requests.
- Auto-merge is allowed only when the test suite meets the coverage floor of the repository and the update is patch or minor.
- Major upgrades are planned work with an owner and target date in the backlog; read the upstream changelog and migration guide.
- A version held back on purpose is pinned with a comment linking to the issue that explains why and when it will be lifted.

## 8. Vulnerable and malicious dependencies

<!-- Guidance: Connect dependency alerts to the organisation's remediation process. Questions: who sees a new alert first? How do you decide that a vulnerable function is not reachable? Pitfall: closing alerts as "not exploitable" without a recorded justification that a customer or auditor can read. -->

### 8.1 Detection

- Software composition analysis (SCA) runs on every pull request, nightly on default branches, and continuously against the SBOMs of released versions, so new advisories on old releases are found.
- Advisory sources: the ecosystem advisory databases, the OSV database, vendor advisories, and the CISA KEV catalog for evidence of exploitation.

### 8.2 Prioritisation and remediation

Remediation SLAs, severity rules and exploitation signals are owned by the Vulnerability Management Policy (`security/vulnerability-management-policy`). For dependencies this policy adds:

1. A vulnerability listed in the CISA KEV catalog, or with confirmed exploitation, takes the shortest SLA regardless of base score.
2. When a fixed version exists, update to it; the cooldown does not apply.
3. When no fixed version exists, apply a documented mitigation (configuration, input validation, removing the vulnerable feature) or replace the dependency.
4. When the vulnerable code is not present or not reachable in our product, record a VEX status of `not_affected` with a justification, as set by the SBOM and VEX Policy (`security/sbom-vex-policy`).
5. Released product versions affected by a dependency vulnerability are fixed according to the Versioning and Release Policy (`dev/versioning-release-policy`) backport rules.

| ID | Package | Advisory | Affected repos | Reachable | Action | Due | Status |
|---|---|---|---|---|---|---|---|
| DEP-VUL-031 *(Example)* | `example-xml-lite` 2.1.0 | GHSA-xxxx-xxxx-xxxx (fictional) | corvid-checkout-api | Yes, parses partner XML | Update to 2.1.4 | 2026-10-31 | In progress |
| DEP-VUL-032 *(Example)* | `example-img-tools` 5.0.2 | CVE-YYYY-NNNNN (fictional) | corvid-storefront | No, only the unused TIFF decoder is affected | VEX `not_affected`, `vulnerable_code_not_in_execute_path`; update in next cycle | 2026-11-30 | VEX published |
| [DEP-VUL-NNN] | [Package] | [Advisory] | [Repos] | [Yes/No and why] | [Action] | YYYY-MM-DD | [Status] |

### 8.3 Malicious packages

A dependency that contains malicious code (credential stealer, backdoor, protestware) is a security incident, not a vulnerability ticket:

1. Block the package and version at the registry proxy immediately.
2. Identify every build and environment that installed it, from lock files, build logs and SBOMs.
3. Assume secrets available to those builds are exposed: rotate CI tokens, registry tokens, cloud credentials and signing keys in scope.
4. Rebuild affected artefacts from a clean state and check released artefacts for contamination.
5. Run the incident under the Incident Response Plan (`compliance/incident-response-plan`) and record lessons learned.

## 9. Licence compliance

<!-- Guidance: Keep licence decisions consistent and fast. Questions: do you distribute software (mobile, on-premises, SDK) or only run it as a service? This changes copyleft obligations. Pitfall: approving by the licence field in the package manifest while files inside carry a different licence. -->

| Category | SPDX identifiers *(Example; confirm with counsel)* | Rule |
|---|---|---|
| Allowed | MIT, BSD-2-Clause, BSD-3-Clause, Apache-2.0, ISC, Zlib, 0BSD, Unlicense, CC0-1.0 | Use freely; keep notices |
| Allowed with conditions | MPL-2.0, EPL-2.0, LGPL-2.1-or-later, LGPL-3.0-or-later | Allowed if unmodified and dynamically linked or kept as a separate file; record obligations |
| Review required | GPL-2.0-only, GPL-3.0-or-later, AGPL-3.0-or-later, SSPL-1.0, BUSL-1.1, CC-BY-SA-4.0 for code, any non-SPDX or custom licence | Open source counsel approval per use case |
| Denied | No licence, licences forbidding commercial use, licences with field-of-use restrictions incompatible with our products | Not used |

- The licence scanner reads both the declared licence and file-level licence texts and reports mismatches.
- Products that are distributed (SDKs, agents, mobile apps) MUST ship a third-party notices file generated from the SBOM.
- Commercial dependencies are reviewed with the Software Licence and Contract Technical Review (`compliance/software-licence-review`).

## 10. Forks, vendoring and patches

<!-- Guidance: Keep modified third-party code visible. Questions: why was it forked? Who tracks upstream fixes? Pitfall: a silent fork that misses three years of upstream security fixes. -->

- Prefer contributing a fix upstream and pinning to the fixed release over forking.
- When we find a vulnerability in a third-party component, report it to the maintainer through their published route. For products in scope of the EU Cyber Resilience Act, Article 13(6) makes this a duty, requires the manufacturer to remediate the vulnerability in its own product under Annex I, Part II, and, where it has developed a fix, to share the code or documentation with the maintainer, in machine-readable form where appropriate (check the consolidated text; this is a documentation format, not legal advice).
- A temporary patch (for example through the package manager's patch mechanism) MUST link to the upstream issue or pull request and be reviewed every update cycle.
- A fork or vendored copy MUST be registered below, keep the original licence and notices, and stay visible to SCA scanners (vendored directories are included in SBOMs).

| ID | Component | Type | Reason | Upstream link | Owner | Review date |
|---|---|---|---|---|---|---|
| DEP-FRK-003 *(Example)* | `example-pdf-render` | Patch | Upstream fix for memory leak not yet released | [Upstream PR link] | [@team-checkout] | 2026-11-15 |
| DEP-FRK-004 *(Example)* | `example-legacy-soap` | Fork | Upstream archived; needed for one partner integration until 2027-06 | [Archived repo link] | [@team-partners] | 2027-01-15 |
| [DEP-FRK-NNN] | [Component] | [Patch / Fork / Vendored] | [Reason] | [Link] | [@owner] | YYYY-MM-DD |

## 11. Removal and end of life

<!-- Guidance: Remove what is no longer needed and plan for what upstream abandons. Questions: how do you detect unused or abandoned dependencies? Pitfall: leaving an archived dependency in place until a vulnerability forces an emergency rewrite. -->

- Unused dependency reports run monthly; unused direct dependencies are removed within one release cycle.
- A dependency is considered abandoned when the repository is archived, the maintainers say so, or there has been no release or maintainer response for [18] months while issues accumulate. Abandoned Tier 1 dependencies need a replacement plan with an owner and date within [90] days.
- Runtimes and frameworks follow their upstream lifecycle; the upgrade is planned before upstream end of life, as set in section 7.1.
- When removing a dependency, also remove its configuration, licence notice entries and any exceptions that referenced it.

## 12. Exceptions and risk acceptance

<!-- Guidance: Allow justified deviations with an end date. Questions: what compensates for the risk? Who approves at this tier? Pitfall: exceptions without expiry that silently become permanent. -->

An exception names the policy statement (section 3), repository, dependency and version, the reason, compensating controls, approver (per tier in section 4.2) and an expiry no later than [6] months. Exceptions that accept a known vulnerability are also recorded in the Risk Register (`compliance/risk-register`).

| ID | Statement | Repository and dependency | Reason | Compensating controls | Approver | Expires |
|---|---|---|---|---|---|---|
| EXC-DEP-007 *(Example)* | DEP-06 | corvid-checkout-api, framework 5.x (one major behind) | Major upgrade needs a database driver change scheduled for Q1 | Security patches applied on 5.x; WAF rule for the relevant endpoint class | AppSec lead | 2027-03-31 |
| EXC-DEP-008 *(Example)* | DEP-04 | corvid-mobile build, vendor action pinned by tag | Vendor publishes only signed tags; SHA pinning breaks their update channel | Signature verified in workflow; action allow-listed by version | AppSec lead | 2027-01-31 |
| [EXC-DEP-NNN] | [DEP-NN] | [Repo, dependency] | [Reason] | [Controls] | [@name] | YYYY-MM-DD |

## 13. Compliance measurement

<!-- Guidance: Measure dependency health, not just scanner output. Questions: which numbers will you review every month, and who acts on them? Pitfall: a vanity count of "vulnerabilities found" that rises with every new scanner. -->

| ID | Metric | Formula | Target *(Example)* |
|---|---|---|---|
| DEP-M01 | Repositories with committed lock file and frozen install | compliant repos / repos in scope x 100 | 100% |
| DEP-M02 | CI actions pinned by SHA | pinned action references / all action references x 100 | 100% for Tier 1 |
| DEP-M03 | Currency of direct dependencies | direct deps within section 7.1 target / direct deps x 100 | 90% or more |
| DEP-M04 | Mean update lag | mean days between release (after cooldown) and merge, for merged updates in the period | 30 days or fewer (Tier 1) |
| DEP-M05 | Overdue vulnerable dependencies | dependency vulnerabilities past SLA, count | 0 for KEV-listed |
| DEP-M06 | Intake reviews completed | new direct deps with an intake record / new direct deps x 100 | 100% |
| DEP-M07 | Licence violations at release | releases blocked or shipped with a denied licence, count | 0 shipped |
| DEP-M08 | Open exceptions past expiry | count | 0 |

Worked example *(Example)*: corvid-storefront has 61 direct dependencies; 55 are within target, so DEP-M03 = 55 / 61 x 100 = 90.2%, just above target. The six behind are tracked in the backlog with owners.

Results are reported monthly on the dependency dashboard and quarterly to the engineering leadership review. Repositories can also run the OpenSSF Scorecard against themselves. DEP-04, and in part DEP-03 (frozen installs in scripts and workflows), map to its Pinned-Dependencies check, which inspects Dockerfiles, shell scripts and GitHub workflows; DEP-05 and DEP-06 map to its Dependency-Update-Tool check. DEP-02 has no Scorecard equivalent and is checked through runner egress rules and registry configuration.

## 14. Review cycle

<!-- Guidance: Keep the policy current as ecosystems and attacks change. Pitfall: approved-source lists and licence categories that no longer match reality. -->

- Scheduled review every 12 months by the policy owner with AppSec and open source counsel.
- Early review after: a malicious-package incident affecting the organisation or a major ecosystem; a new ecosystem adopted; a new major release of SSDF, Scorecard or OSPS Baseline; a regulatory change affecting component due diligence (for example the EU Cyber Resilience Act duty to exercise due diligence on integrated third-party components, Article 13(5), applying from 11 December 2027; check the consolidated text).
- Review outcomes are recorded in the revision history.

## 15. Glossary and references

<!-- Guidance: Define terms with a specific meaning here and list sources and related documents. -->

### 15.1 Glossary

| Term | Meaning |
|---|---|
| Direct dependency | A component declared in the project's own manifest |
| Transitive dependency | A component pulled in by another dependency |
| Lock file | A file recording the exact resolved version and integrity hash of every dependency |
| Cooldown (minimum release age) | Time a new version must be public before it is adopted by routine updates |
| Dependency confusion | Substituting a public package for an internal one with the same name |
| Typosquatting | Publishing a malicious package with a name similar to a popular one |
| SCA | Software composition analysis: identifying components and their known vulnerabilities and licences |
| VEX | Vulnerability Exploitability eXchange: a statement of whether a product is affected by a vulnerability |
| KEV | CISA Known Exploited Vulnerabilities catalog |

### 15.2 References

| Reference | Use |
|---|---|
| NIST SP 800-218, *Secure Software Development Framework (SSDF) Version 1.1*, February 2022 (csrc.nist.gov/pubs/sp/800/218/final); SP 800-218 Rev. 1 (SSDF v1.2) is an initial public draft of December 2025 | Practice PW.4, tasks PW.4.1, PW.4.2 and PW.4.4 (sections 1, 5, 6, 7) |
| OpenSSF Scorecard, release v5.6.0 (October 2026), github.com/ossf/scorecard | Intake signals (5.2), metrics (13) |
| OpenSSF Open Source Project Security Baseline, release v2026.08.28 (baseline.openssf.org): controls OSPS-VM-01.01, OSPS-VM-02.01 and OSPS-VM-03.01 | Upstream project expectations (5.2) |
| CISA Known Exploited Vulnerabilities catalog (cisa.gov/known-exploited-vulnerabilities-catalog) | Exploitation signal (8.2) |
| Regulation (EU) 2024/2847 (Cyber Resilience Act), Articles 13(5) and 13(6) | Due diligence on third-party components and reporting their vulnerabilities (10, 14) |
| Dependabot options reference (docs.github.com), Renovate configuration options (docs.renovatebot.com), pnpm settings (pnpm.io), checked October 2026 | Cooldown configuration (7.2) |
| Vulnerability Management Policy (`security/vulnerability-management-policy`) | Remediation SLAs |
| SBOM and VEX Policy (`security/sbom-vex-policy`) | SBOM and VEX rules |
| Software Supply Chain Security (`security/supply-chain-security`) | Periodic assessment, SLSA |
| OSS Project Security Baseline (`security/oss-project-security-baseline`) | Self-assessment for projects we maintain |
| Versioning and Release Policy (`dev/versioning-release-policy`) | Backports to supported releases |
| CI/CD Pipeline Design (`dev/ci-cd-pipeline-design`) | Runner isolation, pinning in pipelines |
| Software Licence and Contract Technical Review (`compliance/software-licence-review`) | Commercial and complex licences |
| Incident Response Plan (`compliance/incident-response-plan`) | Malicious package incidents |

## Standard and licence note

Based on NIST SP 800-218 (SSDF version 1.1, February 2022), a work of the United States Government not subject to copyright in the United States, and on Regulation (EU) 2024/2847, Articles 13(5) and 13(6), paraphrased from the Official Journal text; the CRA parts are a documentation format, not legal advice. OpenSSF Scorecard (Apache-2.0) check names and the OSPS Baseline (OpenSSF, release v2026.08.28) level, category names and control IDs are cited by name only; no check or control text is reproduced. The CISA KEV catalog is a public US Government resource. Dependabot, Renovate and pnpm are named as configuration examples; GitHub and Dependabot are trademarks of GitHub, Inc., Renovate is a trademark of its owner, and this template is not affiliated with or endorsed by them. Licence identifiers follow the SPDX License List. Check the current official versions of SSDF, Scorecard, OSPS Baseline and the tool documentation before adopting this policy. Original text written for this collection. Template licence: MIT.
