1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
name: Dependency review
# On every PR: diff the dependency manifests/lockfiles and BLOCK the PR if it
# introduces a dependency with a known vulnerability or a disallowed license.
# Complements Dependabot (which fixes vulns) by gating them at PR time.
#
# ── RUNNER / COST ─────────────────────────────────────────────────────────────
# `dependency-review-action` calls the GitHub Dependency Graph API, which
# requires the dependency graph feature. That feature is:
# * always on + FREE for PUBLIC repos (the OSS steady state),
# * available on private repos only with GitHub Advanced Security.
# So on this repo the workflow becomes fully effective once PUBLIC. It runs on
# `ubuntu-latest` (the action ships there); it's a tiny job.
on:
pull_request:
branches:
permissions:
contents: read
pull-requests: write # so the action can post its summary comment
jobs:
dependency-review:
name: Dependency review
# The Dependency Graph API this action calls needs GitHub Advanced Security
# on a PRIVATE repo (it errors "Dependency review is not supported on this
# repository" otherwise). Skip while private so it neither fails every PR
# nor burns Actions minutes; it auto-activates at the public flip, where the
# dependency graph is always-on + free. Mirrors the gate in scorecard.yml.
if: ${{ github.event.repository.private == false }}
runs-on: ubuntu-latest # GitHub-hosted; free once public
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Dependency review
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5
with:
# Block on high+ severity vulns; summarise everything on the PR.
fail-on-severity: high
comment-summary-in-pr: on-failure
# Keep license policy aligned with deny.toml (AGPL-compatible set).
# Strong copyleft that this AGPL project can't absorb from a *dependency*
# is denied so a surprise GPL/SSPL dep can't slip in. (AGPL itself is
# NOT denied — it's this project's own license.)
deny-licenses: >-
GPL-2.0-only, GPL-3.0-only, LGPL-3.0-only, SSPL-1.0
# Per-package license exemptions. Each is something the action
# mis-flags; cargo-deny (the REQUIRED gate, deny.toml) resolves the
# crates correctly — these unblock the advisory-only dependency-review
# action to match.
#
# NOTE ON VERSIONS: the `@x.y.z` suffixes below are DECORATIVE. The
# action's matcher (`purlsMatch`, src/purl.ts) compares only the purl
# type and namespace/name — its own comment reads "ignoring version" —
# so these exempt the package at every version, not just the one named.
# They are kept as documentation of the version the finding was
# verified against. Do NOT add a version expecting it to pin anything;
# equally, do not rely on a version to *narrow* an exemption.
# * r-efi 6.0.0 — UEFI-target-only crate pulled by the rustls TLS stack
# (getrandom → r-efi); NEVER compiles on this project's Linux/Fly
# targets. Its SPDX `MIT OR Apache-2.0 OR LGPL-2.1-or-later` is an OR
# with a permissive branch we take, but the action naively matches the
# LGPL term against deny-licenses and blocks.
# * webpki-root-certs 1.0.8 — Mozilla root store, license CDLA-Permissive-2.0
# (a permissive DATA license the action can't map → reads as unknown).
# * zmij 1.0.23 — dtolnay's Schubfach double→string formatter, a genuine
# transitive dep of serde_json ≥1.0.145. Real license is MIT (verified
# on crates.io: published by dtolnay, repo github.com/dtolnay/zmij);
# the action reads it as null/unknown, so exempt it.
# * Swatinem/rust-cache — LGPL-3.0, and the ONLY non-permissive action
# in the pinned fleet (every other one is MIT or Apache-2.0). It is a
# CI-only GitHub Action: it executes on the runner, is never copied
# into this repo, never linked into the AGPL binary, and never
# distributed with the crate or the container image. LGPLv3
# obligations trigger on *conveying* a covered or combined work
# (LGPLv3 §4 → GPLv3 §§4-6); `uses:` is an invocation, and running a
# program is unrestricted. So there is no combined work and no
# conveyance — nothing for the copyleft to attach to. (Even where
# they genuinely combine, LGPL-3.0 is AGPL-3.0-compatible.)
# Deliberately VERSIONLESS: Dependabot changes the pinned SHA on
# every bump, and a versioned purl would read as if it re-blocked
# each time. `LGPL-3.0-only` stays in deny-licenses above — it is
# the right rule for a *linked crate*, and dropping it would put
# this file out of sync with deny.toml, which does not admit LGPL.
allow-dependencies-licenses: >-
pkg:cargo/r-efi@6.0.0,
pkg:cargo/webpki-root-certs@1.0.8,
pkg:cargo/zmij@1.0.23,
pkg:githubactions/Swatinem/rust-cache