Only QWED v5.0.x is currently supported with security patches and updates. Versions 4.x and earlier are end-of-life. If you are running a prior version, upgrade before applying the guidance below.
1. Secret Management
QWED relies on environment variables for sensitive configuration. Never commit.env files to version control.
Environment Variable Injection
For production deployments, we recommend injecting environment variables using your infrastructure’s secret management solution.Docker / Kubernetes
Use Kubernetes Secrets or HashiCorp Vault to inject secrets as environment variables into the container.HashiCorp Vault Integration
If you use Vault, you can useenvconsul or the Vault Agent Injector to populate environment variables before the application starts.
Critical Secrets
Ensure these secrets are rotated regularly:OPENAI_API_KEY(and other provider keys)JWT_SECRET_KEY(used for signing session tokens)DATABASE_URL(if using an external database)
2. Network Security
Firewall Rules
Restrict network access to the QWED API server:- Public Access: Allow ports
80/443only via a Load Balancer / WAF. - Internal Access: The QWED application port (default
8000) should not be directly exposed to the internet. - Database: Block all public access to the database port (e.g.,
5432). Only allow connections from the QWED application subnet.
Rate Limiting (Production)
QWED includes a default in-memory rate limiter. For production, you should tune these limits and consider a distributed solution.Configuration
You can adjust the rate limits using environment variables:| Environment Variable | Default | Description |
|---|---|---|
RATE_LIMIT_REQUESTS_PER_MINUTE | 100 | Max requests per minute per API key. |
RATE_LIMIT_WINDOW_SECONDS | 60 | Time window in seconds. |
Redis backing (recommended)
The default in-memory limiter does not scale across multiple worker processes or replicas. For high-availability deployments, we recommend using a Redis-backed rate limiter to ensure consistent enforcement across your cluster.The Redis-backed rate limiter uses a fail-closed policy. If Redis becomes unreachable at runtime, requests are denied rather than allowed through. This prevents a Redis outage from silently disabling rate limiting. An in-memory fallback is only used when Redis is unavailable at initialization time.
CORS Configuration
By default, QWED is configured for development (*). You must restrict this in production to prevent unauthorized cross-origin requests.
Set the CORS_ALLOWED_ORIGINS environment variable to a comma-separated list of trusted domains.
3. Authentication Hardening
API key rotation
Regularly rotate API keys to minimize the impact of a potential leak. QWED provides a built-in rotation mechanism via thePOST /admin/keys/rotate endpoint. Old keys should be revoked immediately after the rotation window.
Password policies
If you integrate QWED with a custom user database:- Enforce a minimum length of 12 characters.
- Require a mix of uppercase, lowercase, numbers, and special characters.
- Use the built-in
bcrypthashing provided by QWED’s authentication module.
Session Management
Control the lifetime of access tokens to reduce the window of opportunity for session hijacking.| Environment Variable | Default | Description |
|---|---|---|
JWT_ACCESS_TOKEN_EXPIRE_MINUTES | 60 | Minutes until the access token expires. |
15 or 30 minutes) and implement refresh tokens if needed.
4. Enhanced prompt injection defense
New in v4.0.0
EnhancedSecurityGateway (OWASP LLM01:2025 compliant) that screens all inputs through seven defense layers:
| Layer | Defense | Description |
|---|---|---|
| 1 | Pattern detection | Heuristic matching against 14 known injection patterns |
| 2 | Length limiting | Strict 2,000-character limit (blocks ~70% of injection attacks) |
| 3 | Base64 decoding | Detects and decodes base64-encoded payloads, then scans for injection keywords |
| 4 | Semantic similarity | Uses sequence matching against system prompt (threshold: 0.6) |
| 5 | Keyword detection | 28 advanced keywords: disregard, override, bypass, jailbreak, etc. |
| 6 | Unicode script mixing | Detects Cyrillic/Arabic/Greek characters mixed with Latin (homoglyph attacks) |
| 7 | Zero-width characters | Detects invisible characters (\u200B, \u200C, \u200D, \uFEFF) used to hide payloads |
PII redaction
All API error paths now use a centralizedredact_pii() function that masks email addresses, phone numbers, SSNs, and IP addresses before they reach logs. Stack traces are suppressed in error responses (exc_info=False) to prevent data leakage.
Fail-closed code execution
New in v4.0.4
SecureCodeExecutor). The in-process Wasm and restricted execution fallbacks that existed in earlier versions have been permanently disabled.
If the Docker daemon is unreachable, the affected endpoints return HTTP 503 rather than degrading to an insecure execution mode. The executor performs a live health check (docker.ping()) on every request to detect runtime failures that would not be caught by a startup-time flag.
This design ensures that a Docker outage is surfaced as a visible service disruption rather than silently downgrading security.
Safe expression evaluation
Alleval() calls have been fully eliminated and replaced with a custom AST-walking evaluator. Instead of compiling and executing code, the evaluator parses expressions into an AST, validates every node against a strict allow-list, and then interprets the tree directly — no eval() or compile() is ever invoked.
The safe evaluator enforces three layers of defense:
- AST allow-list — only permitted node types (
Constant,Name,BinOp,UnaryOp,Call,Tuple,List, and approved operators) pass validation. Unknown or dangerous nodes are rejected before evaluation. - CodeGuard integration — when the full
qwed_newpackage is available, expressions are additionally screened byCodeGuardbefore execution. - Restricted namespace — the evaluator resolves symbols only from an explicit namespace. For SymPy paths, only whitelisted functions (e.g.,
sqrt,sin,cos,log,Rational,pi,E) are available. For Z3 paths, onlyAnd,Or,Not,Implies,If,Int,Bool, andRealare permitted.
- Keyword unpacking (
**kwargsviaNone-keyed keywords) is blocked in all call nodes __(double underscore) patterns are blocked to prevent attribute access attacks- SymPy expressions use exact arithmetic (
sympy.Integer,sympy.Float) to avoid floating-point drift during comparison
Credential store security
Theqwed init wizard and YAML provider config system write .env files with strict security guarantees:
.envfiles written with0600permissions (owner-only on Unix)- Atomic writes via
tempfile+os.replaceto prevent partial writes - Symlink attack prevention (
O_NOFOLLOWon Unix) - Automatic
.gitignoreverification ensures.envis excluded from version control - API keys are never printed in full — only the first 8 characters are shown in logs
5. OWASP LLM Top 10 compliance
QWED implements technical defenses for the OWASP LLM Top 10. However, security is a shared responsibility.Your Responsibilities (User/Deployment)
While QWED handles internal verification, you must implement the following “Human in the Loop” and deployment safeguards:LLM01: Prompt Injection & LLM02: Insecure Output Handling
- Human in the Loop: For critical actions (e.g., financial transactions, code deployment), do not rely solely on QWED’s verification. Implement a manual approval step.
- Output Monitoring: Log and randomly audit verified outputs to ensure the verification engine itself hasn’t been bypassed.
LLM05: Supply Chain Vulnerabilities
-
Startup environment integrity: QWED now enforces environment integrity at startup by verifying all Python
.pthstartup hook files against a built-in allowlist. If any unrecognized.pthfile is found, the server refuses to start. You can extend the allowlist for custom deployments using theQWED_ALLOWED_STARTUP_PTH_FILESenvironment variable (comma-separated list of filenames). -
Startup hook detection: Use
StartupHookGuardto scan for malicious.pthfiles in Pythonsite-packagesbefore your application starts. This defends against supply chain attacks that inject code-execution hooks via compromised PyPI packages. - Network Isolation: Run the QWED backend in a VPC without direct outbound internet access, except to specific LLM provider APIs (allowlist).
- Dependency Scanning: Regularly scan your deployment container for vulnerabilities in system packages.
LLM06: Sensitive Information Disclosure
- Data Minimization: Do not send PII (Personally Identifiable Information) to QWED unless absolutely necessary. Mask or redact sensitive data before it reaches the API.
6. Reporting a vulnerability
If you discover a security vulnerability in QWED, do not report it through public GitHub issues, pull requests, or discussions. Instead, report it privately via email to rahul@qwedai.com. If GitHub private vulnerability reporting is enabled for the repository, you may use that channel as well. Include as much detail as possible:- Steps to reproduce the issue
- Affected version(s)
- Relevant code, configuration, logs, or screenshots
- Proof-of-concept or exploit details, if available
- The potential impact on confidentiality, integrity, or availability
Response timeline
- Your report will be acknowledged within 24 hours
- The team will triage and validate the report as quickly as possible
- You will be kept informed of progress during investigation and remediation
- Disclosure timing will be coordinated with you when appropriate
Coordinated disclosure
Please give the maintainers a reasonable amount of time to investigate and remediate the issue before making any public disclosure. You should:- Avoid publicly disclosing the issue until a fix or mitigation is available
- Make a good-faith effort to avoid privacy violations, data destruction, or service disruption
- Avoid accessing, modifying, or exfiltrating data beyond what is necessary to demonstrate the issue
Security issue vs. bug
- Security issue — A vulnerability that compromises the confidentiality, integrity, or availability of the system, such as code execution, injection, auth bypass, privilege escalation, sensitive data exposure, sandbox escape, or fail-open security behavior. Report these privately as described above.
- Bug — A functional defect or unexpected behavior that does not have security implications, such as a UI issue, incorrect calculation, documentation problem, or non-exploitable crash. Report these via the GitHub Issue Tracker.