Ctrl K
ComunidadGuías…

SECURITY_AUDIT.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Security engineering review

Date: 2026-08-13
Baseline: `75f840e`
Scope: privacy runtime, provider Adapters/transports, vault/conversations, output/streaming, media,
configuration, logs/metrics, deployment, dependencies, CI, and repository hygiene.

This is an internal engineering review of an educational project, not a penetration test,
certification, or legal compliance assessment.

## Verified findings addressed

### Reversible surrogate collision (P0)

Finite surrogate lists wrapped and could map different originals to the same replacement. Surrogate
generation is now unique and the vault enforces a bijection. Collision and repeated-generation tests
cover the invariant.

### Encoded, numeric, and post-Adapter wire bypasses (P0)

Recursive pre-Adapter masking alone could not guarantee the actual provider body. The final guard
now checks Adapter output, encoded views, nested JSON, token provenance, object keys, and numeric
field registries. Built-in transports accept sealed checked bytes. OpenAI and Gemini
`httpx.MockTransport` tests assert the exact sent body.

### Opaque DOCX content (P0)

Unknown OPC parts could preserve hidden data. DOCX uses a reviewed allowlist and rejects media,
embeds, macros, unknown opaque parts, duplicate entries, external relationships, and archive limit
violations.

### Token collision, injection, and metadata leakage (P1)

Default tokens now carry 128 random bits, no type, and no counter. Reserved token grammar in client
input blocks before provider access. Semantic placeholders are an explicit compatibility mode.

### Streaming and output gaps (P1)

Strict streaming covers every choice plus content, refusal, legacy function arguments, and modern
tool arguments. Provider output is inspected before restoration; new PII and unknown tokens are
redacted. Malformed successful responses and malformed events fail closed.

### Conversation retention and semantics (P1)

Provider-safe history retains structured assistant tool calls/results instead of only text.
Rehydrated originals are not written to history. Trimming prunes unreferenced mappings; TTL,
explicit deletion, capacity and sensitive-byte budgets are enforced with deterministic clocks.

### Authentication-only tenancy (P1)

`PrincipalContext` provides pseudonymous tenant/application/subject identity without retaining the
credential. Vault/conversation/rate-limit namespaces use it. Same conversation ID under different
keys is isolated by tests.

### Context-blind policy and public allowlists (P1)

Policy v2 uses principal, route, provider, model, purpose, path, role, confidence, risk, recognizer,
and token scope. Public status requires an exact hashed, scoped, expiring, provenanced assertion and
cannot override explicit block/review rules.

### Detection architecture and evasions (P1)

Detection now has a recognizer Interface, bounded NFKC/zero-width/NBSP canonicalization with span
provenance, validators, profiles, and a synthetic evaluation corpus. Metrics are corpus-specific;
real-world recall remains unknown.

### Unsafe logging and observability labels (P1)

Structured logging suppresses unapproved messages and logs event codes/allowlisted fields. Metrics
accept enum names and bounded taxonomy labels only; raw values, prompts, credentials, paths, and
arbitrary high-cardinality labels are absent from the Interface.

### Final red-team compatibility findings (P1)

The frozen-feature adversarial pass found two fail-closed interoperability defects, not data
disclosure: documented schema member names were misclassified as Base64, and the fixed OpenAI
stream `object` value was redacted as a domain. Dictionary keys still receive direct PII/token
checks but are no longer decoded as opaque values. Exact known protocol literals are preserved.
All 28 independent regression cases pass after the fixes.

## Rejected or narrowed suspected findings

- Mappings were not persisted to disk/Redis; the risk was stale in-memory lifetime, now minimized.
- Media was not automatically sent to the remote provider; its risk is local anonymization quality
  and hostile-file parsing.
- A provider-independent Adapter class does not equal runtime support. Only OpenAI-compatible Chat
  and Gemini `generateContent` have complete wired paths at this milestone.
- Local models remain out of project scope by design; masking them does not protect a remote trust
  boundary.

## Residual risks

- No production-quality local PERSON/ORG/LOCATION/address/health NER; regex/OCR/face false negatives
  and PHONE/DOMAIN false positives remain.
- Semantic re-identification from context is possible after direct identifiers are removed.
- Strict streaming buffers output and loses first-token latency.
- RAM is visible to a compromised host and cannot be reliably zeroized by Python.
- One worker is required for conversation mappings; there is no encrypted shared vault.
- Responses, Anthropic, and Gemini Interactions are Adapter-library surfaces, not complete public
  transport claims.
- Unsupported binary/media/provider extensions block. This is a compatibility limitation and a
  deliberate privacy property.

## Verification

The final local Windows run passed 274 tests with branch coverage enabled and 82.93% combined
coverage, above the 75f840e baseline of 81.81%. The strict 28-case detection corpus, 500-iteration
synthetic privacy benchmark, Ruff, compileall, isolated-project dependency audit, frontend build,
frontend audit, React Doctor, secret/history scan, and diff checks also passed. Docker is not
installed on this host, so Linux container build and CodeQL remain CI-authoritative. Exact commands
are in the README and final report.

See `ARCHITECTURE.md`, `docs/THREAT_MODEL.md`, `docs/PRIVACY_GUARANTEES.md`, `DETECTION.md`,
`POLICY.md`, `PROVIDERS.md`, `VAULT.md`, and `MIGRATION.md`.