Locara

Security Legends: Engineering Practices for Locara

What this is: A research note distilling principles from systems with legendary security reputations, with concrete application to Locara (Tauri/Rust + WebView, capability-based sandboxing for third-party apps). Inspiration for the security model + the discipline behind it.

Status: Reference document. Pair with notes/security-audit.md for current findings, and the runtime ADRs for what’s implemented.

Most relevant to Locara: This is the bible for design decisions. Where one of these legends would shake their head at our code, that’s a defect, not a stylistic preference.


1. qmail (D. J. Bernstein)

Primary source: DJB, “Some thoughts on security after ten years of qmail 1.0” (2007), cr.yp.to/qmail/qmailsec-20071101.pdf. Also the original qmail.org security guarantee ($500 bounty, never paid out for ~a decade).

Key principles:

  • Eliminate bugs by eliminating code. Most of qmail is “trivial code that didn’t get a chance to have bugs.” DJB explicitly argues that security has more to do with amount of trusted code than with how carefully it’s written. Quote: “I should have written much less code.”
  • Eliminate trusted code paths. Distinguish “trusted” (its bugs can violate the policy) from “untrusted” (its bugs can’t). qmail’s mail-parsing code runs unprivileged and chrooted; only qmail-queue (tiny, ~700 LOC) holds a privileged file handle.
  • Distrust all input. Every component re-parses/re-validates rather than trusting upstream cleaning. Network-facing code never holds privilege.
  • No partial parsing of complex grammars. qmail uses simple file formats (one message per file, dot-encoded) instead of in-band escaping.

Concretely done: 7 isolated UIDs, each component running as the least-privileged one; replacement of sendmail’s monolith with ~10 small programs piped together; rejection of features (e.g. no .forward chaining) that expand attack surface.

Apply to Locara:

  • The Tauri Rust core is your qmail-queue — keep it tiny, audit every line. Every capability check belongs there, not in plugins or the webview.
  • Manifest parsing, plugin metadata, model-name strings — re-validate at every privilege boundary, even from “your own” frontend. The webview is hostile; treat IPC like network input.
  • Resist feature creep in the privileged broker. Features like “let plugins call other plugins” or “let plugins read each other’s storage” are sendmail-style monoliths waiting to happen.
  • Theater warning: input “sanitization” via blocklists is qmail’s antithesis. Use simple, parseable formats and reject ambiguous input.

2. OpenBSD (Theo de Raadt et al.)

Primary sources: man.openbsd.org/pledge.2, man.openbsd.org/unveil.2; Theo’s talks “Pledge: A new mitigation mechanism” (Hackfest 2015) and “Mitigations and other real security features” (BSDCan); the OpenBSD Innovations page openbsd.org/innovations.html.

Key principles:

  • Secure by default, not by configuration. Out-of-the-box install has minimal services; everything ships disabled. Defaults are the security boundary because most users never change them.
  • Mitigations as exploit-economics. W^X, ASLR, stack protector (ProPolice, born at OpenBSD), RETGUARD, kernel-relink-on-boot (KARL), pinsyscalls, MAP_STACK. Each one alone is bypassable; stacked, they raise per-exploit cost from days to months.
  • Promise-based privilege reduction at runtime. pledge(2) lets a process declare a list of allowed syscall classes (“stdio rpath inet”); any syscall outside the set kills the process. unveil(2) does the same for filesystem paths (pre-declare which paths are visible; the rest don’t exist for that process). Critically, this is per-process self-restriction — the program tells the kernel “from now on, I won’t need X.”
  • Code-review culture. Tree-wide audits (“the audit”); no commits without review; aggressive removal of dead code.

Apply to Locara:

  • Plugins should be the kernel’s view of an OpenBSD process: each gets a pledge-like declared capability set in its manifest, enforced at the Tauri-IPC boundary. The manifest is the kernel-enforced contract.
  • Adopt unveil’s mental model for filesystem access: a plugin sees only /plugins/<id>/data/, period. Not a “deny if path startsWith /Users/…” check; an enumerated visibility list in the broker.
  • Stack mitigations: Rust memory safety + sandboxed filesystem + denied network egress + per-plugin OS-level sandbox-exec/seccomp profile. None alone is sufficient.
  • Theater warning: a permission UI that defaults to “allow all” is the opposite of secure-by-default. Default-deny everything; force the manifest to enumerate.

3. seL4 microkernel

Primary sources: Klein et al., “seL4: Formal Verification of an OS Kernel” (SOSP 2009); Murray et al., “seL4: from General Purpose to a Proof of Information Flow Enforcement” (S&P 2013); sel4.systems/About/seL4-whitepaper.pdf.

Key principles:

  • Formal proof of functional correctness against a spec. ~10,000 LOC of C kernel proven (in Isabelle/HOL) to refine an abstract spec. Plus integrity, confidentiality, and (for ARM) translation-correctness proofs.
  • Capability-based access control as the kernel’s only security primitive. Every operation requires presenting an unforgeable capability (an opaque reference + rights). No ambient authority — there is no “user ID” that grants implicit access.
  • Minimality enables verification. seL4 is small because large = unverifiable. The proof depends on the kernel doing very little.

What the proof buys: zero buffer-overflow, zero NULL-deref, zero use-after-free in the kernel itself, against the modeled assumptions (compiler correctness, hardware behavior, sequential execution model). What it does not buy: protection against bad userspace policy, side channels not in the model, or hardware bugs (Meltdown-class).

Apply to Locara:

  • Even without formal proofs, adopt the capability-as-only-auth model: Tauri commands take an opaque, unforgeable handle (e.g., a session-bound token) rather than a string identifier the plugin chose. No “give me the file at this path” — instead “give me the file the user picked, here’s the token.”
  • Keep the privileged broker code small enough that a single engineer can hold it in their head.
  • Theater warning: “we use capabilities” without removing ambient authority is meaningless. If a plugin can also call fs.read("/etc/passwd") because it’s a Node API still in scope, the capability layer is a fig leaf.

4. SQLite testing rigor

Primary source: sqlite.org/testing.html (the canonical methodology page).

Key practices:

  • MC/DC (Modified Condition/Decision Coverage), the DO-178B avionics standard. Every boolean sub-expression must be shown to independently affect the outcome. SQLite is the only widely-deployed DB to claim this.
  • TH3 (Test Harness #3): proprietary 100% MC/DC test suite, run on every release across ~20 compilers and many platforms.
  • ~590× test code to source code ratio (last published figure). Tests include three independent harnesses (TCL-based, TH3, SLT) so a bug in one harness doesn’t hide bugs.
  • Fuzz: dbsqlfuzz, LibFuzzer, AFL, OSS-Fuzz, anomaly testing (out-of-memory, I/O errors, disk-full, crash-and-recover injected at every malloc and every syscall).
  • Boundary value tests, regression tests for every reported bug, valgrind/MSan/UBSan/ASan clean.

Why CVEs are near-zero: deeply tested + zero dependencies + small codebase + extreme conservatism about new features. SQLite’s secret isn’t one technique; it’s uniform paranoia at every level.

Apply to Locara:

  • For the privileged broker (capability checks, IPC dispatch, manifest parser): aim for property-based + fuzz testing, not just unit tests. Rust’s cargo-fuzz + proptest are the right tools.
  • Inject anomaly faults — what happens when allocation fails mid-IPC? When a plugin crashes mid-call holding a capability handle? When the user revokes permission while a tool call is in flight? Test the permission-revocation race explicitly.
  • 100% line coverage is not 100% MC/DC. For critical capability code, the gap matters.
  • Theater warning: high test count != high coverage of decision logic. Counting tests is a vanity metric.

5. Chrome’s site isolation + sandboxing

Primary sources: chromium.org/Home/chromium-security/site-isolation/; Reis et al., “Site Isolation: Process Separation for Web Sites within the Browser” (USENIX Security 2019); the Chrome sandbox design doc chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md; Mojo IPC docs.

Key principles:

  • Defense in depth via independent layers, each assuming the others fail. Renderer is sandboxed (seccomp-bpf on Linux, AppContainer on Windows, sandbox_init on macOS) and origin-isolated (Site Isolation puts each origin in its own process post-Spectre) and IPC is mojo-typed with broker-mediated access and V8 runs untrusted JS with a typed boundary. Each layer is bypassable; all four together is rare.
  • The renderer is the enemy. Any code parsing untrusted bytes (HTML, JS, images, fonts, video) lives in the lowest-privilege process. The browser process never touches untrusted bytes if it can avoid it.
  • Brokered access, not direct syscalls. Sandboxed processes can’t open files; they ask the browser process via Mojo IPC, which validates and decides.
  • Spectre as a forcing function for process boundaries. Post-2018, “same-origin policy in one process” was deemed broken; site isolation made the OS process the security boundary.

Apply to Locara:

  • The webview is Chrome’s renderer. It parses untrusted-by-default content (LLM output, user-pasted text, plugin-rendered UI). Treat every IPC message from it as adversarial, even if your own code wrote it — same as Chrome treats messages from its own renderer.
  • Plugins should run in separate processes from the broker if the platform allows (Tauri sidecars, OS sandbox-exec / WSB / firejail). One sandbox layer (Wasmtime, Deno permissions, etc.) is not Chrome-grade.
  • Mojo lesson: every IPC message has a typed schema with an explicit security review. Don’t accept arbitrary JSON from plugins; use a typed RPC schema where every field has a parser and the parser is fuzzed.
  • LLM tool-use IPC is your Mojo. Validate every parameter at the broker; never trust the model’s “the user said it’s fine.”
  • Theater warning: “the browser sandbox protects us” — only if you’re not exposing privileged Tauri commands to arbitrary https: origins. Every exposed command is a hole through the sandbox.

6. Capability-based security theory

Primary sources: Norm Hardy, “The Confused Deputy” (1988); Mark Miller, “Robust Composition: Towards a Unified Approach to Access Control and Concurrency Control” (PhD thesis, JHU 2006); Shapiro et al., “EROS: A Fast Capability System” (SOSP 1999); Genode OS Foundations book (genode.org/documentation/genode-foundations); Miller, Tulloh, Shapiro, “The Structure of Authority: Why Security Is Not a Separable Concern” (2004).

Key principles:

  • No ambient authority. There is no global “I am user X, therefore I can read X’s files.” All authority is held as designated capabilities passed explicitly. The classic counterexample is the Confused Deputy: a compiler with both the user’s permissions and the system’s permissions can be tricked by the user into overwriting the system’s billing file. Ambient authority + intermediary = pivot.
  • POLA (Principle of Least Authority). Each subject gets the minimum set of capabilities needed for its current task, not its lifetime. Object-capability discipline makes POLA the default by making authority explicit and passable.
  • Designation = authorization. The act of being given a capability is the permission. There is no separate ACL check. This kills entire bug classes (path traversal, TOCTOU on permission lookup).

Apply to Locara:

  • This is the bedrock principle for Locara’s plugin model. A plugin saying read_file("config.json") is wrong; the right shape is the user picks a file, the broker gives the plugin a FileHandle capability bound to that file, and the plugin can only operate on what it was given. No path strings cross the boundary.
  • Likewise for models, embeddings, network: plugins receive ModelHandle, EmbeddingIndexHandle, NetworkScope capabilities. Their manifest declares types it needs; the user grants instances.
  • Confused-deputy check for Locara: if Plugin A can ask the broker to invoke Plugin B on its behalf, and B inherits the user’s authority rather than A’s, you have built a confused deputy. Calls between plugins must carry the caller’s capability set, not the user’s.
  • Theater warning: many “capability systems” are actually permission flags (booleans), not capabilities (unforgeable references). Boolean network: true is ambient authority for the whole internet; NetworkScope { hosts: [api.x.com] } granted at install time is closer to a capability, but only if it’s an unforgeable handle the plugin holds, not a string the broker rechecks each call.

7. Rust’s security wins

Primary sources: Matt Miller (Microsoft), “Trends, challenges, and shifts in software vulnerability mitigation” (BlueHat IL 2019) — the “~70% of CVEs are memory safety issues” stat; Google Project Zero, “0day In-the-Wild” tracker; Android Security Bulletin trend posts (security.googleblog.com/2022/12/memory-safe-languages-in-android-13.html — “no memory safety vulnerabilities in Rust code in Android”); Chromium’s “Memory safety” page.

Key facts:

  • ~70% of Microsoft’s annually patched CVEs over 12 years were memory-safety bugs. Same approximate figure from Chromium and Android.
  • Android 13 was the first Android release where the majority of new code was memory-safe; the number of memory-safety CVEs in Android dropped from 223 (2019) to 85 (2022) — a >2× reduction. Google reported zero memory-safety vulnerabilities in Rust code in Android over the two years tracked.
  • What Rust eliminates: use-after-free, double-free, out-of-bounds reads/writes, data races (in safe code), uninitialized memory reads, type confusion. What it doesn’t: logic bugs, TOCTOU, unsafe-block bugs, FFI bugs, supply-chain attacks, dependency vulns, panics-as-DoS.

Apply to Locara:

  • Tauri’s Rust core wipes out the dominant CVE class in the privileged process. This is real, not theoretical — Project Zero’s iOS/Chrome 0day analyses are dominated by C/C++ memory bugs.
  • But your unsafe blocks and FFI to system libraries are still C-grade risk. Audit them with the same paranoia as a C codebase. Consider crates like miri for unsafe code review.
  • The webview frontend is still JavaScript on a C++ engine (WebKit/WebView2). The renderer-process attack surface didn’t go away; you just moved memory bugs out of your code.
  • Theater warning: “we’re written in Rust” is not a security claim by itself. It eliminates one (huge) bug class. Logic bugs in capability checks, prompt injection, supply chain, and design flaws are unaffected.

8. macOS app sandbox + entitlements + TCC

Primary sources: Apple’s App Sandbox Design Guide (developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/); Hardened Runtime docs; Patrick Wardle’s The Art of Mac Malware and Objective-See blog; CVE history of TCC bypasses (e.g., CVE-2020-9934, CVE-2021-30970 “powerdir”, many more).

What’s actually enforced:

  • App Sandbox (kernel-enforced via Sandbox.kext / sandboxd, MAC framework): file access restricted to container, IPC restricted, syscall-level mediation. Mandatory for Mac App Store apps; opt-in elsewhere.
  • Entitlements: signed claims about what the app may do (com.apple.security.network.client, etc.). Verified by amfid/taskgated at launch. Forging requires bypassing code signing.
  • Hardened Runtime: prevents code injection, library hijacking, restricted segment writes; required for notarization.

What’s “best effort”:

  • TCC (Transparency, Consent, Control) — the user-prompted access to Camera, Mic, Photos, Documents, Desktop, Downloads, Full Disk Access. Enforced in userspace by tccd, with a database in ~/Library/Application Support/com.apple.TCC/TCC.db. Many historical bypasses (synthetic clicks, dyld hijacks pre-Hardened Runtime, file-overwrite races, dangling references after uninstall, etc.). TCC is an interlock to prevent silent access, not a strong sandbox.
  • Notarization is malware-scanning, not security review. Apple does not audit your code for vulnerabilities or capability abuse.
  • Code signing identifies the publisher; it grants no capability. A signed binary with network.client entitlement is exactly as dangerous as the developer makes it.

Apply to Locara:

  • Entitlements ↔ Locara’s plugin manifest. They should be declared at install time, displayed to the user, kernel-enforced at runtime, and changing them requires re-installation/re-consent.
  • TCC ↔ runtime user prompts (“this plugin wants access to your contacts”). Useful as a second layer, but never the only enforcement. Per Apple’s own TCC bypass history, prompt-driven gating is fragile.
  • Theater warning: code signing is identity, not capability. Notarization is malware scan, not audit. A plugin signed by a trusted dev still gets exactly the manifest’s capabilities and no more — and if your manifest is wide, the signature gives the user false confidence.

9. Plan 9-style namespace isolation

Primary sources: Pike, Presotto, Dorward, Flandrena, Thompson, Trickey, Winterbottom, “Plan 9 from Bell Labs” (USENIX 1995); “The Use of Name Spaces in Plan 9” (1992); Linux mount namespaces / Linux containers as the inheritor; man namespaces(7).

Key principles:

  • Per-process namespaces. Every process has its own view of the filesystem (and devices, and network, in Plan 9 because everything is a file). A process can see only what its parent mounted into its namespace. No global root.
  • Resources as files, accessed through the namespace. Network, GUI, processes — all appear as file trees. The capability to use a resource = the capability to see its file in your namespace.
  • bind and mount are the composition primitives. Build a process’s world by union-mounting just what it needs.

Apply to Locara:

  • This is the mental model for plugin isolation. A plugin doesn’t “ask permission to read /Users/…/Documents”; the broker constructs the plugin’s world such that only /plugin-data and granted file handles exist. There is no path that resolves to anything else, period — like unveil(2) taken to the limit.
  • For local model files, embeddings DBs, and tool binaries: each plugin’s namespace contains only the model handles it was granted. Even file-enumeration leaks information; restrict it.
  • Theater warning: a chroot is not a security boundary by itself (well-known escapes via fd-passing, /proc, etc.). Combine with user-namespace + seccomp + capability-drop. Plan 9 had it easy: it was designed for this. Retrofitting onto macOS/Windows requires multiple OS primitives stacked.

10. Recent agent-platform breaches (ambient auth, prompt injection)

Public-record incidents (citeable):

  • GitHub MCP “Toxic Agent Flow” (Invariant Labs, May 2025): a malicious public issue’s text (prompt injection) caused an agent with the official GitHub MCP server to exfiltrate the contents of private repos to a public PR. Root cause: the agent had ambient authority across all repos the user’s PAT covered; the MCP server doesn’t enforce per-call scoping. Source: invariantlabs.ai/blog/mcp-github-vulnerability.
  • “EchoLeak” / Microsoft 365 Copilot (Aim Security, June 2025, CVE-2025-32711): a single crafted email caused Copilot to exfiltrate tenant data with no user interaction — the model treated email body as instructions. Source: Microsoft MSRC advisory; Aim Labs disclosure.
  • ChatGPT plugin OAuth flaws (Salt Labs, March 2024): account-takeover via OAuth redirect handling in the plugin install flow; victim installs attacker’s plugin without consent; attacker plugin then has the victim’s account scope. Source: salt.security/blog/chatgpt-plugins-flaws.
  • Anthropic Claude Desktop / MCP server vulnerabilities (multiple researchers, 2024–2025): command-injection in third-party MCP servers (e.g., the SQLite MCP server), prompt-injection-driven file exfiltration via filesystem MCP servers configured with overly broad roots. Documented across Embrace The Red, Simon Willison’s blog, and HiddenLayer reports.
  • “Rules File Backdoor” (Pillar Security, March 2025): invisible Unicode in Cursor/Copilot rules files acted as persistent prompt injection that influenced generated code. Same class as MCP tools/list poisoning.

Common pattern: in every case, the agent had ambient authority (a token, a filesystem root, an API key) far broader than any single task required. A prompt injection or social-engineering vector then exercised that ambient authority. There is no exploit chain here — just one capability boundary missing.

Cross-domain prompt injection: Greshake et al., “Not what you’ve signed up for: Compromising Real-World LLM-Integrated Applications with Indirect Prompt Injection” (AISec 2023, arXiv:2302.12173) — the foundational paper. Untrusted input read by a tool (web page, email, file) becomes instructions to the model. The defense is not prompt engineering; it is treating model output as untrusted and gating tool calls on capabilities the user granted, not the model requested.

Apply to Locara:

  • Every lesson above (qmail, OpenBSD, capabilities) was independently re-learned in 2024–25 by the agent ecosystem at user expense. Locara’s edge is starting with these lessons.
  • The agent loop is the new “renderer process”: it parses untrusted bytes (model output) into actions. Treat tool-call requests from the model identically to IPC from a Chrome renderer — typed schema, capability check, broker decides.
  • Per-tool-call capability scoping, not per-session. A model that needs to read one file should hold a one-file capability for that call only, not a directory root for the conversation.
  • Theater warning: “the model has been trained to refuse malicious instructions” — RLHF is not a security boundary. Neither is “we filter user input for prompt injection.” If your security posture depends on the model behaving, you have no security posture.

Cross-cutting “looks-like-security-but-isn’t” list

  • Code signing is identity, not capability. (Apple, Microsoft.)
  • TLS protects the wire, not the endpoint. The endpoint can still betray you.
  • Notarization / store review is malware scanning, not security audit.
  • Permission UIs that default to “allow” are click-through theater; OpenBSD’s lesson is secure by default.
  • Allowlists by string match (URLs, paths, command names) are bypass-prone; use unforgeable handles.
  • “We use a sandbox” without naming the kernel primitive (seccomp, sandbox-exec, AppContainer, namespaces) is marketing.
  • Boolean permissions (network: true) are ambient authority renamed.
  • Prompt-engineering defenses against prompt injection are not a security boundary.
  • High test count is not high coverage; SQLite’s MC/DC is the bar, not unit-test count.
  • “Written in Rust” kills memory bugs, not logic bugs or design flaws.
  • In-process isolation (Wasm-in-process, V8 isolates) is a softer boundary than OS-process isolation; Spectre forced Chrome to learn this.

Suggested Locara distillation (the one-pager)

  1. Tiny privileged broker, written in Rust, audited line-by-line (qmail).
  2. Default-deny manifest with kernel-enforced capability scopes per plugin (OpenBSD pledge + macOS entitlements + ocap theory).
  3. Unforgeable handles, never strings, across the IPC boundary (seL4, Plan 9, ocap).
  4. Per-tool-call capability scoping for AI agent loops, not per-session (lesson from MCP/Copilot breaches).
  5. OS-process isolation per plugin where possible, with seccomp/sandbox-exec/AppContainer profiles (Chrome).
  6. Typed IPC schema with fuzzed parsers; anomaly testing for capability code (SQLite, Mojo).
  7. Treat the webview and the model as adversarial renderers; broker validates everything.
  8. Plan 9 namespacing for plugin worlds: only what was granted exists for that plugin.
  9. Honesty in the threat model: code signing, notarization, and prompt filters are not security boundaries.

References (canonical primary sources)

  • DJB, qmail thoughts, cr.yp.to/qmail/qmailsec-20071101.pdf
  • OpenBSD pledge(2), unveil(2) manpages; openbsd.org/innovations.html
  • Klein et al., SOSP 2009 (seL4 verification); sel4.systems/About/seL4-whitepaper.pdf
  • sqlite.org/testing.html
  • Reis et al., USENIX Security 2019 (Site Isolation); chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md
  • Hardy, Confused Deputy, 1988; Miller PhD thesis 2006; Shapiro EROS SOSP 1999
  • Matt Miller, BlueHat IL 2019 (70% memory safety); security.googleblog.com/2022/12/memory-safe-languages-in-android-13.html
  • Apple App Sandbox Design Guide; Wardle, Art of Mac Malware
  • Pike et al., Plan 9, USENIX 1995; Use of Name Spaces in Plan 9, 1992
  • Greshake et al., AISec 2023 (arXiv:2302.12173); invariantlabs.ai/blog/mcp-github-vulnerability; Microsoft MSRC CVE-2025-32711; Salt Labs ChatGPT plugins disclosure 2024