From 7687cfa5776a17e74068ec73003811b02c9de160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20Cezar=20Mois=C3=A9s?= Date: Mon, 31 Aug 2026 20:32:42 -0300 Subject: [PATCH] release: prepare ZUPT 5.2.8 --- .github/workflows/promote-release.yml | 2 +- AUDIT.md | 75 ++++++++++++--- CHANGELOG.md | 81 ++++++++++++---- DISTRIBUTION.md | 55 ++++++----- INSTALL.md | 29 ++++-- README.md | 118 +++++++++++++++--------- SECURITY.md | 70 ++++++++++---- THIRD-PARTY-NOTICES.md | 4 +- THREAT_MODEL.md | 73 ++++++++++----- doc/zupt-gui.1 | 4 +- doc/zupt.1 | 8 +- gui/README.md | 14 +-- gui/packaging/deb/control | 4 +- gui/packaging/windows/build-windows.bat | 2 +- include/zupt.h | 3 +- install.sh | 2 +- packaging/aur/PKGBUILD | 4 +- packaging/debian/changelog | 14 +++ packaging/guix/zupt.scm | 2 +- packaging/homebrew/zupt.rb | 4 +- packaging/nix/flake.nix | 4 +- packaging/opensuse/README.md | 40 +++++--- packaging/opensuse/_service | 2 +- packaging/opensuse/zupt.changes | 15 +++ packaging/opensuse/zupt.spec | 2 +- packaging/portable/README.txt | 4 +- packaging/rpm/zupt.spec | 11 ++- src/zupt_format.c | 2 +- tests/test_audit_flake.sh | 4 +- 29 files changed, 454 insertions(+), 198 deletions(-) diff --git a/.github/workflows/promote-release.yml b/.github/workflows/promote-release.yml index d05b427..e28d6c1 100644 --- a/.github/workflows/promote-release.yml +++ b/.github/workflows/promote-release.yml @@ -11,7 +11,7 @@ on: required: true type: number tag: - description: Existing annotated release tag, for example v5.2.7 + description: Existing annotated release tag, for example v5.2.8 required: true type: string diff --git a/AUDIT.md b/AUDIT.md index 62eaa08..7f46f35 100644 --- a/AUDIT.md +++ b/AUDIT.md @@ -1,12 +1,12 @@ -# ZUPT 5.2.7 audit guide and finding history +# ZUPT 5.2.8 audit guide and finding history This document describes review surfaces and reproducible checks. It is an upstream self-review, not an independent audit, certification, or guarantee. `SECURITY.md` defines reporting policy and `THREAT_MODEL.md` defines the security boundary. -## 5.2.7 scope +## 5.2.8 scope The baseline scope is the source-only CLI and its bundled source codec: @@ -28,7 +28,7 @@ output. ## Source-only review -The 5.2.7 baseline retains the source-only boundary introduced in 5.2.2, which +The 5.2.8 baseline retains the source-only boundary introduced in 5.2.2, which removed incomplete SDK/PQBOX header snapshots and local precompiled-library expectations. Git and new upstream source archives are intended to contain no compiled executable, object, shared/static @@ -42,10 +42,10 @@ scripts/check-source-only.sh # committed Git tree or immutable tag scripts/check-source-only.sh --tag HEAD -scripts/check-source-only.sh --tag v5.2.7 +scripts/check-source-only.sh --tag v5.2.8 # generated source archive -scripts/check-source-only.sh --archive /path/to/zupt-5.2.7.tar.gz +scripts/check-source-only.sh --archive /path/to/zupt-5.2.8.tar.gz ``` The scanner checks extensions and magic bytes, nested archives, symlink targets, @@ -80,6 +80,7 @@ make -j"$(getconf _NPROCESSORS_ONLN 2>/dev/null || printf 1)" \ WITH_SDK=0 WITH_PQBOX=0 V=1 make WITH_SDK=0 WITH_PQBOX=0 check make WITH_SDK=0 WITH_PQBOX=0 test-all +make sdk-test ``` Relevant review layers include: @@ -92,6 +93,7 @@ Relevant review layers include: | Archive behavior | quick/regression, traversal, argument-order, block-swap, nonce, and exact-size tests | Exercises current parser, integrity, and round-trip properties | | Password sources | `tests/test_password_sources.sh` | Exercises password-file, inherited-descriptor and explicit-prompt rejection paths without logging password contents | | Key files | native key regressions | Exercises no-replace private-file creation, POSIX mode `0600`/Windows current-user-only DACL, failed-partial behavior, checksum, and exact ZKEY/ZPQK version/flags/reserved/size/role validation | +| SDK key publication | `make sdk-test` | Exercises atomic descriptor/handle-backed key copies, POSIX private/public modes, and symlink/hardlink target preservation; this now runs in `release-check` and hosted GCC/Clang Linux CI | | Terminal output | archive-comment regression | Requires displayed untrusted comments to contain no raw terminal-control sequence | | Prompt cleanup | PTY signal regression | Requires handled POSIX interruption to restore the saved terminal state | | Sanitizers | `make test-asan-run` | Builds and executes separate ASan/UBSan/LSan evidence where supported; not a substitute for normal tests | @@ -109,7 +111,7 @@ without evidence. The following upstream self-audit results apply only to the 5.2.2 candidate at commit `ff99770` on the recorded local Linux environments. The immutable 5.2.2 tag was not promoted after post-tag CI integration failures. These results are -not independent certification, a 5.2.7 result, or evidence that release assets +not independent certification, a 5.2.8 result, or evidence that release assets were published. | Gate | Result | Recorded evidence | @@ -141,7 +143,7 @@ A separate local openSUSE Tumbleweed reproduction resolved the explicit produced exactly one `zupt-5.2.4.tar.gz`, which passed the source-only scanner. This isolates a release/test harness defect; it is not evidence of a product, archive-format, cryptographic, codec, or SDK ABI change. It also does not turn -the skipped native jobs into passes or transfer any result to 5.2.7. +the skipped native jobs into passes or transfer any result to 5.2.8. ## Prior 5.2.5 exact-tag native-gate evidence @@ -164,7 +166,7 @@ GNU Bash 3.2.57 in a clean clone. All four exercised modes completed: the repository audit reported 609 files and one archive; `--tree` reported 204/0; `--archive` reported 201/1; and `--root` plus `--tag v5.2.5` reported 810/2. This is targeted scanner compatibility evidence only, not exact-v5.2.6 or -v5.2.7 hosted CI, package, native-platform, or promotion evidence. +v5.2.8 hosted CI, package, native-platform, or promotion evidence. ## Prior 5.2.6 exact-tag native-gate evidence @@ -178,10 +180,52 @@ archive and diagnostic assertions. The 5.2.7 changes scope those helper declarations to supported x86 builds and carry the safe UTF-8 fixture across the Windows argument boundary without locale-dependent byte conversion. These are test/release integration changes, -not archive-format, cryptographic, codec, or SDK ABI changes. They are not proof -that any v5.2.7 native or hosted gate has passed. +not archive-format, cryptographic, codec, or SDK ABI changes. -The exact 5.2.7 candidate must repeat the required suite. Native Windows and +## Prior 5.2.7 exact-tag native-gate evidence + +The immutable `v5.2.7` candidate was not promoted. Exact-tag GitHub Actions run +`33445470664` concluded `cancelled` at `2026-08-31T23:11:19Z`, with 13 +successful jobs, one failed macOS job, and one cancelled Windows job. The macOS +runner filesystem rejected creation of the +raw-C1 filename fixture with `EILSEQ`. The hosted Windows job stalled in `make +check`; a MinGW/Wine reproduction isolated the cause to +`test --password-prompt ... /dev/null || printf 1)" \ WITH_SDK=0 WITH_PQBOX=0 V=1 make WITH_SDK=0 WITH_PQBOX=0 check make WITH_SDK=0 WITH_PQBOX=0 test-all +make sdk-test ``` Where the compiler supports them, run the sanitizer target separately: @@ -303,7 +330,7 @@ result. Post-tag CI integration failures prevented 5.2.2 promotion. Those upstream self-audit results are not independent certification and do not transfer to -5.2.7. The immutable 5.2.3 candidate was not promoted because its source-policy +5.2.8. The immutable 5.2.3 candidate was not promoted because its source-policy test assumed LF for a Windows `.bat` file checked out as CRLF. The immutable v5.2.4 candidate was not promoted after exact-tag GitHub Actions run `33431386002`: 12 jobs succeeded, the sole openSUSE job failed in its @@ -313,7 +340,7 @@ Tumbleweed reproduction confirmed that `refs/tags/v5.2.4` is valid and that `os.chdir(service_dir)` lets `obs_scm`, `tar`, and `recompress` complete with a source-scanned archive. This was a release/test integration defect, not a product, archive, cryptographic, codec, or SDK ABI change, and its evidence does -not transfer automatically to 5.2.7. The immutable v5.2.5 candidate was also +not transfer automatically to 5.2.8. The immutable v5.2.5 candidate was also not promoted: exact-tag GitHub Actions run `33434986357` recorded 13 successful jobs and failed native Windows/macOS jobs. Its Windows fixture-byte and macOS secure-wipe/Bash 3.2 defects were corrected for 5.2.6. A targeted clean-clone @@ -324,8 +351,15 @@ then completed 13 jobs successfully but failed native macOS because x86 SHA-NI test helpers were unused on arm64 under `-Werror`, and failed native Windows when argv transcoding aborted the safe UTF-8 fixture. Those are test-harness integration defects, not product, archive, cryptographic, codec, or SDK ABI -changes; v5.2.6 remained unpromoted. The exact 5.2.7 candidate must -repeat the required suite. Native Windows and macOS, hosted GitHub CI/release +changes; v5.2.6 remained unpromoted. The exact 5.2.8 candidate must +repeat the required suite. The immutable v5.2.7 candidate was likewise not +promoted: exact-tag run `33445470664` concluded `cancelled` at +`2026-08-31T23:11:19Z`, with 13 successful jobs, one failed macOS job after +raw-C1 fixture creation returned `EILSEQ`, and one cancelled Windows job after +the hosted job stalled in `make check`; a MinGW/Wine reproduction isolated the +cause to a redirected password prompt entering `_getch`. Version 5.2.8 makes both test boundaries fail +or skip without hanging, but this is not exact-candidate evidence. Native +Windows and macOS, hosted GitHub CI/release promotion, authenticated OBS, and the openSUSE automatic `debugsource` rpmlint `no-binary` finding remain pending until recorded otherwise. An unavailable or unexecuted environment remains `SKIP`, never `PASS`. diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md index 0d8091d..025f76d 100644 --- a/THIRD-PARTY-NOTICES.md +++ b/THIRD-PARTY-NOTICES.md @@ -159,7 +159,7 @@ grant attached to their unchanged Git blobs, are recorded in ## AppImage type-2 runtime -No AppImage is a promised or promoted 5.2.7 release asset. The upstream +No AppImage is a promised or promoted 5.2.8 release asset. The upstream type-2 runtime inspected during the 5.2.2 review statically linked musl, libfuse, squashfuse, zstd, zlib, and mimalloc, but its own license notice did not list mimalloc and the available release inputs did not provide a complete @@ -171,7 +171,7 @@ no network input and requires the operator to supply both a locally verified runtime and `APPIMAGE_RUNTIME_COMPLIANCE_FILE`, containing the license notices, source correspondence or offer, and relink information applicable to those exact runtime bytes. An artifact produced independently with that helper is -not covered by the 5.2.7 upstream release gates. +not covered by the 5.2.8 upstream release gates. ## Reporting attribution issues diff --git a/THREAT_MODEL.md b/THREAT_MODEL.md index 4d45192..413269b 100644 --- a/THREAT_MODEL.md +++ b/THREAT_MODEL.md @@ -1,4 +1,4 @@ -# ZUPT 5.2.7 threat model +# ZUPT 5.2.8 threat model This document defines the security boundary of the ZUPT archive tool. It is not a certification, a guarantee against every hostile input, or a substitute @@ -17,7 +17,7 @@ plausibly deniable. ## Baseline considered here -The upstream baseline is built from the 5.2.7 source with: +The upstream baseline is built from the 5.2.8 source with: ```sh make WITH_SDK=0 WITH_PQBOX=0 @@ -88,6 +88,8 @@ duplicates but shares the underlying stream/offset and may buffer beyond the line, so callers should provide a descriptor dedicated to that password read. On POSIX, handled prompt interruptions restore the saved terminal state before termination; an exact-candidate PTY regression is required before release. +On Windows, a prompt is entered only for a real console input handle; +redirected input and console EOF fail instead of blocking in `_getch`. Native private-key generation uses no-replace creation with POSIX mode `0600` or a Windows current-user-only DACL. A failed write, flush/fsync, or close leaves @@ -99,6 +101,13 @@ and public/private role validation. This prevents role confusion and partial/trailing-key acceptance; it does not protect a key after endpoint or account compromise. +When the optional system SDK is enabled, the in-repository adapter copies a key +through the core atomic publisher, applies POSIX mode through the already-open +temporary descriptor, and publishes only after copy/close checks succeed. Its +`sdk-test` regression preserves existing symlink/hardlink targets and verifies +private/public modes. This narrows the adapter boundary; it does not extend the +baseline assessment to the external SDK implementation. + ### Encrypted archive integrity Current encrypted archives authenticate ciphertext, canonical block metadata, @@ -175,22 +184,37 @@ temporary through its descriptor or handle. These controls reduce traversal, link, race, and partial-output risks, but do not establish that no parser or filesystem bug can exist. -The Windows handle-relative boundary in 5.2.7 covers normal local Win32 paths. +Benchmark scratch data lives in a random private directory. Cleanup resolves +POSIX components without following links and deletes relative to pinned +descriptors. On Windows it retains no-delete-sharing ancestor handles, refuses +reparse-point recursion, then reopens each emptied directory relative to its +pinned parent and verifies its filesystem identity before handle-based +deletion. An attacker who inserts a link can cause cleanup failure, but the +cleanup must not traverse to the link target. + +The Windows handle-relative boundary in 5.2.8 covers normal local Win32 paths. Win32 extended-length and device-namespace paths, raw UNC output roots, and mapped/network-drive output are not supported. Cross-build and Wine results are not a substitute for the required native `windows-latest` Unicode package gate. Restore locally before moving verified output to network storage. Disk restore copies the measured compacted archive into one exclusively -created, auto-deleted scratch file before it opens a destructive destination. -Preflight and restoration consume that same open snapshot. An explicit -`ZUPT_TMPDIR` selects an existing scratch directory; failure there does not -fall back to consuming the mutable source pathname. On supported Linux, macOS, -and FreeBSD interfaces, a raw block-device target is rejected before writing if -its capacity is unknown or smaller than the image. These controls reduce source -exchange and immediate overrun risk but do not protect against a compromised -kernel/device, a wrongly selected sufficiently large device, power loss, or -hardware failure. +created, auto-deleted scratch file. Preflight and restoration consume that same +open snapshot. An explicit `ZUPT_TMPDIR` selects an existing scratch directory; +failure there does not fall back to consuming the mutable source pathname. On +POSIX, the destination is opened once without truncation or final-symlink +following, classified with `fstat`, and the same raw-device descriptor is +retained for supported Linux, macOS, and FreeBSD capacity checks and writes. +Regular-file output retains atomic publication. A raw target is rejected before +writing if its capacity is unknown or smaller than the image. These controls +reduce source exchange, target exchange, and immediate overrun risk but do not +protect against a compromised kernel/device, a wrongly selected sufficiently +large device, power loss, or hardware failure. + +The SDK publication, POSIX disk-target, and benchmark-cleanup changes address +CodeQL High #5, #6, and #7 respectively. Their source review and regressions +are project evidence, not independent certification or proof that the exact +5.2.8 hosted/native gates passed. For an untrusted archive: @@ -250,9 +274,9 @@ tagged source. Each artifact extends the trust boundary to its builder, toolchain, runner image, and packaging scripts. Treat it as validated only when the exact target has a recorded build, content/package inspection, extracted or installed smoke test, and applicable archive round trip. An AppImage is not -promoted for 5.2.7; bare Linux and Windows executables are also excluded. +promoted for 5.2.8; bare Linux and Windows executables are also excluded. -For 5.2.7, that gated artifact scope covers the CLI files plus the exact GUI +For 5.2.8, that gated artifact scope covers the CLI files plus the exact GUI DEB, noarch/source RPM, and source-only portable ZIP named in the README. The portable ZIP contains no compiled runtime and crosses the release boundary only after source scans and an exact safe-member check. AppDir and Flatpak bundles @@ -265,7 +289,7 @@ strict Clang, GCC `-fanalyzer`, the 9/9 tool-enabled static-analysis run, ASan/UBSan/LSan, and 1,000 mutation-fuzz iterations passed. Earlier off-screen GUI smoke evidence is retained separately. Post-tag CI integration failures prevented 5.2.2 promotion. This upstream self-review is not an independent -certification and is not 5.2.7 evidence. The immutable 5.2.3 candidate was not +certification and is not 5.2.8 evidence. The immutable 5.2.3 candidate was not promoted because its source-policy test assumed LF for a Windows `.bat` checkout that correctly used CRLF. The immutable v5.2.4 candidate was not promoted after exact-tag GitHub Actions run `33431386002`: 12 jobs succeeded, the sole openSUSE @@ -275,17 +299,24 @@ Tumbleweed reproduction established that the explicit `refs/tags/v5.2.4` revision works and that `os.chdir(service_dir)` completes the source-service chain. This narrows the failure to release/test integration; it changes no product, archive, cryptographic, codec, or SDK ABI boundary and supplies no -automatic 5.2.7 evidence. The immutable v5.2.5 candidate was not promoted after +automatic 5.2.8 evidence. The immutable v5.2.5 candidate was not promoted after exact-tag GitHub Actions run `33434986357`: 13 jobs succeeded, but native Windows and macOS failed on fixture-byte preservation and Darwin/Bash 3.2 portability respectively. The corresponding 5.2.6 corrections were followed by exact-tag run `33442264243`: 13 jobs succeeded, while native macOS failed on x86-only SHA-NI helper declarations unused on arm64 under `-Werror`, and native Windows aborted during safe UTF-8 fixture argv transcoding. The v5.2.6 tag was -not promoted. The corresponding 5.2.7 test-harness corrections do not establish -their own test result. Hosted GitHub CI and release promotion, native +not promoted. Version 5.2.7 corrected those two boundaries, but its exact-tag +run `33445470664` concluded `cancelled` at `2026-08-31T23:11:19Z`, with 13 +successful jobs, one failed macOS job after raw-C1 filename creation returned +`EILSEQ`, and one cancelled Windows job after the hosted job stalled in `make +check`; a MinGW/Wine reproduction isolated the cause to a redirected password +prompt entering `_getch`. +The corresponding 5.2.8 fixture and prompt corrections do not establish their +own test result. CI now exercises `sdk-test`, but its inclusion is not a pass. +Hosted GitHub CI and release promotion, native Windows/macOS, authenticated OBS, and the openSUSE automatic `debugsource` -rpmlint `no-binary` finding remain pending until an exact 5.2.7 candidate +rpmlint `no-binary` finding remain pending until an exact 5.2.8 candidate records them. ## Historical compatibility notes @@ -313,7 +344,7 @@ These are historical facts about earlier releases, retained to support recovery: combinations remain unclaimed. Historical test counts in the changelog describe those releases. They do not -automatically become 5.2.7 results; current outcomes belong in the release +automatically become 5.2.8 results; current outcomes belong in the release validation record, with unavailable environments marked `SKIP`. In particular, runs made before the final positional-AAD and mandatory-AIT changes are not final release gates for the resulting candidate. @@ -324,4 +355,4 @@ Email **zupt@riseup.net** with `[security]` in the subject. Include the version, platform, impact, and a minimal non-sensitive reproducer. Do not disclose the issue publicly until a coordinated timeline has been agreed. -Document version: 5.2.7, 2026-08-31. +Document version: 5.2.8, 2026-08-31. diff --git a/doc/zupt-gui.1 b/doc/zupt-gui.1 index 2c37b87..cecb070 100644 --- a/doc/zupt-gui.1 +++ b/doc/zupt-gui.1 @@ -1,6 +1,6 @@ .\" SPDX-License-Identifier: AGPL-3.0-or-later .\" Copyright (c) 2025-2026 Cristian Cezar Moisés -.TH ZUPT-GUI 1 "2026-08-31" "ZUPT 5.2.7" "User Commands" +.TH ZUPT-GUI 1 "2026-08-31" "ZUPT 5.2.8" "User Commands" .SH NAME zupt-gui \- Qt interface for the ZUPT backup utility .SH SYNOPSIS @@ -47,7 +47,7 @@ or only when libvuptsdk or libpqvaptvupt is independently reported enabled. These two optional integrations are detected separately. .PP -The gated 5.2.7 GUI release set is limited to the architecture-independent DEB, +The gated 5.2.8 GUI release set is limited to the architecture-independent DEB, noarch/source RPM, and source-only portable ZIP named in the project README. Package gates require exact checks and installed off-screen GUI/CLI integration. The portable ZIP receives source scans, an exact safe-member allowlist, and an diff --git a/doc/zupt.1 b/doc/zupt.1 index ed48a17..d871e25 100644 --- a/doc/zupt.1 +++ b/doc/zupt.1 @@ -1,6 +1,6 @@ .\" SPDX-License-Identifier: AGPL-3.0-or-later .\" Copyright (c) 2025-2026 Cristian Cezar Moisés -.TH ZUPT 1 "2026-08-31" "ZUPT 5.2.7" "User Commands" +.TH ZUPT 1 "2026-08-31" "ZUPT 5.2.8" "User Commands" . .SH NAME zupt \- source-built backup compression and authenticated-encryption utility @@ -89,7 +89,7 @@ Git and the upstream source tarball are source-only. Separately built CLI DEB, binary RPM, SRPM, notice-bearing Linux tar.xz, Windows ZIP, and macOS DMG assets may be published from the immutable tag only after their target-specific gates pass; they never enter Git or the source tarball. An AppImage is not promoted -for 5.2.7; neither are AppDir/Flatpak bundles, GUI platform installers, or bare +for 5.2.8; neither are AppDir/Flatpak bundles, GUI platform installers, or bare Linux/Windows executables. The Python/Qt frontend remains available as source; its gated architecture-independent DEB, noarch/source RPM, and source-only portable ZIP are included in the release claim. The portable ZIP contains no @@ -477,7 +477,7 @@ then traverse below a pinned directory descriptor with no-follow operations. Windows builds use handle-relative traversal and no-replace publication for normal local Win32 destinations. Extended-length and device-namespace paths, raw UNC output roots, and mapped/network-drive output -are not supported in 5.2.7. Cross-compilation and Wine results are not native +are not supported in 5.2.8. Cross-compilation and Wine results are not native Windows evidence; the native Windows package gate, including its Unicode round trip, is separate and mandatory before publication. . @@ -577,7 +577,7 @@ and the encrypted-dedup linear AAD sequence published through 5.2.1. The narrow compatibility fixture is an actual v5.2.1 password-encrypted DATA/DATA/REF/DATA disk archive stored as hexadecimal text with source and hash provenance. The candidate lists, tests, extracts, and restores that fixture -byte-exact. The exact 5.2.7 candidate must repeat the gate. It does not imply +byte-exact. The exact 5.2.8 candidate must repeat the gate. It does not imply that a 5.2.1 reader accepts every new 5.2.2 archive or that every historical encrypted mode was retested. diff --git a/gui/README.md b/gui/README.md index 1937c1d..378fda5 100644 --- a/gui/README.md +++ b/gui/README.md @@ -1,6 +1,6 @@ # ZUPT GUI -The ZUPT GUI is a Python/Qt front end for the ZUPT 5.2.7 command-line +The ZUPT GUI is a Python/Qt front end for the ZUPT 5.2.8 command-line program. It starts the CLI as a subprocess; compression, archive parsing, and cryptography remain in the C program. @@ -83,10 +83,10 @@ operating systems and must be tested on the target system. Release pages provide only these GUI artifacts after their separate package and installed off-screen GUI/CLI integration gates pass: -- `zupt-gui_5.2.7_all.deb`; -- `zupt-gui-5.2.7-1.noarch.rpm`; -- `zupt-gui-5.2.7-1.src.rpm`; -- `zupt-gui-5.2.7-portable.zip`. +- `zupt-gui_5.2.8_all.deb`; +- `zupt-gui-5.2.8-1.noarch.rpm`; +- `zupt-gui-5.2.8-1.src.rpm`; +- `zupt-gui-5.2.8-portable.zip`. The DEB/RPM packages install the Python/Qt source and depend on the matching `zupt` CLI package. The portable ZIP contains source, launchers, icons, licenses, @@ -97,7 +97,7 @@ An absent artifact did not pass its gate and must not be inferred from another format's result. GUI AppImage, AppDir and Flatpak bundles, and Windows/macOS GUI installers are -not promoted by the upstream 5.2.7 release gates. +not promoted by the upstream 5.2.8 release gates. `packaging/build-gui-appimage.sh` is a downstream-only helper and fails unless its operator supplies the exact verified runtime plus a complete license/source-relink notice through `APPIMAGE_RUNTIME_COMPLIANCE_FILE`; that @@ -110,7 +110,7 @@ notices. It fails unless the directory also has non-empty `PYTHON-NOTICE.txt`, `PYINSTALLER-NOTICE.txt`, `QT-NOTICE.txt`, and either `PYSIDE6-NOTICE.txt` or `PYQT6-NOTICE.txt`. The installer includes that directory together with every ZUPT license and notice. This requirement does -not make the untested GUI installer a 5.2.7 release asset. The promoted Windows +not make the untested GUI installer a 5.2.8 release asset. The promoted Windows ZIP and macOS DMG are CLI-only. Packaging recipes and scripts under `gui/packaging/` and `packaging/` are build diff --git a/gui/packaging/deb/control b/gui/packaging/deb/control index a3632d2..65765c6 100644 --- a/gui/packaging/deb/control +++ b/gui/packaging/deb/control @@ -1,9 +1,9 @@ Package: zupt-gui -Version: 5.2.7 +Version: 5.2.8 Section: utils Priority: optional Architecture: all -Depends: python3 (>= 3.9), python3-pyqt6 | python3-pyside6.qtwidgets, zupt (= 5.2.7) +Depends: python3 (>= 3.9), python3-pyqt6 | python3-pyside6.qtwidgets, zupt (= 5.2.8) Maintainer: Cristian Cezar Moisés Homepage: https://github.com/cristiancmoises/zupt Description: Qt graphical interface for the ZUPT backup utility diff --git a/gui/packaging/windows/build-windows.bat b/gui/packaging/windows/build-windows.bat index 544286f..36c23d6 100644 --- a/gui/packaging/windows/build-windows.bat +++ b/gui/packaging/windows/build-windows.bat @@ -13,7 +13,7 @@ rem runtime files embedded by this local build. setlocal EnableExtensions for %%I in ("%~dp0\..\..\..") do set "REPO_ROOT=%%~fI" set "VERSION=%~1" -if not defined VERSION set "VERSION=5.2.7" +if not defined VERSION set "VERSION=5.2.8" if not defined ZUPT_DIST_DIR set "ZUPT_DIST_DIR=%TEMP%\zupt-release" if not defined ZUPT_CLI_EXE set "ZUPT_CLI_EXE=%REPO_ROOT%\zupt.exe" set "WORK=%TEMP%\zupt-gui-build-%RANDOM%-%RANDOM%" diff --git a/include/zupt.h b/include/zupt.h index c9923ab..4136770 100644 --- a/include/zupt.h +++ b/include/zupt.h @@ -122,7 +122,8 @@ static inline int zupt_win_mkdir_utf8(const char *path) { /* v5.2.5 corrects the OBS service harness cwd; format remains v1.6. */ /* v5.2.6 corrects native release-gate portability; format remains v1.6. */ /* v5.2.7 corrects native test-harness portability; format remains v1.6. */ -#define ZUPT_VERSION_STRING "5.2.7" +/* v5.2.8 hardens three path-race boundaries; format remains v1.6. */ +#define ZUPT_VERSION_STRING "5.2.8" /* Vendored codec release (upstream tag) — single source for display strings. * The codec's own VV_VERSION_* is its internal API version, not the release. */ #define ZUPT_CODEC_RELEASE "2.65.3" diff --git a/install.sh b/install.sh index 88a8221..d7e22d5 100644 --- a/install.sh +++ b/install.sh @@ -6,7 +6,7 @@ set -Eeuo pipefail umask 077 -VERSION=${VERSION:-5.2.7} +VERSION=${VERSION:-5.2.8} PREFIX=${PREFIX:-/usr/local} echo "🔧 Installing ZUPT..." diff --git a/packaging/aur/PKGBUILD b/packaging/aur/PKGBUILD index 1f0e406..e833860 100644 --- a/packaging/aur/PKGBUILD +++ b/packaging/aur/PKGBUILD @@ -11,7 +11,7 @@ # Test locally with `makepkg -s` after the release archive is published. pkgname=zupt -pkgver=5.2.7 +pkgver=5.2.8 pkgrel=1 pkgdesc='Pure-C11 post-quantum backup compression utility (AES-256-CTR + HMAC-SHA256 + ML-KEM-768 + X25519)' arch=('x86_64') @@ -22,7 +22,7 @@ makedepends=('gcc' 'git' 'make') checkdepends=('python') source=("${pkgname}-${pkgver}.tar.gz::https://github.com/cristiancmoises/zupt/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz") -# Byte-reproducible upstream v5.2.7 source archive. +# Byte-reproducible upstream v5.2.8 source archive. sha256sums=('4db1badbb9a62676176829326b6fd4bab5fe67be6631a7f6d341bdc6c7265c04') build() { diff --git a/packaging/debian/changelog b/packaging/debian/changelog index fcc4b75..cbed093 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -1,3 +1,17 @@ +zupt (5.2.8-1) UNRELEASED; urgency=medium + + * Close CodeQL High path-race findings in SDK key publication, disk-restore + target handling, and benchmark workspace cleanup. + * Treat a filesystem refusal to create the macOS raw-C1 scanner fixture as + an explicit skip; reject redirected Windows prompts before _getch; and run + sdk-test in the release and hosted Linux gates. + * Preserve immutable, unpromoted v5.2.7 run 33445470664: 13 jobs succeeded, + macOS failed the raw-C1 fixture, and Windows was cancelled after the hosted + job stalled; a MinGW/Wine reproduction isolated redirected _getch entry. + Require fresh 5.2.8 evidence. + + -- Cristian Cezar Moisés Mon, 31 Aug 2026 23:30:00 +0000 + zupt (5.2.7-1) UNRELEASED; urgency=medium * Scope SHA-NI test helpers to supported x86 builds so macOS arm64 strict diff --git a/packaging/guix/zupt.scm b/packaging/guix/zupt.scm index 456451a..32e24ad 100644 --- a/packaging/guix/zupt.scm +++ b/packaging/guix/zupt.scm @@ -62,7 +62,7 @@ xcb-util-renderutil xcb-util-wm xcb-util-cursor libinput-minimal mtdev libevdev eudev)) -(define %zupt-version "5.2.7") +(define %zupt-version "5.2.8") (define %zupt-source (origin diff --git a/packaging/homebrew/zupt.rb b/packaging/homebrew/zupt.rb index 887bccc..bedf037 100644 --- a/packaging/homebrew/zupt.rb +++ b/packaging/homebrew/zupt.rb @@ -22,8 +22,8 @@ class Zupt < Formula desc "Post-quantum backup compression utility (ML-KEM-768 + AES-256-CTR + HMAC-SHA256)" homepage "https://github.com/cristiancmoises/zupt" - url "https://github.com/cristiancmoises/zupt/releases/download/v5.2.7/zupt-5.2.7.tar.gz" - version "5.2.7" + url "https://github.com/cristiancmoises/zupt/releases/download/v5.2.8/zupt-5.2.8.tar.gz" + version "5.2.8" sha256 "4db1badbb9a62676176829326b6fd4bab5fe67be6631a7f6d341bdc6c7265c04" license all_of: ["AGPL-3.0-or-later", "GPL-3.0-or-later", "BSD-2-Clause", "BSD-3-Clause", "CC0-1.0"] diff --git a/packaging/nix/flake.nix b/packaging/nix/flake.nix index 5ccfdbf..aba67e8 100644 --- a/packaging/nix/flake.nix +++ b/packaging/nix/flake.nix @@ -9,7 +9,7 @@ # nix flake check # lint the flake # # To consume from another flake: -# inputs.zupt.url = "github:cristiancmoises/zupt/v5.2.7"; +# inputs.zupt.url = "github:cristiancmoises/zupt/v5.2.8"; # ...packages.x86_64-linux.default = inputs.zupt.packages.x86_64-linux.zupt; # # `make dist` has its own reproducibility gate. This development flake has no @@ -30,7 +30,7 @@ zupt = pkgs.stdenv.mkDerivation { pname = "zupt"; - version = "5.2.7"; + version = "5.2.8"; # When publishing, replace this with `fetchurl` against the # release tarball. For local development the flake assumes it diff --git a/packaging/opensuse/README.md b/packaging/opensuse/README.md index c29f480..1236273 100644 --- a/packaging/opensuse/README.md +++ b/packaging/opensuse/README.md @@ -1,4 +1,4 @@ -# ZUPT 5.2.7 for openSUSE Build Service +# ZUPT 5.2.8 for openSUSE Build Service This directory is the upstream, source-only OBS recipe for ZUPT. It is a handoff for the downstream maintainer; its presence does not mean that the @@ -10,14 +10,14 @@ changes in this handoff. Alessandro de Oliveira Faria (Cabelo) is credited only as the openSUSE collaborator and downstream OBS package maintainer: he reviews the handoff, commits it through the portal/project he maintains, and may make the openSUSE-side adjustments he considers necessary. This role does not -attribute upstream code or the 5.2.2/5.2.3/5.2.4/5.2.5/5.2.6/5.2.7 upstream changes to -Cabelo. +attribute upstream code or the +5.2.2/5.2.3/5.2.4/5.2.5/5.2.6/5.2.7/5.2.8 upstream changes to Cabelo. ## Files and source policy | File | Purpose | |---|---| -| `_service` | Fetch the immutable `v5.2.7` tag and create `Source0` at build time. | +| `_service` | Fetch the immutable `v5.2.8` tag and create `Source0` at build time. | | `zupt.spec` | Build and test the CLI with optional external system integrations disabled. | | `zupt.changes` | openSUSE-format package history. | | `source-audit.sh` | Handoff wrapper for the repository scanner; run it from the complete handoff tree. | @@ -30,11 +30,11 @@ https://github.com/cristiancmoises/zupt.git ``` `obs_scm` stores an `.obscpio` plus `.obsinfo`. The `tar` and `recompress` -services reconstruct `zupt-5.2.7.tar.gz` inside the build environment, which +services reconstruct `zupt-5.2.8.tar.gz` inside the build environment, which matches `Source0` in the spec. This source policy does not prohibit separately built release-page packages. -The upstream 5.2.7 gates may publish the CLI source tarball, DEB, binary RPM, +The upstream 5.2.8 gates may publish the CLI source tarball, DEB, binary RPM, SRPM, notice-bearing Linux tar.xz, Windows ZIP, and macOS DMG, together with a GUI DEB, noarch RPM, GUI SRPM, and source-only portable GUI ZIP after each format-specific test succeeds. None of those files is an OBS `Source0` input @@ -139,7 +139,7 @@ reconstructed by the build-time services. Neither `%build` nor `%check` may access the network. For a source RPM check outside OBS, place the service-produced -`zupt-5.2.7.tar.gz` next to the spec and use a disposable RPM build tree: +`zupt-5.2.8.tar.gz` next to the spec and use a disposable RPM build tree: ```sh rpm_top=$(mktemp -d) @@ -167,7 +167,7 @@ unavailable rather than passing it. Earlier off-screen GUI smoke evidence is supporting evidence, not an exact-commit package result. Post-tag CI integration failures prevented 5.2.2 promotion. These historical -local results do not establish 5.2.7, native Windows or macOS success, hosted +local results do not establish 5.2.8, native Windows or macOS success, hosted GitHub CI/release promotion, authenticated OBS acceptance, or resolution of the automatic openSUSE `debugsource` rpmlint `no-binary` finding. The immutable 5.2.3 candidate was not promoted because its source-policy test assumed LF for @@ -194,7 +194,7 @@ This result establishes that the explicit tag revision works and isolates a release/test harness defect. It does not change the product, archive format, cryptography, codec, or SDK ABI; it does not make skipped native jobs pass or establish authenticated OBS/Factory acceptance. No v5.2.4 evidence transfers -automatically to v5.2.7. The exact v5.2.7 candidate must repeat every applicable +automatically to v5.2.8. The exact v5.2.8 candidate must repeat every applicable gate, and the automatic openSUSE `debugsource` rpmlint `no-binary` finding remains unresolved and unsuppressed. @@ -216,9 +216,23 @@ macOS arm64 SHA-NI test build treated unused x86-only helper declarations as errors under `-Werror`; Windows argv transcoding aborted the safe printable UTF-8 fixture before its intended path assertions. The 5.2.7 changes correct those test-harness boundaries without an archive-format, cryptographic, codec, -or SDK ABI change. They do not establish 5.2.7 hosted, native, OBS, or promotion +or SDK ABI change. They do not establish 5.2.8 hosted, native, OBS, or promotion evidence. +## Prior 5.2.7 exact-tag native-gate evidence + +The immutable v5.2.7 candidate was not promoted. Exact-tag GitHub Actions run +`33445470664` concluded `cancelled` at `2026-08-31T23:11:19Z`, with 13 +successful jobs, one failed macOS job, and one cancelled Windows job. macOS +rejected creation of the raw-C1 scanner fixture +with `EILSEQ`; the hosted Windows job stalled in `make check`, and a MinGW/Wine +reproduction isolated the cause to a redirected password prompt entering +`_getch`. Version 5.2.8 makes those test +boundaries fail or skip without hanging, addresses CodeQL High #5/#6/#7 in SDK +key publication, disk restore, and benchmark cleanup, and adds `sdk-test` to +release and hosted Linux gates. None of those changes establishes an exact +5.2.8 OBS, native, hosted-CI, or promotion result. + ## Prior openSUSE packaging validation The local results below were produced on 2026-08-24 from the 5.2.2 candidate @@ -256,11 +270,11 @@ gate. ## Handoff procedure for Alessandro/Cabelo 1. Upstream completes every applicable pre-tag source and local audit gate, - then creates and verifies the annotated `v5.2.7` tag. Exact-tag hosted, + then creates and verifies the annotated `v5.2.8` tag. Exact-tag hosted, native-platform, package, and promotion gates must pass before release or downstream handoff; the tag itself is never moved to repair a failure. 2. With Git, `file`, bsdtar, tar, zip, unzip and SHA-256 tools installed, run - `scripts/export-opensuse-package.sh v5.2.7`. Verify the reported ZIP and + `scripts/export-opensuse-package.sh v5.2.8`. Verify the reported ZIP and SHA-256 outside the Git index. The handoff includes both `packaging/opensuse/source-audit.sh` and its required `scripts/check-source-only.sh`; keep that relative layout while auditing. @@ -272,7 +286,7 @@ gate. ``` 4. From the extracted handoff root, run - `packaging/opensuse/source-audit.sh --archive /path/to/zupt-5.2.7.tar.gz`. + `packaging/opensuse/source-audit.sh --archive /path/to/zupt-5.2.8.tar.gz`. Then copy `_service`, `zupt.spec`, `zupt.changes` and `README.md` into the flat OBS package checkout. The audit wrapper is not an OBS build source and must not be copied without its companion `scripts/` directory. diff --git a/packaging/opensuse/_service b/packaging/opensuse/_service index 226388a..7fc42da 100644 --- a/packaging/opensuse/_service +++ b/packaging/opensuse/_service @@ -4,7 +4,7 @@ https://github.com/cristiancmoises/zupt.git git - refs/tags/v5.2.7 + refs/tags/v5.2.8 @PARENT_TAG@ ^v(.*)$ \1 diff --git a/packaging/opensuse/zupt.changes b/packaging/opensuse/zupt.changes index f73d7e7..476816b 100644 --- a/packaging/opensuse/zupt.changes +++ b/packaging/opensuse/zupt.changes @@ -1,3 +1,18 @@ +------------------------------------------------------------------- +Mon Aug 31 23:30:00 UTC 2026 - Cristian Cezar Moisés + +- Update to 5.2.8: + * Close CodeQL High path-race findings in SDK key publication, + descriptor-first disk restore, and benchmark workspace cleanup. + * Make the raw-C1 scanner fixture explicitly skip filesystems that reject + the byte with EILSEQ, reject redirected Windows prompts before _getch, and + add sdk-test to release/hosted Linux gates. + * Preserve immutable, unpromoted v5.2.7 run 33445470664: 13 jobs succeeded, + macOS failed the raw-C1 fixture, and Windows was cancelled after the hosted + job stalled; a MinGW/Wine reproduction isolated redirected _getch entry. + * Pin the OBS source service to the immutable v5.2.8 tag and require fresh + exact-candidate evidence before promotion. + ------------------------------------------------------------------- Mon Aug 31 23:00:00 UTC 2026 - Cristian Cezar Moisés diff --git a/packaging/opensuse/zupt.spec b/packaging/opensuse/zupt.spec index def34ff..f4a6573 100644 --- a/packaging/opensuse/zupt.spec +++ b/packaging/opensuse/zupt.spec @@ -18,7 +18,7 @@ # Name: zupt -Version: 5.2.7 +Version: 5.2.8 Release: 0 Summary: Backup compression with authenticated and post-quantum encryption License: AGPL-3.0-or-later AND GPL-3.0-or-later AND BSD-2-Clause AND BSD-3-Clause AND CC0-1.0 diff --git a/packaging/portable/README.txt b/packaging/portable/README.txt index 815f3aa..05b06ae 100644 --- a/packaging/portable/README.txt +++ b/packaging/portable/README.txt @@ -27,7 +27,7 @@ Requirements ------------ 1. Python 3.9 or newer. 2. PySide6 6.5 or newer, or a compatible PyQt6 package. - 3. ZUPT 5.2.7, installed as `zupt` on PATH or placed beside the launcher + 3. ZUPT 5.2.8, installed as `zupt` on PATH or placed beside the launcher (`zupt.exe` on Windows). A local command must have been built and tested independently; this bundle never downloads one. @@ -46,7 +46,7 @@ Troubleshooting --------------- * "requires PySide6 or PyQt6": install one Qt binding through your operating system package manager or another trusted, preconfigured Python source. - * "zupt not found": install ZUPT 5.2.7 or place its command beside + * "zupt not found": install ZUPT 5.2.8 or place its command beside the launcher. * Set ZUPT_DEBUG=1 to print command-discovery diagnostics to stderr. diff --git a/packaging/rpm/zupt.spec b/packaging/rpm/zupt.spec index 0feb67a..cdefc2a 100644 --- a/packaging/rpm/zupt.spec +++ b/packaging/rpm/zupt.spec @@ -20,7 +20,7 @@ # installed smoke test. Name: zupt -Version: 5.2.7 +Version: 5.2.8 Release: 1%{?dist} Summary: Backup compression with authenticated and post-quantum encryption @@ -101,6 +101,15 @@ comments. Plain archives use non-cryptographic checksums. %endif %changelog +* Mon Aug 31 2026 Cristian Cezar Moisés - 5.2.8-1 +- Close CodeQL High path-race findings in SDK key save, disk restore, and + benchmark cleanup; add the SDK gate, portable raw-C1 fixture handling, and + redirected Windows password-prompt rejection. +- Preserve immutable, unpromoted v5.2.7 run 33445470664: 13 jobs succeeded, + macOS failed the raw-C1 fixture, and Windows was cancelled after the hosted + job stalled; a MinGW/Wine reproduction isolated redirected _getch entry. +- Require fresh 5.2.8 gates. + * Mon Aug 31 2026 Cristian Cezar Moisés - 5.2.7-1 - Correct native test integration: scope SHA-NI helpers away from macOS arm64 and preserve safe UTF-8 fixture bytes across the Windows argv boundary. diff --git a/src/zupt_format.c b/src/zupt_format.c index ef54a6c..f127d98 100644 --- a/src/zupt_format.c +++ b/src/zupt_format.c @@ -4221,7 +4221,7 @@ static zupt_error_t open_archive(FILE *f, zupt_options_t *opts, * parser ignored block_type at this position and decoded whatever it * found — making the byte truly unauthenticated. Now it is structurally * validated (rejected at parse time on mismatch), which is the - * OPAQUE-class coverage promised by PROMPT.md §5. */ + * OPAQUE-class structural coverage recorded in the audit history. */ if (ib.block_type != ZUPT_BLOCK_INDEX) { free(ib.payload); return ZUPT_ERR_CORRUPT; diff --git a/tests/test_audit_flake.sh b/tests/test_audit_flake.sh index f6ce7ec..b48724a 100755 --- a/tests/test_audit_flake.sh +++ b/tests/test_audit_flake.sh @@ -2,7 +2,7 @@ # SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (c) 2025-2026 Cristian Cezar Moisés # -# Flake-stress harness — §3 of PROMPT.md. +# Repeated-suite flake-stress harness. # # Runs every short test suite N times (default 50) and aborts on the # first non-deterministic outcome. Specifically targeted at the audit @@ -21,7 +21,7 @@ set -u # F-02's repro needed 50 runs to be statistically convincing (~10% # baseline flake rate), but at 20 runs we still have ~88% chance of # catching a 10%-flake — fine for routine CI. For a hardened audit -# pass, invoke with 50 or 100 (see PROMPT.md §3). +# pass, invoke with 50 or 100 for a deeper audit run. N="${1:-20}" ZUPT_BIN="${ZUPT_BIN:-./zupt}"