Cortex includes several security features to protect your data and prevent abuse. This guide covers security configuration and best practices.
Prompt Security
Cortex includes layered protection against prompt injection attacks — attempts to manipulate the AI through malicious input, whether typed directly into a question or planted inside an ingested document. No single layer is relied on; each one narrows what the others miss.
How It Works
The defenses fall into five layers:
- Input detection (
prompt_security.py) — the question is normalized (NFKC folding + zero-width stripping, defeating homoglyph/invisible-character obfuscation) and matched against injection patterns. The heuristic is tuned to avoid false-positiving on legitimate code/markup questions. Detection runs in strict mode on the chat and research entry points → a safe refusal. - Prompt Guard classifier (optional) — a model-based second gate on the question (see below).
- Output filtering (
filter_stream) — token-streamed responses pass through a sliding-window filter that redacts verbatim system-prompt phrases and structural role tags before they reach the client. - Untrusted-content fencing — retrieved chunks, graph context, and tool results are wrapped in data-boundary markers and the model is instructed to treat everything inside as data, not instructions (defense against second-order injection carried by your own documents).
- Ingestion-time scan (experimental, off by default) — when enabled via
ENABLE_INGESTION_INJECTION_SCAN=true, every ingested document is scanned once for planted injection instructions and flagged (never blocked), surfaced as an "Injection Flagged" badge in the document list. When the flag is off (the default), the feature is completely absent — no scan runs and no related setting appears in the admin UI.
Prompt Guard (query-time classifier)
Beyond the regex layer, Cortex can route each question through a dedicated prompt-injection classifier model (PIGuard, MIT-licensed) before retrieval, refusing flagged questions with the same safe message. It catches jailbreak/injection phrasings the regex misses, and is tuned to under-flag benign questions that merely contain trigger words.
- Shared, zero per-instance cost — the model is hosted once per machine by
the
cortex-helperservice (alongside the reranker) and called over HTTP, so no tenant backend loads it. (Self-hosters without a helper can instead run it in-process withPROMPT_GUARD_LOCAL=true— mirrors the local reranker fallback; adds resident RAM, so it's off by default.) - Opt-in and fail-open — active only when
PROMPT_GUARD_SERVICE_URLpoints at a helper. If the helper is unreachable, questions proceed unguarded (availability over strictness). - Runtime toggle — admins flip it in System Configuration → Features & Security without a restart. Each guarded question costs one extra security query (metered toward your monthly quota), so the toggle lets you trade that cost off.
Code
What It Protects Against
- Jailbreak attempts - Trying to bypass AI safety guidelines
- Instruction injection - Inserting malicious instructions
- System prompt extraction - Trying to reveal system prompts
- Role manipulation - Pretending to be a different entity
- Second-order (indirect) injection - Instructions planted inside ingested documents or fetched web/tool content (mitigated by fencing — plus the experimental ingestion scan where enabled — not eliminated)
Safe Refusal
When an attack is detected — by the regex layer or the Prompt Guard classifier — Cortex returns a safe refusal instead of processing the question, and logs the detection with the matched pattern (or the classifier's label + score).
API Key Security
Strong Keys
Use cryptographically secure API keys:
Code
Key Permissions
Apply the principle of least privilege:
| Use Case | Recommended Permissions |
|---|---|
| Search/Q&A only | read |
| Document management | read, write |
| Full automation | read, write, delete |
| Admin operations | admin |
Key Expiration
Set expiration dates for temporary access:
Code
Session Security
JWT Configuration
Code
Session Best Practices
- Use HTTPS in production
- Set appropriate session timeouts
- Rotate session secrets periodically
Secret Encryption at Rest
User-supplied secrets — git connector personal access tokens and secret-typed
skill config fields — are encrypted at rest when ENCRYPTION_KEY is set:
Code
- Enable anytime: existing plaintext secrets are encrypted automatically on the next startup. Without a key, secrets are stored in plaintext and a warning is logged at startup.
- Key rotation (zero downtime): prepend the new key —
ENCRYPTION_KEY=<new-key>,<old-key>— restart (everything is re-encrypted with the new key), then drop the old key. - Back up the key: a lost key makes stored secrets unrecoverable; affected git syncs and skill activations fail with a clear "re-enter the credential" error.
- Exports are credential-free: library exports strip skill secrets, and git connections are never exported.
Input Validation
All user inputs are validated:
File Uploads
Code
Validation includes:
- File size limits (enforced mid-stream — oversized uploads are rejected before they are ever fully buffered)
- Allowed file types (PDF, TXT, MD, DOCX)
- Ingestion-time prompt-injection scan (experimental, opt-in via
ENABLE_INGESTION_INJECTION_SCAN=true; content is flagged, never blocked)
Query Limits
- Maximum query length enforced
- Request body size limits
- Rate limiting per API key
Rate Limiting
Opt-in per-API-key token bucket on the ask/upload endpoints:
Code
When a key exceeds its budget the API responds 429 Too Many Requests
with a Retry-After header (seconds until the bucket refills). The
monthly MAX_QUERIES_PER_MONTH quota uses the same 429 + Retry-After
contract.
CORS Configuration
Restrict which origins can access your API:
Code
Network Security
Firewall Rules
Block direct access to internal services:
Code
HTTPS
Always use HTTPS in production:
Code
Data Protection
At Rest
- Neo4j Enterprise Edition supports encryption at rest
- Use encrypted volumes for Docker data
In Transit
- All API communication should use HTTPS
- Internal service communication uses Docker network isolation
Secrets Management
Never commit secrets to version control:
Code
Audit Logging
Enable the append-only JSONL audit trail for compliance review:
Code
Logged events (one JSON object per line, each carrying the acting API key, outcome, and request ID):
- Authentication events (rejected keys, unauthorized requests)
- Document uploads, deletions, and reprocessing
- Search and ask activity
- Configuration changes (API key CRUD, skill config, system reset, library import/export)
The audit log records metadata only — never document content or query
text, consistent with Cortex's observability masking: operational
visibility without content exfiltration. The file rotates at 50 MB
(one .1 generation is kept).
Security Checklist
Before Production
- Change all default passwords
- Set strong
ADMIN_API_KEY(not the example key) - Set strong
SESSION_SECRET(32+ characters) - Set
ENCRYPTION_KEY(and back it up) so git PATs and skill secrets are encrypted at rest - Enable
PROMPT_SECURITY=true - Configure HTTPS with valid certificates
- Restrict
CORS_ALLOWED_ORIGINSto your domains - Block direct access to Neo4j ports
- Review API key permissions
Ongoing
- Rotate API keys regularly
- Monitor audit logs for suspicious activity
- Keep dependencies updated
- Regular security reviews
- Backup encryption keys securely
- Test disaster recovery procedures
Reporting Security Issues
If you discover a security vulnerability:
- Do not open a public GitHub issue
- Email security concerns to the maintainers
- Include details to reproduce the issue
- Allow time for a fix before disclosure