Last Updated: December 5, 2025
Version: 0.80.0+
Maintainer: B Flowers
TORQ Console takes security seriously. This document outlines our security practices, known considerations, and guidelines for secure deployment.
- Security Principles
- Recent Security Improvements
- Network Security
- Data Security
- Cryptographic Practices
- Input Validation
- Deployment Security
- Reporting Security Issues
We implement multiple layers of security controls to protect against various threat vectors.
Default configurations follow the principle of least privilege, requiring explicit actions to enable broader access.
Security features are enabled by default, with clear warnings when security-reducing options are used.
We document all security decisions and provide clear guidance on secure usage.
- Fixed undefined name errors that could cause runtime crashes (4 instances)
- Fixed syntax warnings for invalid escape sequences (2 instances)
- Status: ✅ Complete
- Issue: MD5 hash used for non-security purposes without explicit flag
- Fix: Added
usedforsecurity=Falseparameter to all MD5 usage - Locations Fixed:
torq_console/agents/advanced_memory_system.pytorq_console/core/context_manager.py(3 instances)
- Status: ✅ Complete
Code Example:
# Before (flagged by security scanners)
return hashlib.md5(content.encode()).hexdigest()
# After (explicit non-security usage)
return hashlib.md5(content.encode(), usedforsecurity=False).hexdigest()- Issue: Server defaulted to binding on all network interfaces (0.0.0.0)
- Fix: Changed default to localhost (127.0.0.1) with explicit flag for external access
- Location:
torq_console/api/server.py - Status: ✅ Complete
Migration Guide:
# Old behavior (automatically exposed on all interfaces)
run_server() # Bound to 0.0.0.0:8899
# New behavior (secure by default)
run_server() # Bound to 127.0.0.1:8899 (localhost only)
# To expose on all interfaces (explicit opt-in)
run_server(bind_all=True) # Bound to 0.0.0.0:8899 with security warning- Issue: SQL template generator didn't emphasize parameterized queries
- Fix: Enhanced template with security examples and input sanitization
- Location:
torq_console/agents/tools/code_generation_tool.py - Status: ✅ Complete
Template Improvements:
- Added parameterized query examples
- Included security warnings against string concatenation
- Sanitized user input in template generation
- Provided examples for multiple database libraries
- Issue: Pickle files loaded without integrity verification
- Fix: Added file permission checks and error handling
- Location:
torq_console/indexer/vector_store.py - Status: ✅ Complete
Security Measures:
- Verify file permissions before loading
- Refuse to load world-writable files on Unix systems
- Set secure permissions (0o600) when saving pickle files
- Comprehensive error handling for corrupted files
Localhost Only (Secure Default):
# Server binds to 127.0.0.1 by default
run_server() # Only accessible from the same machineExplicit External Access:
# Use --bind-all flag for external access
run_server(bind_all=True) # ⚠️ Security warning displayed✅ Use localhost binding (default)
python -m torq_console.cli --web
# Server at http://127.0.0.1:8899# nginx configuration
server {
listen 80;
server_name torq.example.com;
location / {
proxy_pass http://127.0.0.1:8899;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Benefits:
- SSL/TLS termination
- Rate limiting
- Access control
- DDoS protection
# docker-compose.yml
services:
torq-console:
image: torq-console:latest
ports:
- "127.0.0.1:8899:8899" # Only expose on localhost
environment:
- BIND_ALL=falseAllow only necessary ports:
# UFW (Ubuntu)
sudo ufw allow from 192.168.1.0/24 to any port 8899
# iptables
iptables -A INPUT -p tcp --dport 8899 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 8899 -j DROPSecurity Measures:
-
File Permission Checks:
- Verify files are not world-writable before loading
- Refuse to load suspicious files
-
Secure File Creation:
- Set restrictive permissions (0o600 on Unix)
- Owner read/write only
-
Error Handling:
- Graceful handling of corrupted files
- No exposure of internal paths in errors
Example Usage:
# Secure vector store initialization
vector_store = VectorStore(persist_dir="/secure/path/to/data")
vector_store.save() # Files saved with 0o600 permissions
# Loading with security checks
vector_store.load("/secure/path/to/data") # Validates file permissionsAPI Keys:
- Store in environment variables or
.envfile - Never commit to version control
- Use
.gitignoreto exclude.env
# .env file (never commit)
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...User Data:
- Minimize data collection
- Clear chat history option
- No telemetry by default
✅ Use SHA-256 or better:
import hashlib
# Generate secure token
token = hashlib.sha256(secret_data.encode()).hexdigest()
# Password hashing (use proper libraries)
from passlib.hash import bcrypt
hashed = bcrypt.hash(password)✅ MD5 with explicit flag:
import hashlib
# Cache key generation
cache_key = hashlib.md5(data.encode(), usedforsecurity=False).hexdigest()❌ Never use MD5 for:
- Password hashing
- Digital signatures
- Security tokens
- Authentication
For sensitive data at rest:
from cryptography.fernet import Fernet
# Generate key (store securely)
key = Fernet.generate_key()
cipher = Fernet(key)
# Encrypt
encrypted = cipher.encrypt(sensitive_data.encode())
# Decrypt
decrypted = cipher.decrypt(encrypted).decode()✅ Always use parameterized queries:
# Python with psycopg2
cursor.execute(
"SELECT * FROM users WHERE username = %s",
(username,) # Parameterized
)
# Python with SQLite
cursor.execute(
"SELECT * FROM users WHERE username = ?",
(username,) # Parameterized
)❌ Never use string concatenation:
# VULNERABLE - SQL Injection risk!
query = f"SELECT * FROM users WHERE username = '{username}'"
cursor.execute(query)✅ Use subprocess safely:
import subprocess
# Safe - arguments as list
subprocess.run(['ls', '-la', user_directory], check=True)
# Safe - with shell=False (default)
subprocess.run([command, arg1, arg2])❌ Avoid shell=True with user input:
# VULNERABLE - Command injection risk!
subprocess.run(f"ls {user_input}", shell=True)✅ Validate paths:
from pathlib import Path
def safe_file_access(user_path: str, base_dir: Path) -> Path:
"""Safely resolve user-provided paths."""
requested = (base_dir / user_path).resolve()
# Ensure path is within base directory
if not requested.is_relative_to(base_dir):
raise ValueError("Path traversal attempt detected")
return requestedRequired for production:
# API Keys
ANTHROPIC_API_KEY=your_key_here
OPENAI_API_KEY=your_key_here
# Security settings
BIND_ALL=false # Explicit localhost binding
LOG_LEVEL=info # Don't expose debug info in productionWhat to log:
- Authentication attempts
- API access patterns
- Error rates
- Security warnings
What NOT to log:
- API keys
- User passwords
- Personal information
- Full request payloads
# Good logging
logger.info(f"User {user_id} accessed resource {resource_id}")
# Bad logging - exposes sensitive data
logger.info(f"API call with key {api_key} to {endpoint}")Security Update Schedule:
-
Monitor dependencies: Use
pip-auditorsafetypip install pip-audit pip-audit
-
Update regularly:
pip install --upgrade torq-console
-
Review security advisories:
- GitHub Security Advisories
- CVE databases
- Python security mailing lists
- Change default server binding to localhost
- Use reverse proxy with SSL/TLS
- Configure firewall rules
- Set secure file permissions
- Remove debug/development code
- Review all API keys and secrets
- Enable security logging
- Set up monitoring and alerts
- Review and test backup procedures
- Document security configuration
- Train team on security practices
- Update dependencies monthly
- Review access logs weekly
- Audit file permissions quarterly
- Penetration testing annually
- Security awareness training
We take security seriously. If you discover a security vulnerability:
DO:
- Email security details to the maintainers privately
- Provide clear reproduction steps
- Allow time for fix before public disclosure (90 days)
- Work with us to verify the fix
DON'T:
- Publicly disclose before fix is available
- Exploit the vulnerability
- Access data you don't own
- Perform destructive testing
Subject: [SECURITY] Brief description
Description: Detailed description of the vulnerability
Impact: What can an attacker do?
Reproduction:
1. Step 1
2. Step 2
3. Observe result
Environment:
- TORQ Console version: X.Y.Z
- Python version: X.Y.Z
- Operating System: OS version
Suggested Fix: (optional)
Your recommendation for addressing the issue
- 24 hours: Initial acknowledgment
- 7 days: Assessment and severity classification
- 30 days: Fix developed and tested
- 90 days: Fix released and disclosure (if critical)
Security researchers who responsibly disclose vulnerabilities will be:
- Acknowledged in release notes (if desired)
- Listed in SECURITY.md
- Given credit in CVE if applicable
-
Bandit: Python security linter
pip install bandit bandit -r torq_console/
-
pip-audit: Check for known vulnerabilities
pip install pip-audit pip-audit
-
Safety: Check dependencies for security issues
pip install safety safety check
- Security Issues: Open a private security advisory on GitHub
- General Questions: See CONTRIBUTING.md
- Discussion: GitHub Discussions
| Version | Date | Changes |
|---|---|---|
| 0.80.0+ | 2025-12-05 | Security improvements: MD5 flags, network binding, SQL injection prevention, pickle security |
| 0.70.0 | 2025-XX-XX | Initial security documentation |
Security is a continuous process. This document will be updated as new security measures are implemented and best practices evolve.
Last reviewed: December 5, 2025