Skip to content

ci: add Dependabot version updates (PER-15358) - #957

Open
EliMoshkovich wants to merge 1 commit into
masterfrom
ci/add-dependabot
Open

EliMoshkovich wants to merge 1 commit into
masterfrom
ci/add-dependabot

Conversation

@EliMoshkovich

@EliMoshkovich EliMoshkovich commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Linear: PER-15886 · umbrella PER-15358

This repo had no dependency automation. Adding pip, npm, docker and github-actions version updates.

Pushing this branch printed: GitHub found 49 vulnerabilities on permitio/opal's default branch (28 high, 16 moderate, 5 low). Dependabot alerts are already on and have accumulated 49 unread findings. This PR adds the version updates that actually propose fixes — but that backlog needs an owner regardless.

Why this matters beyond OPAL

OPAL is the upstream that downstream consumers inherit. permitio/pdp-v2 installs opal-client and opal-common, so the floors and caps declared here decide what a PDP image can resolve — and several CVE waivers in the PDP exist purely because a cap here forbids the fixed version.

Context: a customer scanned permitio/pdp-v2:0.9.14 and reported 12 CVEs. Fixing that (permitio/PDP#337) traced three of the residual items straight back to this repo.

Scope limit — stated plainly, because it's easy to assume otherwise

The pip entry does NOT cover OPAL's library dependencies.

Those live in packages/requires.txt and packages/*/requires.txt, and each setup.py loads them at runtime:

def get_install_requires():
    with open(os.path.join(here, "requires.txt")) as fp:
        return [line.strip() for line in fp.read().splitlines() if not line.startswith("#")]

Dependabot's pip parser reads standard manifests (requirements.txt, a literal install_requires, setup.cfg, pyproject.toml) and cannot resolve a dynamic file read. So those files are invisible to it, and bumping OPAL's actual caps stays a manual job.

➡️ Migrating requires.txtpyproject.toml is the highest-value follow-up here and deserves its own PR.

What the entry does cover is still worth having — two pins in the root requirements.txt already carry the comment "pinned by Snyk to avoid a vulnerability", so someone was doing this by hand already.

Real work the other entries will surface

docker/Dockerfile:

  • Builds on python:3.10-bookworm and python:3.10-slim-bookworm. Python 3.10 reaches end of life in October 2026. The PDP already moved off python:3.10 for that reason plus four CPython CVEs that only had 3.13 fixes.
  • Pulls alpine:latest twice — a floating tag with no reproducibility at all.
  • Hand-pins openpolicyagent/opa:1.9.0-static and permitio/cedar-agent:0.2.1.

Workflows — the most immediate payoff. They currently mix:

Action Versions in use
actions/checkout @v2, @v3, @v4, + a bare SHA
actions/setup-python @v2, @v4, @v5
docker/build-push-action @v2, @v6
docker/setup-buildx-action @v1, @v3
docker/setup-qemu-action @v1, @v3

The @v1/@v2 generations are years old and run on Node runtimes GitHub has already deprecated.

Downstream note in the config

The file ends with a comment block recording the three declarations that force PDP waivers, so the next person editing requires.txt can see why they matter to a consumer:

Declaration Effect downstream
starlette>=0.40.0,<1 the <1 cap forbids fixes for CVE-2026-48710 (1.0.1), CVE-2026-48817/48818 (1.1.0), CVE-2026-54283 (1.3.1) — all four waived as unreachable in the PDP, none upgradable while this stands
ddtrace>=3.0.0,<4 forbids 4.8.2, which fixes CVE-2026-50271; the PDP works around it by dropping baggage from DD_TRACE_PROPAGATION_STYLE_EXTRACT
gitpython>=3.1.32,<4 the floor is the problem, not the cap. 3.1.59 fixes CVE-2026-78676 — a CRITICAL (CVSS 9.8) argument-injection RCE via git-config re-serialization into core.hooksPath — and 3.1.58 fixes six more. A floor of 3.1.32 lets any consumer resolve a vulnerable version; pdp-v2:0.9.14 shipped 3.1.57 and had to add its own explicit floor to escape it.

Raising the gitpython floor to >=3.1.59 is a one-line change with real downstream security value — happy to do it in a separate PR if you'd like; I kept this one to config only.

Config details

cooldown is supply-chain defence rather than noise reduction: most malicious-release incidents are caught within a week, which is why GitHub made a 3-day cooldown the platform default in July 2026. Security updates are never delayed by it. Only semver-strict ecosystems support the semver-specific knobs, so pip/npm get semver-major-days while docker/github-actions get default-days only.

Shape mirrors the agent-security, PDP and permit-opa configs so every repo behaves alike. Verified: valid YAML, codespell clean, single trailing newline, no tabs or CRLF (local pre-commit couldn't bootstrap — no python3.12 here — so the relevant hooks were checked by hand).

Related: permitio/PDP#337, permitio/PDP#338, permitio/permit-opa#49, permitio/permit-opa#50.

🤖 Generated with Claude Code

This repo had no dependency automation. It matters beyond OPAL itself, because
OPAL is the upstream that downstream consumers inherit: permitio/pdp-v2 installs
opal-client and opal-common, so the floors and caps declared here decide what a
PDP image can resolve. Several CVE waivers in the PDP exist purely because a cap
here forbids the fixed version.

Ecosystems: pip (/), npm (/documentation), docker (/docker), github-actions (/) -
weekly, Monday. Shape mirrors the agent-security, PDP and permit-opa configs so
every repo behaves alike. cooldown is supply-chain defence rather than noise
reduction (GitHub made a 3-day cooldown the platform default in July 2026);
security updates are never delayed by it. Only semver-strict ecosystems support
the semver-specific knobs, so pip/npm get semver-major-days and
docker/github-actions get default-days only.

A SCOPE LIMIT worth stating plainly, because it is easy to assume otherwise: the
pip entry does NOT cover OPAL's library dependencies. Those live in
packages/requires.txt and packages/*/requires.txt, and each setup.py loads them
at runtime with a plain open() inside get_install_requires(). Dependabot's pip
parser reads standard manifests and cannot resolve a dynamic file read, so those
files are invisible to it. Bumping OPAL's actual caps therefore stays manual
until they become a pyproject.toml - which is the highest-value follow-up here
and deserves its own PR. What the entry does cover is still useful: two pins in
the root requirements.txt already carry the comment "pinned by Snyk to avoid a
vulnerability", so someone was doing this by hand.

Real work the other entries will surface:

  docker/Dockerfile builds on python:3.10-bookworm and python:3.10-slim-bookworm,
  and Python 3.10 reaches END OF LIFE in October 2026. The PDP already moved off
  python:3.10 for that reason plus four CPython CVEs that only had 3.13 fixes. It
  also pulls alpine:latest twice - a floating tag with no reproducibility - and
  hand-pins openpolicyagent/opa:1.9.0-static and permitio/cedar-agent:0.2.1.

  The workflows mix actions/checkout@v2, @V3, @v4 and a bare commit SHA;
  actions/setup-python@v2, @v4, @v5; docker/build-push-action@v2 and @v6;
  docker/setup-buildx-action@v1 and @V3; docker/setup-qemu-action@v1 and @V3. The
  @v1/@v2 generations are years old and run on Node runtimes GitHub has already
  deprecated.

The config ends with a DOWNSTREAM NOTE recording the three caps that force PDP
waivers - starlette<1, ddtrace<4, and gitpython's >=3.1.32 floor - so the next
person to touch requires.txt sees why they matter to a consumer. The gitpython
one is the sharpest: 3.1.59 fixes CVE-2026-78676, a CRITICAL (CVSS 9.8)
argument-injection RCE, and a floor of 3.1.32 lets any consumer resolve a
vulnerable version. pdp-v2:0.9.14 shipped 3.1.57 and had to add its own floor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 11, 2026 15:35
@linear-code

linear-code Bot commented Sep 11, 2026

Copy link
Copy Markdown

PER-15358

PER-15886

@netlify

netlify Bot commented Sep 11, 2026

Copy link
Copy Markdown

Deploy Preview for opal-docs canceled.

Name Link
🔨 Latest commit fe582b1
🔍 Latest deploy log https://app.netlify.com/projects/opal-docs/deploys/6aa41faccce80e0009029bc5

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

EliMoshkovich added a commit to permitio/PDP that referenced this pull request Sep 11, 2026
The Waivers section closed by claiming every waiver exists because opal-common
caps the dependency. That stopped being true when the two x/crypto/ssh waivers
landed - those are blocked by an unreleased Go 1.26, not by OPAL. Replaced with
a table that names the actual blocker and retirement condition for all five.

Added where each class of finding really lives, so the next person does not
re-derive it:

- OPAL owns the dependency caps (packages/requires.txt,
  packages/opal-common/requires.txt): starlette<1, ddtrace<4, and
  gitpython>=3.1.32. The gitpython FLOOR is the sharpest of the three - 3.1.32
  lets any consumer resolve a version carrying the CRITICAL CVE-2026-78676 RCE,
  which is how 0.9.14 shipped 3.1.57 and why this repo needed its own floor.
  Also notes that Dependabot cannot see those files at all: setup.py loads
  requires.txt with a runtime open(), which its pip parser cannot resolve, so
  OPAL's caps stay manual until they become a pyproject.toml.

- permit-opa owns every Go CVE in /app/bin/opa, and had neither a CVE gate nor
  dependency automation - which is why its drift surfaced in OUR scans.

Both now have Dependabot PRs (permitio/opal#957, permitio/permit-opa#50), same
shape as this repo's and agent-security's.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
EliMoshkovich added a commit to permitio/PDP that referenced this pull request Sep 11, 2026
The Waivers section closed by claiming every waiver exists because opal-common
caps the dependency. That stopped being true when the two x/crypto/ssh waivers
landed - those are blocked by an unreleased Go 1.26, not by OPAL. Replaced with
a table that names the actual blocker and retirement condition for all five.

Added where each class of finding really lives, so the next person does not
re-derive it:

- OPAL owns the dependency caps (packages/requires.txt,
  packages/opal-common/requires.txt): starlette<1, ddtrace<4, and
  gitpython>=3.1.32. The gitpython FLOOR is the sharpest of the three - 3.1.32
  lets any consumer resolve a version carrying the CRITICAL CVE-2026-78676 RCE,
  which is how 0.9.14 shipped 3.1.57 and why this repo needed its own floor.
  Also notes that Dependabot cannot see those files at all: setup.py loads
  requires.txt with a runtime open(), which its pip parser cannot resolve, so
  OPAL's caps stay manual until they become a pyproject.toml.

- permit-opa owns every Go CVE in /app/bin/opa, and had neither a CVE gate nor
  dependency automation - which is why its drift surfaced in OUR scans.

Both now have Dependabot PRs (permitio/opal#957, permitio/permit-opa#50), same
shape as this repo's and agent-security's.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
EliMoshkovich added a commit to permitio/PDP that referenced this pull request Sep 11, 2026
The Waivers section closed by claiming every waiver exists because opal-common
caps the dependency. That stopped being true when the two x/crypto/ssh waivers
landed - those are blocked by an unreleased Go 1.26, not by OPAL. Replaced with
a table that names the actual blocker and retirement condition for all five.

Added where each class of finding really lives, so the next person does not
re-derive it:

- OPAL owns the dependency caps (packages/requires.txt,
  packages/opal-common/requires.txt): starlette<1, ddtrace<4, and
  gitpython>=3.1.32. The gitpython FLOOR is the sharpest of the three - 3.1.32
  lets any consumer resolve a version carrying the CRITICAL CVE-2026-78676 RCE,
  which is how 0.9.14 shipped 3.1.57 and why this repo needed its own floor.
  Also notes that Dependabot cannot see those files at all: setup.py loads
  requires.txt with a runtime open(), which its pip parser cannot resolve, so
  OPAL's caps stay manual until they become a pyproject.toml.

- permit-opa owns every Go CVE in /app/bin/opa, and had neither a CVE gate nor
  dependency automation - which is why its drift surfaced in OUR scans.

Both now have Dependabot PRs (permitio/opal#957, permitio/permit-opa#50), same
shape as this repo's and agent-security's.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
EliMoshkovich added a commit to permitio/PDP that referenced this pull request Sep 11, 2026
The Waivers section closed by claiming every waiver exists because opal-common
caps the dependency. That stopped being true when the two x/crypto/ssh waivers
landed - those are blocked by an unreleased Go 1.26, not by OPAL. Replaced with
a table that names the actual blocker and retirement condition for all five.

Added where each class of finding really lives, so the next person does not
re-derive it:

- OPAL owns the dependency caps (packages/requires.txt,
  packages/opal-common/requires.txt): starlette<1, ddtrace<4, and
  gitpython>=3.1.32. The gitpython FLOOR is the sharpest of the three - 3.1.32
  lets any consumer resolve a version carrying the CRITICAL CVE-2026-78676 RCE,
  which is how 0.9.14 shipped 3.1.57 and why this repo needed its own floor.
  Also notes that Dependabot cannot see those files at all: setup.py loads
  requires.txt with a runtime open(), which its pip parser cannot resolve, so
  OPAL's caps stay manual until they become a pyproject.toml.

- permit-opa owns every Go CVE in /app/bin/opa, and had neither a CVE gate nor
  dependency automation - which is why its drift surfaced in OUR scans.

Both now have Dependabot PRs (permitio/opal#957, permitio/permit-opa#50), same
shape as this repo's and agent-security's.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
EliMoshkovich added a commit to permitio/PDP that referenced this pull request Sep 11, 2026
The Waivers section closed by claiming every waiver exists because opal-common
caps the dependency. That stopped being true when the two x/crypto/ssh waivers
landed - those are blocked by an unreleased Go 1.26, not by OPAL. Replaced with
a table that names the actual blocker and retirement condition for all five.

Added where each class of finding really lives, so the next person does not
re-derive it:

- OPAL owns the dependency caps (packages/requires.txt,
  packages/opal-common/requires.txt): starlette<1, ddtrace<4, and
  gitpython>=3.1.32. The gitpython FLOOR is the sharpest of the three - 3.1.32
  lets any consumer resolve a version carrying the CRITICAL CVE-2026-78676 RCE,
  which is how 0.9.14 shipped 3.1.57 and why this repo needed its own floor.
  Also notes that Dependabot cannot see those files at all: setup.py loads
  requires.txt with a runtime open(), which its pip parser cannot resolve, so
  OPAL's caps stay manual until they become a pyproject.toml.

- permit-opa owns every Go CVE in /app/bin/opa, and had neither a CVE gate nor
  dependency automation - which is why its drift surfaced in OUR scans.

Both now have Dependabot PRs (permitio/opal#957, permitio/permit-opa#50), same
shape as this repo's and agent-security's.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants