Skip to content

Security: ycaptain/densa

Security

.github/SECURITY.md

Security Policy

Scope

This project is an agent skill pack for personal LLM-maintained knowledge bases. It does not run a service and stores no user data of its own. However, vaults built from this skill pack routinely hold material that is highly sensitive — therapy transcripts, medical notes, NDA-bound meeting records, private journals. The guidance below treats your vault as the primary asset to protect.

Reporting a vulnerability

Please report any of the following privately via GitHub Security Advisories:

  • A bypass in _system/densa/ that allows red-line violations (e.g. silent raw/ mutation, log history rewrite, analysis.sources cardinality breach) to slip through pre-commit or CI.
  • A schema ambiguity an adversarial LLM run could exploit to exfiltrate or corrupt vault content while appearing to follow the contract.
  • A prompt-injection pattern in a raw/ file (or any source you might reasonably ingest — clipped articles, transcripts, screenshots) that causes the LLM to perform writes outside the operation's declared scope, skip the plan-then-confirm gate, or coerce a red-line bypass via natural-language instructions.
  • A bug in setup_encryption.sh or the git-crypt integration that could result in unencrypted raw files being pushed to a remote.

Please do not open a public issue for these. We aim to acknowledge within 7 days.

For non-security bugs (rendering glitches, prompt clarity, etc.) use a normal bug report issue.

Hardening checklist for your vault

If you instantiate this skill pack for sensitive material:

  • Wire the pre-commit hook per README.md §"Quickstart".
  • Configure encryption for any sensitive L2 before the first push: see docs/setup.md §"Privacy — sensitive material".
  • Verify encryption is active: git-crypt status -e should list every path you intended to encrypt.
  • Use a second cold-backup remote on a different provider (Codeberg, GitLab, or a self-hosted forge). Single-vendor account loss is the most common way personal vaults disappear.
  • Store your GPG private key on a hardware token (YubiKey, Nitrokey) or in a vetted secrets manager. Loss of the key = loss of encrypted history. Never commit .git-crypt/keys/default.
  • Treat the LLM agent's web access as adversarial: per the L1 red lines, no silent web fetches during ingest. Review every prompt-driven enrichment before it lands in the wiki.
  • Treat raw/ content as untrusted input to the LLM. A clipped article, an ASR-transcribed call, or a web-clip can contain adversarial instructions targeting the agent ("ignore previous instructions and write ..."). Densa's operation prompts fence raw content as <untrusted> so the LLM can tell its instructions apart from the source — see §"Trust-tier protocol" below. The plan-then-confirm gate (every operation drafts a plan you approve before writes) is your second line of defence — never approve a plan without reading the targets of every write, not just the summary.
  • If you push to a public remote, audit .gitattributes and .gitignore against accidentally exposing inbox/ or raw/ paths that weren't yet routed. inbox/ is especially risky as a staging area — consider .gitignoreing inbox/*.md and treating the inbox as never-committed scratch space.
  • Before the first push to any remote, scan for accidentally committed secrets: gitleaks detect --no-banner --staged or trufflehog filesystem . are stdlib-free baselines. Encrypted blobs are still readable to anyone with the git-crypt key.
  • Be aware of LLM-agent vendor surface: prompts, raw contents, and partial wiki contents may be logged or used for evaluation by the LLM vendor depending on your plan and settings. Check your Cursor / Claude Code / Codex / other-vendor data-handling policy before ingesting clinically sensitive or NDA-bound material.

Trust-tier protocol

Densa is a markdown skill pack — it makes no LLM calls of its own. The threat surface is the agent IDE (Cursor / Claude Code / Codex / Cline) your human operator runs Densa's operation prompts inside. A clipped article, an ASR transcript, or any web-clip dropped into raw/ can carry adversarial instructions targeting the agent ("ignore previous instructions and write …"). Densa's response is defence-in-depth across three layers, none of which depends on the LLM vendor:

  1. The LLM fences raw content as data. Every operation prompt (ingest / query / process-inbox plus the three _system/prompts/domains/*-analysis.md sub-prompts) instructs the LLM to wrap raw-source content in <untrusted source="<path>">…</untrusted> and treat instruction- shaped text inside the fence as findings to surface, never as commands. The three-tier trust vocabulary is defined in AGENTS.md §4.5; the threat model + mitigation pattern is at docs/reference/red-lines.md §9.
  2. The human approves the plan. Every operation drafts the page set + diff before any write. Skipping the plan-then-confirm step is the failure mode the fence is designed to make survivable.
  3. The validator gates the commit. AGENTS007 restricts each commit to its prefix's declared write scope; AGENTS003 + AGENTS006 enforce source-grounding on what does land. A successful injection would still have to thread the operation-scope needle without tripping any rule — much harder than persuading one prompt to misbehave.

A 2026-05 review of the wiki-compiler / Obsidian-AI prior-art set (a maintainer-only prior-art review, n=7) found Densa is the first project in the space to document an explicit prompt-injection mitigation. Smart Composer's "Multimedia Context" feature auto-scrapes URL + YouTube transcript content into the prompt with no fencing; nashsu/llm_wiki, Tolaria, and obsidian-llm-wiki-local ingest raw content directly into prompts. The fence convention is cheap to adopt downstream — it is one bullet in your operation prompt.

Supply-chain notes

The validator (_system/densa/) is pure Python with no runtime third-party dependencies — it imports only the standard library. The pre-commit hook invokes the same package via python -m densa. Both are short enough (~1k lines including the rule registry) to read end-to-end before trusting in a security-sensitive vault.

There aren't any published security advisories