Skip to content

v1.10.0

Choose a tag to compare

@github-actions github-actions released this 18 Jul 15:56

A hardening + maintenance release. The centerpiece is a security-focused code
review swept across the untrusted-input boundary
— aikit is the parser layer
the ecosystem routes every hostile GGUF/safetensors byte and every persisted
index through. Alongside the fixes: two additive API surfaces, real allocation
and throughput wins, arm64 now gated in CI, and a toolchain/dependency refresh.

No Hard-tier API breakage. Everything here is additive or behavioral; the
changed kernels stay bit-identical, pinned by the exact-equality parity gates.
Safe drop-in upgrade from 1.9.0.

Highlights

  • 🔒 Untrusted-input boundary hardened. A crafted or merely-mismatched model
    file / persisted index could previously cause a path-traversal read, an
    uncatchable crash (stack exhaustion, worker-goroutine panic), a ~250 GB
    over-allocation, a SIGBUS/checkptr throw from an unaligned unsafe cast, or
    a use-after-munmap segfault. All closed — see Security below.
  • New API (additive). linalg.MatmulBTW4A8Into — a zero-alloc int4 decode
    matmul (0 allocs/op steady-state, the int4 twin of MatmulBTW8A8Into) — and
    Close() on Model / BERT / CrossEncoder / SPLADE for deterministic
    release of mmapped weights instead of waiting on a GC finalizer.
  • Perf. BERT/SPLADE/CrossEncoder attention now runs through the pooled
    scratch arena: 432 → 3 allocs per forward, and a lone forward parallelizes
    instead of running single-threaded. MatmulBTQ8 widens each weight row once
    (was M times) at prefill.
  • 🧪 arm64 in CI. The NEON asm and the bit-identity gates (M-/width-invariance,
    packed-path identity) now run on a real ubuntu-24.04-arm runner — an
    arm64-only regression can no longer ship green. Plus staticcheck via
    golangci-lint (54 findings → 0).

Upgrade notes

  • Version is a MINOR bump for the additive API above. Existing callers need no
    changes.
  • Behavioral hardening you might notice: several parsers/loaders now return a
    clean ErrFormat (or a recoverable, caller-side panic) where a malformed input
    previously slipped through or crashed deep in a kernel. DotI8 now panics on a
    length mismatch (it read out of bounds before). Vision loaders validate tensor
    shapes and config at load. None of this affects well-formed input.
  • chunk/treesitter bumped gotreesitter 0.20.2 → 0.40.0. Its exact chunk
    boundaries are best-effort (ADR-010), so a few may shift on real code; the
    load-bearing contracts (byte-fidelity, AST-meaningful boundaries) are gated and
    hold. The pure-Go core is unaffected — this is isolated to the quarantined
    submodule.
  • Toolchain moved to Go 1.26.5; golang.org/x/text 0.37→0.40, x/sys 0.45→0.47.

The full categorized changelog (Added / Changed / Fixed / Security, with the
per-finding detail) is in
CHANGELOG.md → 1.10.0.

Security (the untrusted-input boundary)

  • safetensors sharded load — path traversal. Shard names from the untrusted
    index JSON were joined to the model dir; "../../../etc/passwd" mmap'd a file
    outside the bundle. Rejected as ErrFormat.
  • safetensors header — no shape × dtype cross-check. A giant shape with a
    tiny byte range parsed, then panicked at inference. Now requires overflow-safe
    ∏shape · dtypeSize == byteRange.
  • safetensors typed accessors — no alignment check. The unsafe reinterpret
    cast assumed alignment the format doesn't guarantee (a -race/checkptr throw,
    SIGBUS on strict-alignment ports). Zero-copy when aligned, byte-copy otherwise.
  • GGUF metadata — unbounded array-of-array recursion. Millions of frames past
    the goroutine-stack limit → unrecoverable abort. Depth capped at 128.
  • HNSW load — missing product allocation guard. The f32 branch clamped
    ndocs/dim individually but not their product (~250 GB attempt). Guarded.
  • mmap lifetime — use-after-unmap. Three zero-copy accessors could be
    munmap'd mid-read → SIGSEGV. runtime.KeepAlive backstops added.
  • Unrecoverable matmul panics. A shape violation above the parallel threshold
    panicked on a worker goroutine (uncatchable). Validation now runs before the
    fan-out; constructors reject negative dims / overflow.