Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Dependabot version updates, grouped per ecosystem so one upstream release does not arrive as three
# pull requests.
#
# The five-day cooldown is a supply-chain control, not a convenience. Most malicious npm and PyPI
# releases in recent memory were detected and yanked within hours, so waiting before adopting a new
# version neutralises that class of attack without anyone needing to be watching at the right moment.
# Security updates are unaffected: Dependabot security PRs are driven by advisories and ignore this.
#
# Layout note: this repository publishes three packages, and each ecosystem's manifest sits where its
# packaging rules force it. composer.json and pyproject.toml are at the root; the npm package is in
# `js/`. See the README.

version: 2

multi-ecosystem-groups:
# Everything that ends up in a published artefact or its lockfile.
packages:
schedule:
interval: weekly
# Kept separate because a workflow bump changes what runs in the release path, which deserves its own
# review rather than being batched with library updates.
github-actions:
schedule:
interval: weekly

updates:
- package-ecosystem: npm
multi-ecosystem-group: packages
directory: /js
patterns:
- '*'
cooldown:
default-days: 5
labels:
- dependencies

- package-ecosystem: composer
multi-ecosystem-group: packages
directory: /
patterns:
- '*'
allow:
- dependency-type: all
cooldown:
default-days: 5
labels:
- dependencies

- package-ecosystem: pip
multi-ecosystem-group: packages
directory: /
patterns:
- '*'
cooldown:
default-days: 5
labels:
- dependencies

# Every action here is pinned to a full commit SHA, and a CI job fails the build if any is not.
# Dependabot understands SHA pins and bumps them with the version comment intact, which is the only
# sustainable way to keep pinned actions current.
- package-ecosystem: github-actions
multi-ecosystem-group: github-actions
directory: /
patterns:
- '*'
cooldown:
default-days: 5
labels:
- dependencies
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,11 @@ ecosystems, so a malicious version would run in our CI and on developer machines
builds install with `--ignore-scripts`.
- CodeQL (JavaScript, Python, Actions), dependency review with a copyleft denylist, and a weekly
OpenSSF Scorecard run.
- The Renovate base sets a five-day `minimumReleaseAge` cooldown. Most malicious releases are detected
and yanked within hours, so a cooldown neutralises that class of attack without anyone needing to be
watching at the right moment.
- A five-day dependency cooldown, applied by `.github/dependabot.yml` across npm, Composer, pip and
GitHub Actions, with updates grouped per ecosystem. Most malicious releases are detected and yanked
within hours, so a cooldown neutralises that class of attack without anyone needing to be watching at
the right moment. Security updates are advisory-driven and unaffected. The Renovate presets express
the same policy for consumers on Renovate.

`SECURITY.md` documents the controls, the verification commands, and the known gaps — including that
Composer has no artefact provenance mechanism, so the PHP package's integrity rests on repository
Expand Down
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,20 @@ repos:

---

## Renovate
## Dependency updates

This repository is also the org-wide Renovate config, extended by name the same way the style presets
are. In a consuming repository's `renovate.json`:
This repository's own updates are handled by **Dependabot** (`.github/dependabot.yml`): grouped per
ecosystem, with a five-day cooldown on every one. The cooldown is a supply-chain control rather than a
convenience — see `SECURITY.md`.

Note that Renovate is **not installed** on the organisation. Dependabot is what actually runs. The
presets below are for consumers that adopt Renovate, and express the same policy.

## Renovate presets (optional)

This repository also ships an org-wide Renovate config, extended by name the same way the style presets
are. Using it requires installing the Renovate GitHub App. In a consuming repository's
`renovate.json`:

```json
{
Expand All @@ -403,9 +413,9 @@ polyglot repository would otherwise get three pull requests for one upstream com

Requires Renovate 38 or newer, which is when `matchPackageNames` gained glob support.

**Do not also enable Dependabot version updates.** Dependabot *security* updates are fine alongside
this and complement it: they only fire on advisories. A `dependabot.yml` with a `schedule` block,
though, means every bump arrives twice.
**Pick one tool per repository.** Dependabot *security* updates compose fine with Renovate, because
they only fire on advisories. Dependabot *version* updates do not: every bump would arrive twice. Our
repositories use Dependabot, so these presets are only relevant if that changes.

---

Expand Down
19 changes: 13 additions & 6 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,19 @@ Enforced through GitHub settings rather than files:

### Consuming a compromised upstream

The Renovate presets set a repository-wide `minimumReleaseAge` cooldown, so a dependency version stays
unadopted for several days after publication. Most malicious npm and PyPI releases in recent memory
were detected and yanked within hours; a cooldown converts that class of attack into a non-event
without needing anyone to be paying attention at the right moment.

Linters and formatters additionally never automerge, at any update type.
`.github/dependabot.yml` sets a **five-day cooldown** on every ecosystem, so a dependency version stays
unadopted for five days after publication. Most malicious npm and PyPI releases in recent memory were
detected and yanked within hours; a cooldown converts that class of attack into a non-event without
needing anyone to be paying attention at the right moment. Security updates are unaffected — those are
advisory-driven and ignore the cooldown.

Updates are grouped per ecosystem so one upstream release does not arrive as three pull requests, and
GitHub Actions are grouped separately: a workflow bump changes what runs in the release path and
deserves its own review.

The Renovate presets this repository also ships (`default.json`, `renovate/*.json`) express the same
policy for consumers who use Renovate. They are **not active here** — Renovate is not installed on the
organisation, Dependabot is.

## Known gaps

Expand Down
Loading