Why this matters for regulated industries
The regulatory frame matters because it inverts the security question. The default assumption in most modern AI tooling is "data leaves the host, the cloud holds it safely, audit logs are good enough." For organisations covered by GDPR Art. 32, HIPAA §164.312, attorney-client privilege, ISO 27001 with data-residency clauses, or national-cybersecurity frameworks, that assumption is inverted: data cannot leave the host, and the burden of proof is on the operator.
BuildOnAI's design starts from the inverted assumption:
- Self-hosted by default. Every service runs on hardware the operator controls. No cloud calls, no telemetry, no vendor lock-in. The optional fallback to a hosted LLM is opt-in via API key — without it, the ecosystem stays fully offline.
- Document Processor stays local. Tauri desktop app written in Rust + Svelte. PDF / DOCX / TXT parsing happens on the host filesystem. Embeddings are generated by Ollama on the host. ChromaDB stores them on local disk. The original document never crosses a network boundary.
- ed25519 inter-agent auth. When an organisation needs more than one agent or one host, every request is signed. Public keys live as plain files on the key-server; revocation is
rm. No external identity provider is required. - Audit trail by construction. Every privileged endpoint writes a structured JSONL audit line. Tail-and-alert is enough; no separate SIEM is required to start.
The four structural layers
"Structural security" means the protection is part of the architecture, not a process the operator has to follow. Four layers, each in a different repository, each with its own SECURITY.md:
1. Cortex Policy Engine
Cortex's Policy Engine
refuses dangerous tool calls regardless of who or what
asked. A compromised prompt can ask the model to delete
files; the policy refuses. Three rules ship by default
(deny on destructive shell, ask
on filesystem writes outside the project, allow
on read-only commands). Custom rules go in
policy.json at the project root. The engine
is the structural defence against prompt injection — no
amount of clever input gets a human-confirmation step
revoked once the policy says ask.
2. ed25519 signed requests
The Key Server
+ AUTH_MODE three-mode dial
(off → observe → enforce)
turns every inter-agent HTTP call into a signed transaction.
Replays are blocked by short-lived nonces; clock drift over
~60 s is rejected. Public keys are plain files; revocation
is rm. The migration path is gradual — see
Secure deployment.
3. Document Processor isolation
Document Processor runs as a Tauri desktop app — Rust core, Svelte UI, no embedded browser sandbox to escape. File system access is scoped to user-chosen directories via Tauri's allow-list; there is no remote endpoint for an attacker to reach. A parsed document leaves Document Processor only if the operator configures an explicit pipeline, like the one in Document pipeline.
4. CI-enforced invariants
Every repository has a .github/workflows/
pipeline with security invariants — Python AST checks for
shell-injection patterns, capability-based fallback
sentinels, known-public-endpoint whitelists, signed
fixtures for migration tests. Disabling CI invariants
voids commercial-licence guarantees; this is written into
the licence as a contractual clause, not just a
gentleman's agreement.
What we protect against, what we don't
Each repository ships a SECURITY.md with the precise threat model for that component. Common shape:
In scope
- An untrusted prompt tricking the model into requesting a destructive action (Policy Engine refuses regardless).
- An unauthorised peer on the network calling protected endpoints under
AUTH_MODE=enforce(request is rejected; ed25519 verification fails). - Replay attacks against signed endpoints (nonce cache + timestamp window).
- A compromised agent host being decommissioned mid-incident (
rmthe public key on key-server; revocation is immediate).
Out of scope
- A determined attacker with arbitrary network access to the host's listening ports under
AUTH_MODE=off(the default for solo / trusted-LAN deployments). If your environment doesn't match those assumptions, switch toenforce. - Malicious code in a Cortex plugin dropped into
plugins/. Plugins are trusted-by-design today; PEP 684 subinterpreter isolation is on the roadmap (Cortex v1.2). Until then, treatplugins/like you'd treat any directory of executable code on the host. - Attacks on the host operating system itself. BuildOnAI is a userland service; it relies on the host's process isolation, container isolation, and filesystem permissions for the layers it doesn't own.
Vulnerability disclosure
If you've found a security issue, write to
[email protected]
with subject [SECURITY]. Initial
acknowledgement within three business days. We'd rather
fix something quietly and credit you in the release notes
than learn about it on social media first.
Please do not file public GitHub issues for security
reports. The SECURITY.md file in each
repository describes the per-component reporting path and
our response commitments.
Per-repository threat models
Every repository ships its own SECURITY.md with the authoritative threat model for that component:
- consciousness-server / SECURITY.md — AUTH_MODE matrix, agent-restart channel, systemctl control surface, key-server secrets dispenser, test-runner subprocess.
- cortex / SECURITY.md — Policy Engine semantics, structural defence against prompt injection, plugin isolation roadmap.
- document-processor / SECURITY.md — Tauri allow-list, no-network-by-default, classifier accuracy and false-positive notes.
- buildonai-key-server / SECURITY.md — IP allow-list, optional API-key header, audit log shape.