Skip to content

docs: threat model + pre-publish security hardening#70

Merged
project-navi-bot merged 6 commits into
mainfrom
docs/threat-model
May 26, 2026
Merged

docs: threat model + pre-publish security hardening#70
project-navi-bot merged 6 commits into
mainfrom
docs/threat-model

Conversation

@Fieldnote-Echo

@Fieldnote-Echo Fieldnote-Echo commented May 26, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the maintained threat model and lands the tight pre-publish hardening
that lets it claim a closed state rather than a wishlist.

Threat model (THREAT_MODEL.md)

Attack-surface analysis scoped to what ordvec actually is (a pure compute
library — no network/auth/secrets/multi-tenancy), covering deserialization,
unsafe SIMD, the Python FFI boundary, the supply chain, and query/resource
exhaustion. Every code-level claim was verified against the tree. Clear
library-owned vs deployment-owned split; corpus-poisoning kept qualitative and
ordvec-specific (ordinal rank inversion, top-n_top overlap, RankQuant
boundary) with one established reference (PoisonedRAG) — no unverifiable
percentages.

Hardening landed here

  • #![deny(unsafe_op_in_unsafe_fn)] in fastscan.rs + explicit unsafe {}
    around the AVX-512 kernel (THREAT-SIMD-001). No behaviour change.
  • fastscan_b2 fuzz target — the FastScan b=2 scan path was the one
    unsafe-heavy kernel no existing target reached (THREAT-FUZZ-001, closed).
  • RELEASING.md + docs/INDEX_PROVENANCE.md; threat model linked from
    SECURITY.md.

Verified release posture (no code change needed)

crates.io (yank-only) + PyPI (version-burn) are immutable by construction; both
release workflows already emit SLSA build provenance fail-closed + PyPI PEP 740.
Release environments now require maintainer approval and are restricted to main.

Test plan

Full local gate, all green:

  • cargo fmt --all --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test + --features experimental + --no-default-features
  • cargo +1.89.0 build (MSRV) · cargo build --locked · RUSTFLAGS=-D warnings cargo build
  • cargo +nightly fuzz build (all 7 targets)

A deep multi-hour fork-mode fuzz campaign across all targets is being run
separately before publish.

Open follow-ups (tracked in the threat model)

  • v* tag-protection ruleset + a basic main ruleset (GitHub settings).
  • Roll the unsafe lint out crate-wide to the other SIMD modules.
  • Bounded weekly CI fuzz smoke job (THREAT-FUZZ-002).
  • Second maintainer/owner (OpenSSF) — then a release wait timer becomes meaningful.

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Threat model, release controls, and FastScan kernel hardening

✨ Enhancement 🧪 Tests 📝 Documentation

Grey Divider

Walkthroughs

Description
• Add comprehensive threat model and release controls documentation
• Enforce unsafe-operation visibility in FastScan AVX-512 kernel via lint
• Add fuzzing target for FastScan b=2 compute path (previously unfuzzed)
• Document index-file provenance guarantees and validation scope
Diagram
flowchart LR
  A["Threat Model Analysis"] --> B["THREAT_MODEL.md"]
  C["Release Pipeline Controls"] --> D["RELEASING.md"]
  E["Index Provenance Docs"] --> F["docs/INDEX_PROVENANCE.md"]
  G["FastScan Kernel Hardening"] --> H["unsafe_op_in_unsafe_fn lint"]
  I["Fuzzing Coverage Gap"] --> J["fastscan_b2 fuzz target"]
  H --> K["src/fastscan.rs"]
  J --> L["fuzz/fuzz_targets/fastscan_b2.rs"]
  B --> M["Security Posture"]
  D --> M
  F --> M
  K --> M
  L --> M

Loading

File Changes

1. THREAT_MODEL.md 📝 Documentation +450/-0

Verified attack-surface analysis with residual tracking

• Comprehensive attack-surface analysis with library-owned vs deployment-owned split
• Threat register documenting 18 threats across deserialization, SIMD, FFI, supply chain, and
 resource exhaustion
• Existing defenses verified (parser hardening, OIDC/SLSA controls, unsafe-kernel invariants)
• Open mitigations tracked (tag rulesets, crate-wide unsafe lint rollout, CI fuzz smoke job)
• References to PoisonedRAG, OWASP LLM08:2025, and GitHub security best practices

THREAT_MODEL.md


2. RELEASING.md 📝 Documentation +69/-0

Release workflow controls and dispatch-only publish

• Release pipeline controls: workflow_dispatch-only, required-reviewer approval, main-only
 deployment
• OIDC trusted publishing and SLSA build provenance before publish
• Environment protection via repo settings (not code)
• Checklist for coordinated crate/wheel/Zenodo releases
• Publish held; CI runs dry-run only

RELEASING.md


3. docs/INDEX_PROVENANCE.md 📝 Documentation +55/-0

Index-file validation scope and provenance guidance

• Documents what loaders validate: structure, not origin or truth
• Lists structural invariants (permutation, composition, popcount checks)
• Clarifies that semantically poisoned but structurally valid indexes pass all checks
• Guidance for deployments: checksum manifests, artifact-store integrity, Sigstore attestations
• Notes that sidecar verifier can be added later without format change

docs/INDEX_PROVENANCE.md


View more (4)
4. SECURITY.md 📝 Documentation +9/-1

Expanded security reporting scope and threat model link

• Expanded welcome categories to include unsafe SIMD kernels, Python FFI, and release pipeline
 reports
• Added link to THREAT_MODEL.md for full attack-surface analysis
• Clarified that loaders are fuzzed and parsing-robustness reports are especially welcome

SECURITY.md


5. src/fastscan.rs ✨ Enhancement +92/-79

Enforce explicit unsafe blocks in FastScan kernel

• Added #![deny(unsafe_op_in_unsafe_fn)] to enforce explicit unsafe {} blocks
• Wrapped entire AVX-512 kernel loop in explicit unsafe {} block with SAFETY comment
• No behavior change; defense-in-depth to keep unsafe surface visible to future refactors
• Addresses THREAT-SIMD-001; crate-wide rollout to other SIMD modules tracked separately

src/fastscan.rs


6. fuzz/fuzz_targets/fastscan_b2.rs 🧪 Tests +52/-0

Add FastScan b=2 fuzzing target for kernel coverage

• New libFuzzer target for RankQuantFastscan (pack_fastscan_b2 + search_asymmetric_fastscan_b2)
• Exercises the one unsafe-heavy scan path not reached by search_rankquant target
• Fixed dim=64, varies doc count (1..=100, crossing 32-doc block boundary), embedding/query
 values, and k
• Drives scalar reference kernel on non-AVX-512 CI; AVX-512 kernel under Intel SDE
• Closes THREAT-FUZZ-001

fuzz/fuzz_targets/fastscan_b2.rs


7. fuzz/Cargo.toml ⚙️ Configuration changes +9/-0

Register fastscan_b2 fuzz target in Cargo manifest

• Added fastscan_b2 binary target pointing to new fuzz_targets/fastscan_b2.rs
• Configured as test=false, doc=false, bench=false per fuzz-target convention

fuzz/Cargo.toml


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented May 26, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Qodo Logo

@codecov

codecov Bot commented May 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 42 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/fastscan.rs 0.00% 42 Missing ⚠️

📢 Thoughts on this report? Let us know!

Add #![deny(unsafe_op_in_unsafe_fn)] to fastscan.rs and wrap the AVX-512 FastScan kernel's raw loads/stores and intrinsics in an explicit unsafe block. No behavior change. Keeps the kernel's unsafe surface explicit so a future refactor cannot silently lean on the fn-level unsafe. Defense-in-depth for THREAT-SIMD-001; crate-wide rollout to the other SIMD modules tracked as a follow-up.

Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
RankQuantFastscan (pack_fastscan_b2 + search_asymmetric_fastscan_b2 + the scalar/AVX-512 kernel) is the one unsafe-heavy scan path the search_rankquant target does not reach. The new target drives it through the public API, crossing the 32-doc block boundary to exercise tail-padding. Closes THREAT-FUZZ-001. fuzz/Cargo.lock synced (ordered-float 4.6 to 5.3) to match the core crate's current pin; not a new dependency.

Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
THREAT_MODEL.md: verified attack-surface analysis with a library-owned vs deployment-owned split and an honest residual list; deployment poisoning kept qualitative and ordvec-specific. RELEASING.md: dispatch-only + required-reviewer + main-only + OIDC/SLSA/PEP-740 controls and the publish-hold. docs/INDEX_PROVENANCE.md: loaders validate structure, not origin. Links the threat model from SECURITY.md and broadens the welcomed-report categories.

Signed-off-by: Nelson Spence <nelson@projectnavi.ai>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces comprehensive security documentation, including a threat model (THREAT_MODEL.md), index file provenance details (docs/INDEX_PROVENANCE.md), and release guidelines (RELEASING.md). It also hardens the AVX-512 FastScan kernel in src/fastscan.rs by enforcing #![deny(unsafe_op_in_unsafe_fn)] and wrapping unsafe operations in explicit blocks. Additionally, a new fuzz target fastscan_b2 is added to cover the FastScan compute path. The reviewer suggested moving the macro_rules! step definition outside of the for loop body in src/fastscan.rs to make the code more idiomatic and readable.

Comment thread src/fastscan.rs
…or 78%

Codecov had no config, so its default patch status fired on this PR: the unsafe_op_in_unsafe_fn wrap re-indented ~80 lines of the AVX-512 FastScan kernel, which the no-AVX-512 coverage runner never executes — a false patch signal (those kernels run under Intel SDE; see #68). Make patch informational (advisory) and pin the project status to the same 78% floor coverage.yml enforces via --fail-under-lines; real coverage gating stays in the workflow. Ignore the separate fuzz/ workspace.

Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
…loop

Address Gemini review: define macro_rules! step once before the inner loops instead of inside the 4-wide unroll, and reuse it in the remainder loop (removing a duplicated ~10-line intrinsic body). Pure code motion — step!(0) expands to exactly the old remainder body. No behaviour change; verified on real AVX-512 (the fastscan_b2_top10_matches_avx512_kernel equivalence test passes on a Zen5 host). Note: macro_rules expands at compile time, so the prior in-loop placement had no runtime cost — this is readability only.

Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
Review polish: RELEASING.md says 'PyPI publish' (the wheel is built by maturin but published via the PyPI Trusted Publishing action, not 'maturin publish'). THREAT_MODEL.md says 'covered by cargo-fuzz targets' instead of 'continuously fuzzed', which could be misread as CI-continuous fuzzing (fuzzing is manual; THREAT-FUZZ-002 tracks a CI smoke job).

Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
@project-navi-bot project-navi-bot merged commit c1a6c59 into main May 26, 2026
28 checks passed
@project-navi-bot project-navi-bot deleted the docs/threat-model branch May 26, 2026 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants