Skip to content

ken v1.1.0 — security hardening + int8 reranker by default

Choose a tag to compare

@github-actions github-actions released this 12 Jun 01:34

A feature-and-hardening release. The int8 reranker becomes the default now that it's free, output: "json" reaches the last tool, the remote-clone path closes its two known SSRF gaps, and a govulncheck gate joins CI.

No breaking changes. mcp.Run / mcp.NewServer / the chunk.Chunker interface and the MCP wire format are unchanged from 1.0. The int8 default and the new KEN_MAX_CLONE_BYTES knob are both backward-compatible — existing configs keep working.

Highlights

⚡ int8 reranker is now the default

aikit v1.5.0 fixed the q8 path, so int8 now matches f32 reranker latency (50-doc cold: 7.35 s vs 7.75 s on arm64) at ~21× less runtime memory (18 MiB vs 379 MiB) and ¼ the weight footprint (~140 MB resident vs ~547 MB) — with cosine 0.997 vs f32, unchanged ranking quality. KEN_MCP_RERANK_QUANT and --rerank-quant now default to int8; pass f32 for the full-precision path. No re-download needed — LoadQ8 quantizes your existing CodeRankEmbed snapshot in-process.

This reverses the "int8 is slower on Apple Silicon" note from 1.0.1 — that was the pre-fix aikit path.

🧩 All nine MCP tools now speak JSON

recently_changed was the last markdown-only tool; it now accepts output: "json" and returns a typed RecentlyChangedResponse (considered-count + per-commit hash / short_hash / subject / author / RFC3339 timestamp / changed_files), built from the same rows as the markdown render so the two can't drift.

🔒 Security

  • Clone SSRF guard hardened + a byte cap. ken-mcp's remote-repo clone now re-validates the resolved IP at connect time and dials it literally (TLS still verifies the hostname via SNI) — closing the DNS-rebinding TOCTOU the pre-flight check couldn't catch, including redirects to internal hosts. It also byte-caps the clone stream (KEN_MAX_CLONE_BYTES, default 2 GiB) so a hostile server can't stream an unbounded/pathological pack. Both checks honor KEN_ALLOW_PRIVATE_CLONE_TARGETS=1.
  • govulncheck CI gate. Go's symbol-level vulnerability scanner now runs on every push. Bringing it green fixed 9 reachable CVEs (bumped golang.org/x/crypto to v0.52.0 and the toolchain to go 1.26.4). The gate blocks any reachable-CVE regression from landing.

🐛 Fixed

  • Data race in the definition-pattern cache. internal/search's defPatternCache (the compiled-regex memo behind the definition tool) was read and written unsynchronized; concurrent queries could race it. Now guarded by an RWMutex, with a race-detector regression test.

📚 Docs & tooling

New top-level CONTRIBUTING.md and SECURITY.md, a Makefile, a "Compared to other agent code-search tools" table in the README, and a "Personally-namespaced dependencies" section in DEVELOPERS.md documenting the gotreesitter dependency delta and the go.work local-aikit workflow.

Install / upgrade

# Homebrew (macOS/Linux) — ken ships as a cask
brew upgrade --cask ken     # new install: brew install --cask townsendmerino/tap/ken
# Windows (Scoop)
scoop update ken            # new install: scoop bucket add townsendmerino https://github.com/townsendmerino/scoop-bucket; scoop install ken
# Or with Go
go install github.com/townsendmerino/ken/cmd/ken@v1.1.0
go install github.com/townsendmerino/ken/cmd/ken-mcp@v1.1.0

No config changes are required to upgrade. If you run the reranker (KEN_MCP_RERANK=on) and want to keep the full-precision path, set KEN_MCP_RERANK_QUANT=f32.

Full changelog: CHANGELOG.md · compare v1.0.1...v1.1.0