Releasing

Release pipeline

The release process is automated via reusable workflows from kdeldycke/repomatic. A push to main triggers the release.yaml workflow, which produces:

All release artifacts are signed with GitHub Artifact Attestations providing SLSA v1 provenance.

The release PR must be merged via “Rebase and merge” (never squash). See the repomatic-release skill for the full mechanics.

Chocolatey

The Chocolatey package definition is maintained in-tree at packaging/choco/meta-package-manager/, but is no longer pushed to the Chocolatey community repository (see Impact on Chocolatey for the rejection rationale). The automated chocolatey job has been removed from release.yaml; only the in-tree nuspec remains, so users can build and install locally (see install.md) and the choco-source job in tests-install.yaml keeps the build instructions exercised.

The package directory name must match the nuspec basename: this is enforced by Chocolatey-AU’s AUPackage, which derives the nuspec path from Split-Path -Leaf $pwd.

Guix

The Guix package definition is maintained in-tree at packaging/guix/. The guix job in release.yaml runs after the main release, fetches the PyPI sdist SHA256, converts it to Nix-style base32, and updates the .scm file. Since Guix packages live on Codeberg and require reviewed PRs, the job only opens a PR to this repository with the updated definition, which can then be pushed to the upstream PR at guix/guix#8047.

Nix

The Nix package definition is maintained in-tree at packaging/nix/ while NixOS/nixpkgs#506145 is pending review. The nix job in release.yaml runs after the main release, computes the SRI hash of the GitHub source tarball using nix-prefetch-url, and updates package.nix. The job opens a PR to this repository with the updated definition, which can then be pushed to the nixpkgs PR branch.

Two dependencies (click-extra and extra-platforms) are also bundled in packaging/nix/ since they are not yet in nixpkgs. A default.nix wrapper overlays them into the Python package set, and a flake.nix provides flake-based access. Once the nixpkgs PR lands, the overlay and bundled dependencies become unnecessary.

Antivirus false positives on Windows binaries

Nuitka --onefile Windows x64 binaries are systematically flagged by antivirus engines on VirusTotal. This is a structural issue with the Nuitka compilation model, not a sign of actual malware.

Why it happens

Nuitka --onefile creates a self-extracting archive that decompresses an embedded Python runtime to a temporary directory and executes it at launch. This “drop and execute from temp” pattern is behaviorally identical to trojan droppers, which triggers heuristic and ML-based detections.

Additional factors:

  • Nuitka is popular with malware authors for source code protection, which poisons AV heuristics for all Nuitka-compiled binaries.

  • mpm invokes external system commands (package managers), triggering behavioral rules for command-and-control activity.

  • Microsoft has gone as far as suspending an Artifact Signing account over Nuitka onefile binaries.

Typical detection profile

Based on the v6.2.1 release (scanned 2026-04-10):

Platform

Detection rate

VT reports

Notes

Linux x64

0/62

Clean

Linux ARM64

0/60

Clean

macOS x64

0-1/63

Occasional ML false positive

macOS ARM64

2/55-60

meta-package-manager, mpm

Cynet, Microsoft ML, Avast/AVG

Windows ARM64

1/68-70

meta-package-manager, mpm

Fewer ARM64 heuristics in AV engines

Windows x64

33-35/70

meta-package-manager, mpm

Heavily flagged by heuristic/ML engines

.whl / .tar.gz

0/56-63

Clean (Python source, no Nuitka)

The Windows x64 detections come from generic signatures like Gen:Variant.Application.tedy (BitDefender family), Trojan:Win32/Sabsik (Microsoft), Python/Packed.Nuitka.AL (ESET), and various ML-based classifiers.

Submitting false positive reports

After each release, if VirusTotal detections are high, submit false positive reports to the major vendors. Priority order by impact:

  1. Microsoft (https://www.microsoft.com/en-us/wdsi/filesubmission): most influential engine. Covers Sabsik, Wacatac detections. Turnaround: 1-2 business days.

  2. BitDefender (https://www.bitdefender.com/submit/): their engine powers ~6 downstream vendors (ALYac, Arcabit, Emsisoft, GData, MicroWorld-eScan, VIPRE). Fixing BitDefender removes the most detections per submission.

  3. ESET (email samples@eset.com, files in password-protected ZIP with password infected): covers Python/Packed.Nuitka.AL. Turnaround: 1-3 business days.

  4. Symantec (https://symsubmit.symantec.com/false_positive): covers ML.Attribute.HighConfidence. ML-based detections may take longer (3-7 business days).

  5. Avast/AVG (https://www.avast.com/submit-a-sample): shared engine, one submission covers both. Covers Win64:Malware-gen.

  6. Sophos (https://support.sophos.com/support/s/filesubmission): covers Generic Reputation PUA. PUA submissions require justification of the software’s legitimate purpose. Turnaround: up to 15 business days.

A complete list of vendor FP contacts is maintained by VirusTotal and False-Positive-Center.

Impact on Chocolatey

Chocolatey’s moderation pipeline rejects any package flagged by more than 10 antivirus engines on VirusTotal (chocolatey/home#395). The Windows x64 binary sits at 33-35/70 detections, well above that threshold, so submission 6.4.2 was rejected and automated publishing to the community repository has been removed from release.yaml. Reaching the cutoff would require either lowering the detection count through false-positive submissions (a moving target) or applying one of the long-term mitigations below.

Long-term mitigations

  • Code signing with an EV certificate would reduce heuristic detections across the board, especially from Microsoft and Symantec ML models.

  • Switching from --onefile to --standalone would eliminate the self-extracting pattern entirely, at the cost of distributing a directory instead of a single .exe.

  • Nuitka Commercial (https://nuitka.net/doc/commercial.html) claims proprietary AV-mitigation techniques but offers no guarantees.

References