Skip to content

fix(sandbox): pin the Kali keyring instead of the drifting InRelease hash - #206

Merged
ecryptoguru merged 2 commits into
mainfrom
fix/sandbox-kali-pin-durable
Oct 8, 2026
Merged

ecryptoguru merged 2 commits into
mainfrom
fix/sandbox-kali-pin-durable

Conversation

@ecryptoguru

Copy link
Copy Markdown
Owner

What this fixes

Build and smoke-test sandbox image fails on every engine PR and on main (9c6b9102).

containers/Dockerfile pinned KALI_APT_INRELEASE_SHA256=5bc9a9bf... against the kali-last-snapshot suite. That suite is a rolling pointer: Kali re-signed its InRelease on 2026-10-08 01:58 UTC (now 33,968 B, sha256 c6fc6a6d...), so the sha256sum -c - step fails and will fail again on every future re-sign.

Design chosen: pin the trust anchor, not the drifting bytes

The archive publishes no immutable dated suite — archive.kali.org/kali/dists/ lists nine suites and all are floating; kali-last-snapshot is the only snapshot suite, and it is refreshed in place. The dated-snapshot service snapshot.kali.org returns 502 on repeated attempts, so option (a) is not available.

The durable anchor is the Kali keyring shipped by the digest-pinned base image:

  • Base image kalilinux/kali-rolling@sha256:f4912486... is pinned by manifest-list digest, so its contents — including usr/share/keyrings/kali-archive-keyring.gpg — are immutable.
  • That keyring is sha256 42a247ff5a26869e3739b6d3ad125938bb5da8e7bb43ed0791d2a190cd09c64f and holds key 827C8569F2518CC677FECA1AED65462EC8D5E4C5.
  • The current InRelease verifies against that key (gpg --verify → Good signature from "Kali Linux Archive Automatic Signing Key (2025)"), so the build now proves the keyring is the one Kali signs with, and apt then verifies the index against it.

Enforced fail-closed in /etc/apt/apt.conf.d/99lyrashield-signature-required:

APT::Get::AllowUnauthenticated "false";
Acquire::AllowInsecureRepositories "false";
Acquire::AllowDowngradeToInsecureRepositories "false";

Nothing is weakened: no [trusted=yes], no --allow-unauthenticated, no fallback to an insecure repository. The keyring hash check makes a substituted keyring fail the build; apt's own verification then makes an unsigned or wrong-key index fail the build. Package selection is unchanged — the snapshot suite stays pinned at Pin-Priority: 1001 with --allow-downgrades.

upgrade still installs kali-archive-keyring, so Kali key rotation continues to work without a code change.

Trade-off of the rejected alternative

Option (a), an immutable dated suite pinned by hash, is strictly stronger — it freezes the package set as well as the index. It is unavailable: no such suite is published and the snapshot service is down. Had it existed, it would also have meant the sandbox silently stops receiving tool updates until someone refreshes the pin.

Option (b) as literally specified — verify against the pinned Kali archive keyring — is what shipped, with one correction: gpgv is not present in the base image (only apt's internal gpgv/sqv methods are), so the verification is done by apt itself rather than by a hand-rolled gpgv invocation. That is the stronger placement: the check runs on every apt-get update in the image, not once in a Dockerfile step.

The residual trade-off versus (a): the trust boundary is now Kali's signing key rather than a frozen byte string, so a Kali key compromise would be trusted. The previous hash pin had the same exposure — it verified a signature made by that same key — it just also happened to freeze one day's index bytes.

Changes

  • containers/Dockerfile — replace both ARG KALI_APT_INRELEASE_SHA256 lines with ARG KALI_APT_KEYRING_SHA256=42a247ff...; verify the keyring by content hash; add the fail-closed apt policy file.
  • tests/test_sandbox_dockerfile.py — assert the InRelease pin is gone, both keyring pins match, the three fail-closed settings are present and --allow-unauthenticated / trusted=yes are absent.
  • UPGRADES.md — refresh procedure for the pin.

strix/**, ENGINE_REVISION and .lyrashield-worker-pin are untouched; scripts/verify-controlled-derivative.sh has no Kali reference.

Verification

  • tests/test_sandbox_dockerfile.py: 10/10 pass (executed directly; the module has no pytest dependency).
  • Negative control: reinstating the old KALI_APT_INRELEASE_SHA256 shape makes test_every_external_sandbox_input_is_immutable_or_hash_verified fail — the assertion is load-bearing.
  • ruff check and ruff format --check clean on the edited test file.
  • Live proof the keyring hash and signing key agree: gpg --verify InRelease against that keyring → good signature.
  • Docker build itself is CI-verified (docker-smoke); no Docker daemon in the authoring sandbox.

Draft: the founder and the Deep Review agent decide on merge.

…hash

`kali-last-snapshot` is a rolling pointer that Kali re-signs on every archive
refresh, so the pinned InRelease hash broke `Build and smoke-test sandbox
image` on each re-sign (main 9c6b910). The archive publishes no immutable
dated suite and snapshot.kali.org is not serving, so the index bytes cannot be
pinned durably.

The trust anchor is now the Kali keyring shipped by the digest-pinned base
image, verified by content hash, with apt signature verification enforced
fail-closed through 99lyrashield-signature-required. Package selection still
pins the snapshot suite at Pin-Priority 1001 with --allow-downgrades.

UPGRADES.md documents how to refresh the pin.
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b2bf9818-c721-4426-9087-c7b7746f6276
📥 Commits

Reviewing files that changed from the base of the PR and between 9c6b910 and 3d58f7b.

📒 Files selected for processing (3)
  • UPGRADES.md
  • containers/Dockerfile
  • tests/test_sandbox_dockerfile.py
 _________________________________________________
< Code Wars Episode II: Attack of the Git Clones. >
 -------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The deb line named no keyring, so apt authenticated the Kali index with
whatever trusted key the image happened to carry while the build separately
hashed /usr/share/keyrings/kali-archive-keyring.gpg. Name that exact file
with [signed-by=...] in both stages so the keyring whose sha256 the build
checks is the file apt is told to trust, and keep the fail-closed apt conf.

Verified the later 'apt-get install -y kali-archive-keyring' does not disturb
that file: kali-archive-keyring_2025.2_all.deb unpacks the same keyring at the
same path with an identical sha256 (42a247ff...). A future package that
rotated the key would fail closed at the post-install 'apt-get update'.

tests/test_sandbox_dockerfile.py gains an invariant that every Kali deb line
carries signed-by pointing at the hashed keyring path, proven load-bearing by
two negative controls (option removed, option pointing elsewhere). UPGRADES.md
records signed-by and the keyring-package check.
@ecryptoguru
ecryptoguru marked this pull request as ready for review October 8, 2026 23:22
@ecryptoguru
ecryptoguru merged commit d4f8a40 into main Oct 8, 2026
5 checks passed
@ecryptoguru
ecryptoguru deleted the fix/sandbox-kali-pin-durable branch October 8, 2026 23:22
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.

1 participant