Skip to content

[BUG] Sync .cicd security fix and harden hatch_build.py against silent CFFI build degradation (release-readiness for 26.6.1) #1856

@oberstet

Description

@oberstet

Summary

Before tagging/publishing autobahn-python 26.6.1, two release-readiness items
from the zlmdb 26.6.1 release need to be carried over here:

  1. Bump the .cicd (wamp-cicd) submodule to pick up the shell/script-injection
    fix in the shared identifiers.yml reusable workflow (private advisory
    GHSA-6658-6vq6-hjpr, originally reported against autobahn-python).
  2. Harden hatch_build.py so a silent CFFI build failure can no longer
    degrade a platform wheel into a structurally-valid-but-unintended
    py3-none-any wheel — adapted to autobahn's NVX being optional (it has a
    pure-Python fallback), unlike zlmdb's mandatory LMDB extension.

These are intentionally scoped as one focused branch (fix_cicd_sync),
separate from the open functional bugfixes (#1834/#1835 et al.), so review stays
clean and this can merge quickly.

Background

1. .cicd submodule is behind the security fix

  • Current pin: .cicd @ 8f520a9
  • Required pin: .cicd @ f77ca2b (contains the GHSA-6658-6vq6-hjpr fix)

The fix passes untrusted GitHub event fields (notably fork-PR branch names, which
GitHub does not restrict to a shell-safe charset) via env: as quoted data
rather than interpolating ${{ github.event.* }} directly into run: bash, and
adds a fail-closed branch-name allowlist. The follow-up commit inlined the
validator into identifiers.yml so the reusable @main workflow is
self-contained and pin-independent. zlmdb has already bumped to f77ca2b and
verified it end-to-end through the 26.6.1 release; autobahn-python is the next
consumer in the rollout.

Companion (GitHub repo-settings, not in this branch): enable the pypi
GitHub Environment with required reviewers as the real human publish gate.
Please confirm this is already enabled on autobahn-python.

2. hatch_build.py silent CFFI-degradation (the zlmdb#116 pattern)

In initialize() the wheel is only marked platform-specific conditionally:

# If we built any extensions, mark this as a platform-specific wheel
if built_nvx or built_flatc:
    build_data["infer_tag"] = True
    build_data["pure_python"] = False

_build_cffi_modules() swallows compile failures (it catches Exception, prints
a Warning:, and returns built_any=False) — so a transient native-compile
crash (the concrete case seen on zlmdb was a gcc SIGSEGV compiling under QEMU
ARM64 emulation
) does not fail the build. Instead the hook leaves
pure_python=True and emits a autobahn-26.6.1-py3-none-any.whl at exit 0.

Consequences, identical to zlmdb#116:

  • The nick-fields/retry@v3 wrapper never fires (nothing errored to retry).
  • The wheel passes zip/twine check (it is structurally valid).
  • Only check-release-fileset (strict) catches it at release time
    (Missing cpy3xx-…-aarch64 + Extra …-py3-none-any.whl) — i.e. the failure
    surfaces late, at the release gate, instead of at the build.

Why autobahn's fix must differ from zlmdb's

zlmdb's LMDB CFFI extension is mandatory — a py3-none-any zlmdb wheel is
non-functional, so zlmdb's fix is an unconditional "raise if not built".

autobahn's NVX is an optional accelerator: there is a real pure-Python
fallback (src/autobahn/websocket/xormasker.py, the UTF-8 validator likewise),
and AUTOBAHN_USE_NVX=0 is an explicitly supported configuration. A
py3-none-any autobahn wheel built with NVX deliberately disabled is legitimate.

Therefore the guard must be conditional, not a blanket raise:

  • If NVX was requested (AUTOBAHN_USE_NVX not in {"0","false"}) but
    _build_cffi_modules() reported nothing built → raise (this is the silent
    degradation we want to catch and let CI retry).
  • If NVX was deliberately disabled → allow the pure-Python wheel as today.

flatc is bundled best-effort (it is a developer convenience; the binary schemas
are committed and shipped, so a package build never runs flatc) and must not
gate the wheel tag either way.

Proposed changes (branch fix_cicd_sync)

  1. Submodule bump: .cicd 8f520a9 → f77ca2b.

  2. hatch_build.py initialize() — replace the conditional
    pure_python=False block with NVX-aware logic, roughly:

    • compute nvx_requested = os.environ.get("AUTOBAHN_USE_NVX", "1") not in ("0", "false")
    • if nvx_requested and not built_nvx: raise RuntimeError(...) explaining
      that the mandatory-when-requested NVX extension failed to compile and the
      build refuses to silently emit a py3-none-any wheel (so CI retries the
      transient failure rather than uploading a degraded artifact).
    • set build_data["infer_tag"] = True / pure_python = False whenever any
      native artifact was produced (built_nvx or built_flatc), unchanged.
    • leave the AUTOBAHN_USE_NVX=0 path producing a pure-Python wheel.
  3. docs/changelog.rst — under the existing 26.6.1Build & CI/CD
    section, add entries for the .cicd security bump and the hatch_build
    hardening.

Out of scope (separate work)

Acceptance criteria

  • .cicd submodule pinned at f77ca2b.
  • A wheel build with NVX requested but the CFFI compile failing now exits
    non-zero (no py3-none-any emitted); CI retry can re-attempt.
  • A wheel build with AUTOBAHN_USE_NVX=0 still produces a pure-Python wheel
    and succeeds.
  • flatc build failure (best-effort) does not, by itself, fail the wheel.
  • Changelog updated under 26.6.1.
  • CI green (incl. ruff check).

References

  • zlmdb#116 / zlmdb PR#117 (the mandatory-extension variant of this fix)
  • GHSA-6658-6vq6-hjpr (wamp-cicd identifiers.yml injection; fix f77ca2b)
  • src/autobahn/websocket/xormasker.py (pure-Python NVX fallback)
  • hatch_build.py::initialize (lines ~49-69), ::_build_cffi_modules

Checklist

  • I have searched existing issues to avoid duplicates
  • I have provided a minimal reproducible example
  • I have included version information
  • I have included error messages/logs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions