Skip to content

Security: Singhsh01/ContextOS

Security

docs/security.md

Security model

Repository content is treated as untrusted input at every stage: it is evidence about code, never instructions.

Trust boundaries

Layer Source Trusted? Where it appears
System instructions ContextOS yes <system_instructions> at the top of every package
Task the user or calling agent authorised <task>
Repository facts memory items a person verified reviewed <repository_facts>, each with kind and verification date
Evidence repository files no <untrusted_evidence …> blocks
Model observations LLM output no stored only as proposed memory until reviewed

Threats and controls

Threat Control Test
Prompt injection from repository files Patterns such as "ignore previous instructions", fake system: turns, <system> tags, requests to reveal secrets or pipe curl into a shell are detected at ingestion and again per chunk. Flagged items stay retrievable (hiding them would hide real code) but carry a warning attribute and raise a high-level uncertainty signal. test_injection_content_is_flagged_and_fenced
Forged delimiters Evidence text cannot open or close untrusted_evidence, task or system_instructions tags; they are escaped before rendering. test_injection_detection_and_neutralisation
Secret leakage Credential files are never read (.env, keys, .npmrc, .pypirc, *.tfstate, …); inline tokens and password = "…"-style assignments are redacted before storage, so they never reach the database, embeddings, the UI or a model. test_ingestion_respects_gitignore_and_secrets, test_secret_files_and_redaction
Unauthorised local access Local imports only below CONTEXTOS_ALLOWED_ROOTS; empty means local import is disabled. Symlinks are skipped so a repository cannot point outside its root. test_import_outside_allowed_roots_is_refused
Unauthorised repository access via MCP CONTEXTOS_MCP_ALLOWED_REPOS allow-list checked by every tool, including list_repositories. test_mcp_allowlist
Cross-repository contamination Every query is scoped by repo_id; graph caches are per repository; embedding comparisons are restricted to the repository's embedding version. test_no_cross_repository_contamination
Poisoned persistent memory Anything written by a model is proposed and never injected. Only a person can verify it. Facts record the files they depend on and go stale when those files change. test_incremental_reindex_and_memory_invalidation
Stale architecture assumptions Packages exclude chunks from another commit; the validator re-reads cited lines from the working tree and down-weights changed ones; an uncertainty signal warns when HEAD is ahead of the index. packager unit tests

Known gaps

  • Injection detection is pattern-based. It catches common phrasings, not paraphrases or encoded payloads; the structural fencing is the primary defence.
  • Secret redaction covers well-known token formats and common assignment shapes, not arbitrary high-entropy strings.
  • The HTTP API has no authentication. Run it on localhost or behind an authenticating proxy.
  • GitHub import clones public repositories over HTTPS only; private repositories need credentials configured for git outside ContextOS.

There aren't any published security advisories