Skip to content

styxx 7.48.1 — security repair (GHSA-h5xv-4344-f62r)

Choose a tag to compare

@github-actions github-actions released this 07 Oct 00:11
· 160 commits to main since this release
pip install -U styxx==7.48.1

Security release. Advisory: GHSA-h5xv-4344-f62r. Upgrade if you verify OATH capsules made by someone else, run styxx.charon over them, or run styxx.corpus_audit over a repository you did not write.

The text below is the start of the [7.48.1] section of CHANGELOG.md: the summary and the security entry in full. The entries carried from [Unreleased], and the one written at the cut about conformance/sworn/, follow them in the file.


A patch release: one security repair, the version bump that conformance/sworn/ moves with, and
what merged on main after 7.48.0. Upgrade with pip install -U styxx==7.48.1. For anyone who
verifies capsules made by someone else, or runs styxx.charon over them, upgrading is the fix.
The entries headed [Unreleased] until this cut are kept whole below, in the order this file
carried them; entries written at this cut say so in their opening line.

Security

  • python -m styxx.capsule verify (OATH Capsule v0.1) and styxx.charon's re-run of a capsule
    wrote the capsule's embedded document and receipts under names the capsule chose, so a capsule
    could write bytes of its author's choosing to any path the user running the verifier can write.
    python -m styxx.corpus_audit, re-deriving a certificate over its receipts' bytes at the issuing
    commit, wrote them the same way under receipt names the audited certificate gave. Affected: 7.47.0
    and 7.48.0 through the capsule verifier; 7.48.0 through charon and corpus_audit. Advisory
    GHSA-h5xv-4344-f62r. What was wrong, the repair and the workaround until you can upgrade are in
    the entry below.

In the package since 7.48.0

  • python -m styxx.islands gains --island-z, and --demo reads its list at island_z=3 and
    prints the rule it used (#93). The library default stays 1.0.
  • The PyPI description gives each AUC to the instrument that earned it.

In the repository, not the wheel

  • The #125 packet repair, the errata and corrections from the 7.48.0 audit, 7.48.0's Zenodo record,
    the sworn action's docs (#164), and two tests that failed on Windows for reasons outside the code
    under test (#185, #186).
  • SECURITY.md said releases reach PyPI through Trusted Publishing with PEP 740 attestations.
    They do not: publish.yml uploads with an API token held as a repository secret and sets
    attestations: false. The file now says so, and its steps for checking a release compare
    SHA-256 sums only. Written at this cut.

Cutting this release

  • styxx/_version.py is 7.48.1 (e2b3174), and CITATION.cff gives version 7.48.1 and
    date-released 2026-10-06 (3fc2c85).
  • conformance/sworn/ was regenerated for the version stamp (e2b3174; entry below): 15 vectors
    took new ids, 0 moved, and no expected outcome changed.
  • README.md, which becomes the PyPI page, was audited at this cut against the tree it ships with.
    One line changed (2770cd7): the note under the islands demo said a drift of about 0.005 could
    change which clique members fall under the island cut, which #93 made untrue for --demo; it now
    says the block is abridged and that the drift's cause is not established. Its links still point
    at the v7.48.0 tag.

Security: a capsule or an audited certificate chose where styxx wrote files (GHSA-h5xv-4344-f62r)

styxx/capsule.py, styxx/charon.py, tests/test_capsule_bare_names.py (NEW); commit 76e9dcc.
styxx/corpus_audit.py, tests/test_corpus_audit_bare_names.py (NEW); commit d8b856a, after the review
of this release found the same write there. Written at this cut from those commits.

  • What was wrong. A v0.1 OATH capsule (styxx-oath/capsule/v0.1) embeds its document and its
    receipts as bytes, each under a name. python -m styxx.capsule verify FILE re-runs the certifier
    by writing those bytes to Path(tempdir) / name, and the capsule supplies the name. A path
    joined to an absolute name is that absolute name, and .. climbs out, so an absolute name or a
    ../ name was written outside the temporary directory: verifying a capsule someone else made
    could create or overwrite any file the user running the verifier can write, with bytes the
    capsule's author chose. The hash checks did not stop it, because the capsule also carries the
    certificate those bytes are checked against. styxx.charon's re-run of a v0.1 capsule (in
    ingest, verify and derive) wrote the same way. So did python -m styxx.corpus_audit with
    history on (the default for a full clone): to re-certify a certificate over the bytes its
    receipts had at the issuing commit, it wrote those bytes under the receipt names the audited
    certificate gives, so auditing a repository someone else wrote could write outside its
    temporary directory.
  • Affected releases. 7.47.0 and 7.48.0, through python -m styxx.capsule verify
    (styxx.capsule.verify_capsule), which has been in the package since 2026-08-31; and 7.48.0,
    through styxx.charon and styxx.corpus_audit. Creating a capsule is not affected: it writes
    under the names of the files you hand it.
  • The repair. Every embedded name must be a bare file name under POSIX and Windows rules alike:
    no separator, no drive, not . or .., no control character, no trailing dot or space, and no
    Windows device name. No two names may be the same file on a case-insensitive file system.
    Otherwise verify reports the name as a problem, writes nothing and does not re-run the
    certifier, so the capsule fails; charon records live_error: unsafe_embedded_name and writes
    nothing; corpus_audit writes nothing, re-derives nothing for that certificate and says why in
    its stands_reason. The ten v0.1 capsules committed under papers/ carry only names the rule accepts, and
    all ten still verify.
  • What to do. Upgrade: pip install -U styxx==7.48.1. Until you can, verify only capsules from
    a source you trust, or verify them in a throwaway environment (a container, a virtual machine or
    a disposable account) where a file written anywhere does no harm. The same holds for running
    python -m styxx.charon over capsules you did not make, and python -m styxx.corpus_audit over
    a repository you did not write (or run it with --history off).
  • The tests. tests/test_capsule_bare_names.py refuses an absolute receipt name, a ../
    receipt name and a ../ document name with nothing written; holds charon to writing nothing
    where a forged capsule points; refuses two names that differ only in case; and pins the rule on
    7 names it accepts and 19 it refuses. Run against 43b3b60, the commit this release branched
    from, the four tests of a name that escapes (absolute receipt, ../ receipt, ../ document,
    charon) fail, the 26 cases that pin the rule fail because the rule is not there, and the
    honest-capsule and case-collision tests pass (on Windows). tests/test_corpus_audit_bare_names.py
    audits a throwaway repository whose certificate names a receipt ../../ out of the temporary
    directory, and one with an absolute name: nothing is written outside it. Run against 76e9dcc the
    climbing case fails; the absolute case passes there too, because that name never resolves to
    bytes at the issuing commit.
  • What it does not say. That the certifier is safe to run over arbitrary bytes. Verifying a
    capsule still re-runs the installed certifier over the embedded document and receipts; that is
    the design. This repair bounds where those bytes are written.

Integrity

file sha256
styxx-7.48.1-py3-none-any.whl a5d8a6b3ba1e0070cda1cb69c5452cd68f22f8ecec286af7157594b5a47b9a31
styxx-7.48.1.tar.gz fde727642f4e6140c69d8c6805c810d26b5f6159deb7065c629999f74bce3da6

Built by publish.yml on Ubuntu from tag v7.48.1 (commit b42942186015848daa32e40b95970f4e370a3016), uploaded to PyPI, and attached here. Checked on 2026-10-06:

  • both files as published on PyPI have these hashes, and so do the assets on this page;
  • a clean virtual environment installing styxx==7.48.1 from PyPI reports 7.48.1;
  • that install verifies a committed capsule from papers/;
  • it refuses a copy of that capsule whose receipt name is an absolute path, and writes nothing there.

The upload used an API token, so there are no PEP 740 attestations; check these hashes instead (see SECURITY.md).

Archived on Zenodo as 10.5281/zenodo.23200977, the next version of the styxx software record (concept 10.5281/zenodo.19758618), with the source bundle of this tag, the wheel and the sdist.

🤖 Release prepared with Claude Code