Skip to content

WolfStack v25.9.2

Choose a tag to compare

@github-actions github-actions released this 01 Aug 08:37
· 397 commits to master since this release

v25.9.2: SECURITY — the built-in cluster secret no longer authenticates anyone who is not already a recorded peer

Reported privately by Dostxodjayev Abdullox (@squeeze440) on 2026-08-01,
with a proof of concept against the signed v25.9.0 release binary.
CWE-798 + CWE-306, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8).

The cluster secret compiled into every build is published in this repo's
source. Until now any node that had not rotated to a per-install secret
accepted that constant as valid inter-node authentication from ANY source
address. require_auth() returns a 'cluster-node' identity for such a
request with no session, API key or account involved, so a remote
unauthenticated attacker could enumerate every container and then run
arbitrary commands as root inside any of them via
POST /api/containers/{runtime}/{id}/exec.

Fix: the built-in default is honoured only when the request arrives from
an address already recorded as a peer in nodes.json, taken from the
transport-level peer_addr() and explicitly NOT X-Forwarded-For /
realip_remote_addr (trusting those would hand the bypass straight back).
A single-node install has no recorded peers and refuses the constant
outright; an existing cluster keeps authenticating, so this ships without
needing a coordinated rotation.

Second, subtler path closed at the same time, found by the new regression
test rather than by review: load_cluster_secret() falls back to the
built-in constant whenever the custom-secret file is absent, empty or
unreadable, so on exactly the at-risk nodes BOTH the in-memory and
on-disk comparison branches already held the default. Guarding only the
third branch would have looked correct and changed nothing. Any
presentation of the published constant is now resolved through a single
decision point regardless of which internal slot holds those bytes; the
ordering requirement is documented at the call site.

All 14 call sites across api, vms, tui and the mTLS middleware take the
peer-scoped form; the peer-less helper is deleted so no caller can skip
the peer argument. Six new tests, including a named PoC regression and
IPv4-mapped-IPv6 canonicalisation for dual-stack listeners.

Nodes still on the default already raise a Compromise-severity finding
via secret_audit into System Check and the alert channels. Adds
SECURITY.md documenting the private reporting path — the reporter hit
the maintainer-only /security/advisories/new URL, which 404s without
write access.

Follow-up, tracked separately: container-exec and other shell sinks
should not accept cluster-secret auth at all (reporter's third
recommendation). That needs an audit of which endpoints peers
legitimately proxy and is deliberately not rushed into this release.

Co-Authored-By: CodeWolf paul@wolf.uk.com
Co-Authored-By: Wolf Software Systems Ltd paul@wolf.uk.com


Verifying this release

Each binary is signed via cosign keyless OIDC (no key distribution — signing identity is the GitHub Actions workflow itself, anchored to the Sigstore Fulcio CA and the Rekor transparency log) and ships with a SLSA build provenance attestation.

Verify the cosign signature:

cosign verify-blob \
  --bundle wolfstack-x86_64.cosign.bundle \
  --certificate-identity-regexp 'https://github.com/wolfsoftwaresystemsltd/WolfStack/\.github/workflows/release\.yml@.*' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  wolfstack-x86_64

Verify the build provenance:

gh attestation verify wolfstack-x86_64 --repo wolfsoftwaresystemsltd/WolfStack

Verify the SHA-256 checksum:

sha256sum -c SHA256SUMS

Artifacts

  • wolfstack-x86_64 / wolfstack-aarch64 / wolfstack-armv7 — static musl binaries (Linux x86_64, ARM64 / Raspberry Pi 4+, and 32-bit ARM).
  • wolfstack-<arch>.cosign.bundle — cosign signature bundle (cert + signature + Rekor entry).
  • SHA256SUMS — checksums for both binaries.

For per-version history see CHANGELOG.md.