RuvNet Brain runs on your machine, downloads a knowledge bundle, and (with your consent) can update itself — so we take reports seriously and fix them in the open. This policy exists because the project's first security review was a private, responsible disclosure; the next reporter should have a clear path.
Please do not open a public issue for a security problem. Instead:
- Use GitHub's private vulnerability reporting (Security tab → "Report a vulnerability"), or
- Email the maintainer at the address on the GitHub profile.
Include: what you found, a file:line or reproduction, the impact, and (if you have one) a suggested fix.
"Confirmed" reports — where you ran the exact command or read the exact line — are the most actionable.
- We verify every report against the real code before acting (we do not dismiss, and we do not rubber-stamp). Fixes are proven with a real command before they're called done.
- Each finding is tracked with a
file:lineroot cause, the exact fix, and its verification — seedocs/adr/0010-security-hardening-sec-0010.mdfor the format (that ADR is the record of the first review). - We credit reporters unless you ask us not to.
- The knowledge bundle is Ed25519-signed with transitional enforcement.
scripts/sign-bundle.mjsemits a detached<zip>.sig(over the bundle's SHA-256) plus<zip>.sha256, and the installer verifies it before extracting, against an Ed25519 public key embedded inbin/install.mjsso the trust root travels with the installer code (an attacker who swaps the bundle can't also swap the key). A signature that is present but invalid always fails closed — the download is deleted and extraction refused. A missing signature currently warns and proceeds (SIGNING_REQUIRED = false) so releases predating signing still install; this flips to hard-required once every release is signed. The unattended code-overwrite path remains disabled (updates detect-and-notify, they do not auto-apply executable files). - Model weights download from HuggingFace on first run only when not already cached, and are now
pinned to exact commit SHAs (no longer the floating
mainbranch) so the weights — and therefore every embedding — cannot silently change under an upstream re-publish. See Model & data provenance below. - The grounding hooks are POSIX shell — on native Windows without WSL/Git-Bash they don't fire (the
search_ruvnettool still works).
The brain's answers are only as trustworthy as the weights that produce its embeddings, so those are pinned and loaded locally:
- Embedding models (pinned by exact HuggingFace commit SHA, quantized ONNX):
Xenova/all-MiniLM-L6-v2— 384-dim, the default query embedder and the small build (kb/forge-ask.mjs,kb/forge-build.mjs) — pinned at751bff37182d3f1213fa05d7196b954e230abad9.Xenova/bge-base-en-v1.5— 768-dim, the sharper big build (kb/forge-big.mjs, and the query side ofkb/forge-ask.mjswhen a big bundle is present) — pinned at4d6cd88e18e51a5e020c2c305726d76ada9c03cf.Xenova/ms-marco-MiniLM-L-6-v2— cross-encoder reranker (kb/forge-rerank.mjs) — pinned ata09144355adeed5f58c8ed011d209bf8ee5a1fecwhen the default model is used (an operatorCE_MODELoverride falls back tomain).
- Weights load from a local ONNX cache, not the network by default. The loader
(
@xenova/transformersv2.17.2) points at a local model cache (KB_MODEL_CACHE, else akb/-localmodels-cache) and permits a remote HuggingFace fetch only when that specific model is not already cached. Once cached it is fully offline. The cache lookup is revision-agnostic, so pinning a SHA never forces a re-download of an already-present model — it only makes the first fetch on a fresh machine deterministic. - Pin vs. package version are independent. The pinned SHA fixes the weights; the
@xenova/transformersnpm version (bumped via Dependabot) fixes the loader code. A loader upgrade never changes the pinned weights — review such updates for API compatibility with the pinned revisions. - Bundle integrity is covered by the Ed25519 signing posture described above (signed
.sig+.sha256, public key embedded in the installer, verify-before-extract, invalid-signature fail-closed).
Active development is on main; fixes land there first and flow to users via the plugin's update path.
The exact current version is on the badge at the top of the README.