Download Latest Version semlith-v0.51.1-x86_64-pc-windows-msvc.zip (24.5 MB)
Home / v0.46.0
Name Modified Size InfoDownloads / Week
Parent folder
install.ps1 2026-10-23 14.6 kB
install.sh 2026-10-23 12.0 kB
semlith-v0.46.0-aarch64-apple-darwin.tar.gz 2026-10-23 26.7 MB
semlith-v0.46.0-aarch64-apple-darwin.tar.gz.sig 2026-10-23 294 Bytes
semlith-v0.46.0-aarch64-unknown-linux-gnu.tar.gz 2026-10-23 26.4 MB
semlith-v0.46.0-aarch64-unknown-linux-gnu.tar.gz.sig 2026-10-23 294 Bytes
semlith-v0.46.0-x86_64-pc-windows-msvc.zip 2026-10-23 24.4 MB
semlith-v0.46.0-x86_64-pc-windows-msvc.zip.sig 2026-10-23 294 Bytes
semlith-v0.46.0-x86_64-unknown-linux-gnu.tar.gz 2026-10-23 27.6 MB
semlith-v0.46.0-x86_64-unknown-linux-gnu.tar.gz.sig 2026-10-23 294 Bytes
SHA256SUMS 2026-10-23 603 Bytes
SHA256SUMS.sig 2026-10-23 294 Bytes
README.md 2026-10-23 7.1 kB
Semlith 0.46.0 source code.tar.gz 2026-10-23 9.2 MB
Semlith 0.46.0 source code.zip 2026-10-23 9.5 MB
Totals: 15 Items   123.7 MB 0

The two security audits of 0.45.1 (2026-10-23) found nothing Critical or High. This release closes all eighteen of their findings, or records why one is accepted. Each fix comes with a test that fails on 0.45.1.

Security

  • Only a commit on main can become a signed release (SEC-001). Before, any pushed v* tag was built, signed with the project key, attested and published as Latest, so anyone who could push a branch and a tag could ship a release every installer accepted. The release workflow now refuses a tag whose commit main does not contain, before anything is built. Only an organisation admin can create a v* tag. The signing key lives in a release environment that only v* tags can deploy to.
  • Each release job holds one permission (SEC-007).
  • sign holds the key and no write token. attest holds the OIDC token. release writes the release and runs the one third-party action.
  • Tag builds use --locked with no build cache.
  • Checkouts drop their credentials.
  • Latest moves only to the highest version released.
  • The shared-library and glibc gates fail on empty readelf or objdump output instead of passing.
  • The packs workflow builds with a read-only token and publishes in a separate job that runs no third-party code.
  • The installers check who built a release, and refuse an old one (SEC-007, SEC-015). install.sh and install.ps1 ask gh for an attestation signed by release.yml for the tag being installed. They refuse a resolved latest older than v0.46.0, and any tag that is not a whole vMAJOR.MINOR.PATCH. install.sh refuses busybox wget. install.ps1 runs in one script block, so irm | iex leaves nothing in the caller's session, and it restores the process-wide TLS setting afterwards.
  • semlith add never fetches through a proxy (SEC-003). ureq read ALL_PROXY, HTTPS_PROXY and HTTP_PROXY. Through a proxy, the proxy resolves the name, so the private-address guard checked only the proxy's address. A failed fetch now names any proxy variable that is set. 198.18.0.0/15, 192.0.0.0/24, 192.88.99.0/24 and fec0::/10 are private (SEC-009).
  • semlith upgrade unpacks the bytes it checked (SEC-004, SEC-014). It used to write the checked archive out and open it again, in a work directory that might already exist. It now unpacks from memory into a directory it has just created, owner-only. Both archive readers refuse an entry with a colon (a Windows drive-relative path or alternate data stream) or a Windows device name.
  • Packs and the embedding model are used as they were checked (SEC-004). A pack is extracted from the bytes that matched its digest. A bare-version stamp from before 0.41.0 no longer counts as installed. The embedding model's files are checked against their pinned digests once per process, as they are loaded.
  • On macOS, a native parser cannot grow past its worker's memory limit (the second audit's Medium). Darwin refuses a lower RLIMIT_AS, so the limit used to cover only Rust's allocations, and the deadline bounded the rest. The daemon now reads each worker's memory footprint every 25 ms and ends one that passes its idle footprint plus the limit. The file is refused with the peak and the cap, and the next file parses. A poll can overshoot by what a parse allocates in 25 ms, about 13 MiB on an M1. A worker that has already read other files gets the file once more on a fresh worker before it is refused, because malloc keeps what earlier files freed.
  • Isolation headers (SEC-015). Every portal response sends Permissions-Policy, Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Resource-Policy: same-origin.
  • Every lockfile is audited (SEC-010, SEC-011, SEC-013, SEC-016).
  • cargo deny checks every feature's dependency graph (the Linux release builds with dynamic-ort), and denies yanked crates and wildcard requirements.
  • The fuzz harness's lockfile moves to rustls-webpki 0.103.16, webpki-roots 1.0.11 and zip 9.0.5.
  • The Core ML pack installs a lock with every package pinned by hash, and CI audits it beside both Cargo lockfiles.
  • ttf-parser and paste stay unmaintained with no replacement upstream, so their ignores carry today's reasons. ttf-parser reads only fonts semlith picks for its own PDF reports. lopdf calls it only to write a PDF, never when an indexed PDF is read. The font readers that do see indexed PDFs run in the parse worker. tests/parse_pdf.rs indexes a PDF whose embedded Type 1 font overflows its reader's stack, and one whose CFF font panics. The first is refused as a crash, the second as having no text, and the daemon stays up.
  • A secret scan gates every push (SEC-002). gitleaks runs over the tree, with a rule for crates.io tokens. Publishing has gone through Trusted Publishing since 0.41.0, and the stale local token is gone.

Changed

  • CI decides more carefully what is prose (SEC-005, SEC-006). changes.sh used to treat the agent rules, skill and clients guide that semlith setup writes into users' clients as prose, because they live under docs/. It now treats them as code. A rename counts as both of its paths. A previous head is trusted only if its run, on the same branch, ran the heavy lanes green. Self-tests cover it and the new tag check.
  • The bug hunt in native-smoke.yml reads its own budget-capped ANTHROPIC_BUGHUNT_KEY and skips without it. Its tools are installed at pinned versions.

Accepted

  • A process running as you that writes the model cache while the daemon runs could change an unpacked pack's files, or the model graph ONNX Runtime opens by path, after the check. Such a process can already replace the binary. docs/security.md says so (SEC-004).
  • Two expired confidential-VM attestation tokens remain in the history behind the v0.37.0-rc.5 and rc.6 tags, which the tag ruleset keeps immutable. They grant nothing (SEC-012).

Install

macOS and Linux

:::sh
curl --proto '=https' --tlsv1.2 -fsSL https://raw.githubusercontent.com/semlith/semlith/main/install.sh | sh

Windows

:::powershell
irm https://raw.githubusercontent.com/semlith/semlith/main/install.ps1 | iex

Or download the archive for your platform below, unpack it, and put semlith on your PATH. Intel macOS has no prebuilt binary: ONNX Runtime no longer publishes x86_64 macOS builds.

Verify a download against SHA256SUMS before running it, SHA256SUMS against its signature (release key SHA256:a5oJmrakIwDHEWTDWqWe51Ttt6m2tQ0dsGzIqyxDuxs) with echo "semlith-release ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICMTHiHMzeSHzzc+8UDZHUzJcvb6XGUBb+TJdFes91xm" > allowed_signers and ssh-keygen -Y verify -f allowed_signers -I semlith-release -n file -s SHA256SUMS.sig < SHA256SUMS, and its provenance with gh attestation verify <file> --repo semlith/semlith --signer-workflow semlith/semlith/.github/workflows/release.yml.

Source: README.md, updated 2026-10-23