Skip to content

11.2.0 Release - #305

Open
liquidsec wants to merge 38 commits into
stablefrom
dev
Open

liquidsec wants to merge 38 commits into
stablefrom
dev

Conversation

@liquidsec

@liquidsec liquidsec commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

11.2.0 Release

Merges dev into stable to cut v11.2.0.

Lookup attribution (#304)

lookup() now returns only the providers whose own entries contain the target (#294). Entries go into a Normal-mode radix tree broadest-first, and each one inherits the resolved provider list of its nearest container; entries that add nothing are skipped. Resolution happens at build time, so lookup() is a single tree get() plus a map lookup.

query before after
18.195.165.195 Amazon, Cloudfront, Quiccloud Amazon
52.67.31.86 Amazon, Cloudfront, Gocache Amazon
foo.s3.amazonaws.com Amazon, GitHub, HPE, Microsoft Amazon
hpefonts.s3.amazonaws.com Amazon, HPE

This changes attribution results, which is the main reason for the minor bump.

Python 3.15 (#310)

pyo3 and pyo3-async-runtimes 0.27 -> 0.29, so the extension builds against Python 3.15.

Dependabot (#307)

Dependabot now opens weekly grouped PRs for minor/patch updates and for majors, per ecosystem, all targeting dev. Cargo is added as an ecosystem for the first time, along with the shared auto-merge workflow for minor and patch updates.

Dependency updates

Version

11.1.0 -> 11.2.0 in Cargo.toml, Cargo.lock, pyproject.toml and uv.lock.

dependabot Bot and others added 30 commits June 28, 2026 00:12
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.18 to 0.15.20.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](astral-sh/ruff@0.15.18...0.15.20)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.15.20
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…uff-0.15.20

build(deps-dev): bump ruff from 0.15.18 to 0.15.20
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.20 to 0.16.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](astral-sh/ruff@0.15.20...0.16.2)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.16.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [maturin](https://github.com/pyo3/maturin) from 1.14.1 to 1.15.0.
- [Release notes](https://github.com/pyo3/maturin/releases)
- [Changelog](https://github.com/PyO3/maturin/blob/main/Changelog.md)
- [Commits](PyO3/maturin@v1.14.1...v1.15.0)

---
updated-dependencies:
- dependency-name: maturin
  dependency-version: 1.15.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps blasthttp from 0.9.0 to 0.10.0.

---
updated-dependencies:
- dependency-name: blasthttp
  dependency-version: 0.10.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.13.4 to 2.13.5.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/v2.13.5/HISTORY.md)
- [Commits](pydantic/pydantic@v2.13.4...v2.13.5)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-version: 2.13.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.16.2 to 0.16.8.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](astral-sh/ruff@0.16.2...0.16.8)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.16.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the github-actions group with 1 update in the / directory: [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain).


Updates `actions-rust-lang/setup-rust-toolchain` from 1 to 2
- [Release notes](https://github.com/actions-rust-lang/setup-rust-toolchain/releases)
- [Changelog](https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md)
- [Commits](actions-rust-lang/setup-rust-toolchain@v1...v2)

---
updated-dependencies:
- dependency-name: actions-rust-lang/setup-rust-toolchain
  dependency-version: '2'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
ubuntu-latest is a label GitHub moves. The image changes under us and
a green pipeline turns red on a morning nobody touched the code.
Pinning to ubuntu-24.04 means the runner moves when we move it.

dtolnay/rust-toolchain was called at @stable, a branch, not a release.
It is pinned to a commit, dated in the trailing comment because that
repo publishes no release tag for it. Version-tagged actions are
untouched.
…lasthttp-0.10.0

build(deps-dev): bump blasthttp from 0.9.0 to 0.10.0
…uff-0.16.8

build(deps-dev): bump ruff from 0.16.2 to 0.16.8
…aturin-1.15.0

build(deps-dev): bump maturin from 1.14.1 to 1.15.0
lookup() returned every provider nested anywhere inside the matching
entry, not just those whose own entry contains the target. HPE declares
one bucket, hpefonts.s3.amazonaws.com, and that made every
*.amazonaws.com host come back tagged HPE; one QUIC.cloud /32 did the
same to 8.4M addresses around it. Downstream in bbot a stray cdn tag
makes portfilter drop every non-web port, so this showed up as missing
findings rather than wrong ones.

The tree was built in ScopeMode::Acl, which deliberately collapses a
nested entry into whatever already covers it. That is correct for an
access list and fatal for attribution: the provider was filed under the
container's key, so by lookup time nothing could tell HPE's bucket from
Amazon's whole namespace. The two-pass loop was an earlier fix for ACL
mode destroying GitHub's blob.core.windows.net when Azure's windows.net
was inserted; it preserved the child but widened the key to windows.net.

Build in ScopeMode::Normal instead, so every entry keeps its own node,
and resolve each entry's provider set once at build time by inserting
broadest first and inheriting from the nearest container already in the
tree. Entries that add no provider their container lacks are skipped:
anything under them resolves to that container for the same answer, which
keeps a provider's own nested subnets from inflating the tree. lookup()
is unchanged, still one get() plus a map hit.

Legitimate nesting survives. A tenant's own host returns the tenant and
the infrastructure owner both, so hpefonts.s3.amazonaws.com is still
Amazon + HPE and GitHub's Azure ranges are still Microsoft + GitHub.
Only hosts the tenant never claimed stop matching.

Against the live signature file, keys covering more than one provider
fall from 133.2M addresses to 35.0M, and the remainder is real shared
attribution. Build cost goes from 205ms to 312ms once per 24h refresh;
the map holds Arc handles so the extra keys cost pointers, not strings.

test_lookup_windows_blob_domain asserted the old behaviour, that
asdf.blob.core.windows.net returns GitHub. GitHub lists specific hosts
under blob.core.windows.net and not that one, so it now asserts the
opposite, alongside regression tests for the amazonaws.com and AWS-IP
leaks and a case covering real tenancy.

Fixes #294

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
build_data_structures inserted every CIDR and domain into an ACL-mode
radix tree, which keeps only the outermost entry. A nested entry was
filed under its container's key, so a lookup anywhere in the container
returned the nested provider too. One QUIC.cloud /32 tagged all of
18.128.0.0/9 as a CDN, and HPE's one S3 bucket claimed every
*.amazonaws.com host.

The tree now runs in Normal mode, so every entry keeps its own node and
its own providers. resolve() walks from the most specific match up
through each containing entry and returns the union. A target gets the
providers whose own entry contains it: ancestors, never siblings or
descendants. The second insert pass existed only to converge the ACL
merge and is gone.

test_lookup_windows_blob_domain asserted that an arbitrary
*.blob.core.windows.net host is GitHub. GitHub lists only specific blob
hosts, so the test now checks a host GitHub lists (GitHub and Microsoft)
and an unlisted one (Microsoft only).

New unit tests build from a synthetic signature file. Before the fix:
10.9.9.9, 10.1.2.4 and www.bigcloud.example returned
["BigCloud", "TinyCdn"] where ["BigCloud"] was expected.

Against the live signature file after the fix:
18.195.165.195 -> Amazon (was Amazon, Cloudfront, Quiccloud)
foo.s3.amazonaws.com -> Amazon (was Amazon, GitHub, HPE, Microsoft)
18.192.146.200 -> Amazon, Quiccloud (its own /32 still attributes)

Fixes #294
…ydantic-2.13.5

build(deps-dev): bump pydantic from 2.13.4 to 2.13.5
…ctions/github-actions-b24befd130

build(deps): bump actions-rust-lang/setup-rust-toolchain from 1 to 2 in the github-actions group across 1 directory
Cargo.toml, pyproject.toml, both lockfiles, and the Docker image tags.
Merging to stable publishes to PyPI and tags the release from the
Cargo.toml version, so the bump has to land before the release merge.
master was never updated to the v3 signature format — it only ever had
cloud_providers.json — so the link 404s today. stable is the default
branch and carries the file the daily job writes.
Takes liquidsec's build-time resolution per review: each entry stores
the providers that contain it, so lookup is one get plus a map hit.
resolve(), parent_of() and ipnet are gone.

Keeps this branch's offline fixture tests, ported to the radix get
path, including the insert-order rebuild test that guards the breadth
sort.
Every push to stable published to crates.io, PyPI, and Docker Hub,
decided whether to tag by comparing a grepped version against `git
describe`, and minted the tag in CI. The daily signature commit to
stable therefore republished, and the Docker tags were hand-edited
literals (v11, v11.2, v11.2.0).

- Cargo.toml is the only declared version. pyproject.toml reads it
  through maturin (`dynamic = ["version"]`).
- New publish.yml, `v*` tags only. Fails unless the tag equals
  Cargo.toml, reruns the rust, python, and docker test workflows,
  then publishes the crate, the wheel matrix with attestation, and
  the Docker image. Docker tags derive from the version. Actions are
  SHA-pinned, windows and macos runners pinned.
- The test workflows only test: callable, read-only, no publish jobs.
- Dropped: the tag-guessing step, CI tag minting, `--skip-existing`
  masking re-publishes, and Docker Hub tag pruning.
- The three test workflows grouped concurrency on github.workflow,
  which under workflow_call is the caller's name, so all three shared
  publish.yml's group. Use fixed per-file prefixes and only cancel
  superseded PR runs.
- crates.io and Docker Hub published as soon as tests passed, so a
  failed wheel build still shipped the crate and image. Both now wait
  on every wheel and the sdist, like PyPI.
publish.yml refuses tags outside vMAJOR.MINOR.PATCH and
vMAJOR.MINOR.PATCH-rc.N before comparing to Cargo.toml. PyPI upload
drops PYPI_TOKEN for trusted publishing, registry jobs run in the
release environment, and a final job creates the GitHub Release with an
SPDX JSON SBOM in the same tag run.

daily-update and pipeline-tests gain a contents: read permissions
block, every remaining tag-ref action is pinned to a commit SHA, and
CLA calls the shared reusable workflow.
Governance declares one gated environment named pypi across published
repos. crates and docker jobs stay in release.
ipnet was added to Cargo.toml but nothing imports it. The attribution
docs restated the mechanism line by line and carried em dashes; keep
only the why (Normal vs Acl mode, broadest-first inheritance).
Four test workflows plus an inline wheel matrix, docker push, crates
upload and release duplicated what the shared workflows in
blacklanternsecurity/CLA now provide. tests.yml calls rust-tests.yml
and python-tests.yml (pipeline tests fold into the python job) and keeps
a docker job for test_docker.py. publish.yml calls release-check.yml,
maturin-wheels.yml, crates.yml, docker.yml and publish.yml, keeping only
the trusted-publishing PyPI upload at top level. Docker tags and image
name come from release-check outputs and the repository name instead of
literals; DOCKER_USERNAME is now a repository secret.

daily-update drops the hardcoded Python 3.12 so uv follows
requires-python. ruff lint rules are declared in pyproject so the dev
dependency range cannot widen them silently, and README examples are
ruff formatted.
Releases are a pushed tag cut with the shared release.sh, which checks
the tag against the manifest. State that here instead of copying the
script.
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.16.8 to 0.16.9.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](astral-sh/ruff@0.16.8...0.16.9)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.16.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the github-actions group with 1 update: [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain).


Updates `actions-rust-lang/setup-rust-toolchain` from 1 to 2
- [Release notes](https://github.com/actions-rust-lang/setup-rust-toolchain/releases)
- [Changelog](https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md)
- [Commits](actions-rust-lang/setup-rust-toolchain@v1...v2)

---
updated-dependencies:
- dependency-name: actions-rust-lang/setup-rust-toolchain
  dependency-version: '2'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
…uff-0.16.9

build(deps-dev): bump ruff from 0.16.8 to 0.16.9
…r and patch (#307)

* ci(dependabot): group updates weekly and auto-merge minor and patch

Individual dependabot PRs pile up faster than one engineer can review
them and go stale until they conflict (bbot-enterprise#141).

Every ecosystem now runs weekly against dev and opens at most two
grouped PRs: one for minor and patch bumps, one for majors. A
pull_request_target workflow enables auto-merge (squash) on the
minor/patch group so it lands once required checks pass. Majors still
need a human.

* ci(dependabot): call the shared auto-merge workflow

The auto-merge job was a byte-identical copy in ten repositories. It now
calls dependabot-auto-merge.yml in blacklanternsecurity/.github, pinned
by SHA, so the fetch-metadata pin and merge policy live in one place.

The trigger moves from pull_request_target to pull_request. Dependabot
branches live in this repository, so the privileged target context was
never needed and zizmor flags it as a dangerous trigger.

* ci(dependabot): call auto-merge from the public CLA repository

blacklanternsecurity/.github is private, so public repositories cannot
call reusable workflows from it and the run failed as a workflow file
issue. The shared workflow lives in blacklanternsecurity/CLA, which is
public and already hosts cla-reusable.yml.

* ci(dependabot): gate auto-merge on finished checks

dev carries no required checks (#139), so gh pr merge --auto would merge
immediately rather than on green. The shared workflow now waits for
every other check on the head commit, refuses on failure or cancel, and
merges with --match-head-commit. The caller grants checks: read so it can
read check state.

* ci(dependabot): pin the shared workflow to the current CLA tip

Aligns with the SHA the other shared CLA workflows are pinned to. The
auto-merge workflow is unchanged between the two commits.
singlerider and others added 7 commits October 6, 2026 08:26
The insert-order test rebuilt the same fixture repeatedly, but the
breadth sort is a total order, so the insert sequence never varied.

Add a three-level CHAIN fixture that fails if an entry inherits its
ancestor's declared providers instead of the ancestor's resolved list.
names() now delegates to names_in(fixture, target).
…ctions/github-actions-b24befd130

build(deps): bump actions-rust-lang/setup-rust-toolchain from 1 to 2 in the github-actions group
fix(lookup): attribute providers to the entries they declare
pyo3 0.27 stops the build on interpreters it doesn't know, and 3.15.0
final ships October 9. The shared python-tests.yml and maturin-wheels.yml
derive their matrix from requires-python = ">=3.10", so 3.15 joins both
the moment it releases: `python / test (3.15)` would fail at `maturin
develop` and take the required `python / passed` check with it, blocking
every PR, and the 3.15 wheel leg would stop publish.yml before PyPI,
crates.io and the release.

pyo3 0.29.0 added 3.15 support (PEP 820 module init, PyModExport/PyABIInfo).
No source changes: python.rs is already on the Bound/Python::attach API.

Capping requires-python was the alternative, but that locks 3.15 users
out of installing.
build(deps): bump pyo3 to 0.29 for Python 3.15
PR #304 fixed provider attribution in src/lib.rs but also replaced the
CI/release pipeline (shared reusable workflows, tag-driven publish,
dynamic version). Restore the previous workflows, pyproject version,
uv.lock, and README so releases keep working under the old system while
the new CLI is developed. The lookup fix itself is untouched.
@liquidsec
liquidsec marked this pull request as ready for review October 19, 2026 16:26
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