Please report suspected vulnerabilities privately — do not open a public issue for a security problem. Use GitHub's private vulnerability reporting (Security → Report a vulnerability). Include a description, reproduction steps, and the impact you see. You'll get an acknowledgement, and a fix or mitigation will be coordinated before any public disclosure.
cite-citadel is pre-1.0; only the latest released version on PyPI is supported. Please upgrade before reporting.
cite-citadel has a small, honest data-flow surface — understanding it is the best defense:
- cite-citadel spawns your CLI as a subprocess in the workspace. Ingest does
shutil.which(<cli>)+subprocesson the official coding-agent binary you installed and logged in (claude/copilot/gemini). It bundles no provider code, embeds no credentials, and reads, logs, or transmits no secret or token itself. - Raw content travels wherever your provider's terms say. Your CLI reads the files under
raw/under your account; where that content then goes (and whether prompts/logs are retained) is governed by that provider's terms, not by cite-citadel. See the README's License & third-party tools section for the linked provider terms. - Data-governance caveat. Because ingest sends raw content to your CLI/provider, do not ingest confidential or regulated material on a plan whose terms permit training on inputs. Pick the plan/tier appropriate to your data sensitivity.
- Transcript privacy. A
CITADEL_LLM_LOG_DIRtranscript (prompt + full CLI stdout/stderr) can contain source content. It is written local-only — keep it out of version control and off shared locations. The generatedwiki/.citadel_failures.jsonis likewise per-machine derived state and is gitignored. The same applies to the audio transcript cache (CITADEL_AUDIO_SUPPORT):.citadel_transcripts/next to the wiki dir holds each recording's spoken content as plaintext — and to the PDF text-layer cache (.citadel_pdftext/, written whenever the pypdf pre-pass runs — i.e. by default, unlessCITADEL_PDF_TEXT=0or pypdf was force-removed), which holds each PDF's extracted text the same way — transcription itself runs fully locally (a whisper-class CLI on your machine), but treat the cache like the raw recordings themselves. Resume checkpoints (CITADEL_RESUME, on by default) are the same class of derived state:.citadel_resume/next to the wiki dir banks the wiki pages a chunked source's completed segments produced, in plaintext, until that source finishes (or an age sweep clears it). It only ever materializes for a large source whose run was interrupted;CITADEL_RESUME=0turns it off entirely, at the cost of re-paying for those segments. - Serving is local by default; HTTP is opt-in and authenticated.
citadel servespeaks stdio — the client spawns it, nothing listens on a socket.citadel serve --httpadditionally binds a port (MCP Streamable HTTP) and is the one network surface citadel has. It refuses to start withoutCITADEL_HTTP_TOKEN(≥16 characters); every request must carryAuthorization: Bearer <token>, compared in constant time (both sides are hashed first, so not even the presented token's length shows up in the timing), and an unauthenticated request is answered 401 before it reaches a tool or a session. The bind defaults to loopback, and DNS-rebinding protection is on: a request'sHostmust be a name the server accepts — derived from the bind address, or named inCITADEL_HTTP_ALLOWED_HOSTSfor a tunnel/proxy (a0.0.0.0bind refuses to start without it, rather than accepting any name) — and a request carrying a browserOriginis refused unlessCITADEL_HTTP_ALLOWED_ORIGINSadmits it. The transport itself is plain HTTP: put a TLS-terminating tunnel (cloudflared / tailscale /ssh -R) in front of it rather than binding a public interface, and prefer--read-only(CITADEL_HTTP_READ_ONLY=1) for anything reachable beyond your own machine — it disableswiki_captureandwiki_ingest(they stay listed but answer with a refusal), the latter of which spawns your coding-agent CLI on the serving host. Treat the token like a password to the whole workspace: it is the only credential, and rotating it is just editing.envand restarting. - Billing shadow. If a provider API key sits in your environment while
CITADEL_LLM_CLI=claude, the CLI may bill the metered API instead of your subscription.citadel doctorwarns about this; the same subscription-vs-API story is covered in the terms note above.