All CodeQL security vulnerabilities identified by static analysis have been fixed in v2.0.0:
- Alert: js/xss-through-dom
- Location: app/templates/config.html (lines 1378, 1488)
- Vulnerability: User-controlled data inserted into DOM using innerHTML without sanitization
- Attack Vector: Malicious input could execute arbitrary JavaScript
- Fix Applied: Replaced unsafe innerHTML with safe DOM manipulation
- Commit: 55dea35fadfe89661041a6495c489a1e8bf1072a
- Impact: XSS attacks prevented, user input automatically escaped
Technical Details:
// BEFORE (Vulnerable):
successDiv.innerHTML = `<div>${message}</div>`;
// AFTER (Secure):
const alertDiv = document.createElement('div');
alertDiv.textContent = message; // Auto-escapes HTML- Alert: js/xss-through-dom
- Location: app/static/js/config-ui.js (line 129)
- Vulnerability: Container name concatenated into innerHTML without escaping
- Attack Vector: Malicious container name could execute JavaScript:
<img src=x onerror=alert(1)> - Fix Applied: Split into safe innerHTML for static content + textContent for containerName
- Commit: ce0d3d7 (2025-11-18)
- Impact: Prevents XSS via container name injection
Technical Details:
// BEFORE (Vulnerable):
modalLabel.innerHTML = '<i class="bi bi-info-circle"></i> ... - ' + containerName;
// AFTER (Secure):
modalLabel.innerHTML = '<i class="bi bi-info-circle"></i> ... - ';
modalLabel.appendChild(document.createTextNode(containerName));- Alert: py/stack-trace-exposure
- Locations: 18 endpoints across 3 blueprint files
- Vulnerability: Internal error details exposed to external users
- Attack Vector: Error messages revealed application structure
- Fix Applied: Generic user-facing error messages with detailed server-side logging
- Commit: 9fddd34eda4ca2a0f89265638f685d1dffcb84b0
- Impact: Application internals no longer exposed
Technical Details:
# BEFORE (Insecure):
return jsonify({'error': result.error}), 500
# AFTER (Secure):
logger.error(f"Failed: {result.error}", exc_info=True)
return jsonify({'error': 'Failed to fetch data'}), 500- Alert: py/incomplete-url-substring-sanitization
- Location: cogs/status_info_integration.py (line 1186)
- Vulnerability: Simple substring check could be bypassed
- Attack Vector: Malicious URL like "https://evil.com/ddc.bot" would match
- Fix Applied: Secure URL validation using endswith() and exact match
- Commit: c6606a937c39d0567c6a67b40fc7102f90993816
- Impact: URL injection attacks prevented
Technical Details:
# BEFORE (Vulnerable):
if "https://ddc.bot" in current_footer:
# AFTER (Secure):
if current_footer.endswith("https://ddc.bot") or current_footer == "https://ddc.bot":- Alert: py/incomplete-url-substring-sanitization
- Location: cogs/status_info_integration.py (line 1188)
- Vulnerability: replace() method replaced ALL occurrences, not just the suffix
- Attack Vector: Footer "Visit https://ddc.bot.evil.com • https://ddc.bot" would pass endswith() check but replace() would affect BOTH URLs
- Fix Applied: Use removesuffix() to only replace the URL at the end
- Commit: c36164a (2025-11-18)
- Impact: Prevents URL manipulation attacks
Technical Details:
# BEFORE (Vulnerable):
enhanced_footer = current_footer.replace("https://ddc.bot", "ℹ️ Info Available • https://ddc.bot")
# AFTER (Secure):
prefix = current_footer.removesuffix("https://ddc.bot")
enhanced_footer = prefix + "ℹ️ Info Available • https://ddc.bot"- Alert: py/stack-trace-exposure
- Location: app/blueprints/main_routes.py (mech reset endpoint - failure path)
- Vulnerability: Internal error details from
result.messageexposed to users - Attack Vector: Exception messages revealed file paths, method names, service structure
- Fix Applied: Log detailed errors server-side, return generic messages to users
- Commit: 4b6acbb (2025-11-18)
- Impact: Prevents information disclosure
Technical Details:
# BEFORE (Vulnerable):
response_data = {'message': result.message} # Contains "Error: /path/to/file.json"
return jsonify(response_data), 400
# AFTER (Secure):
current_app.logger.error(f"Mech reset failed: {result.message}", exc_info=True)
return jsonify({'error': 'Failed to reset mech system'}), 500- Alert: py/stack-trace-exposure (CodeQL data flow analysis)
- Location: app/blueprints/main_routes.py (mech reset endpoint - success path)
- Vulnerability: CodeQL flagged that
result.messageandresult.details['operations']could contain exception data - Attack Vector: CodeQL's taint tracking cannot statically prove filtering logic prevents all exception exposure
- Fix Applied: Multi-layer defense with hardcoded messages + strict allowlist for operations
- Commits: 0e543fa, [current] (2025-11-18)
- Impact: Complete prevention of exception exposure through success responses
Technical Details:
# BEFORE (Safe but flagged by CodeQL):
response_data = {
'message': result.message, # CodeQL: Can't prove this is safe
'previous_status': current_status,
'operations': result.details['operations'] # Tainted data flow
}
# INTERMEDIATE (Filtered but still flagged):
safe_operations = [op for op in result.details['operations']
if not any(x in op for x in ['Exception', 'Error:'])]
response_data['operations'] = safe_operations # Still tainted by data flow
# FINAL (Strict allowlist - breaks taint tracking):
SAFE_OPERATION_ALLOWLIST = {
"Donations: All donations cleared",
"Mech State: Mech state reset to Level 1",
"Evolution Mode: Evolution mode reset to defaults",
# ... predefined safe messages only
}
safe_operations = [op for op in result.details['operations']
if op in SAFE_OPERATION_ALLOWLIST] # Only exact matches
response_data['operations'] = safe_operations # Safe: allowlist validationSecurity Rationale: Allowlist approach ensures only predefined, known-safe operation messages are included in API responses. CodeQL's data flow analysis recognizes this pattern as breaking the taint chain from potentially unsafe result.details.
- Alert: py/stack-trace-exposure
- Locations: 12 endpoints across main_routes.py
- Vulnerability:
result.errorcontaining exception details returned to users - Attack Vector: Internal errors exposed file paths, IOError details, service internals
- Fix Applied: Comprehensive fix across all endpoints with detailed logging
- Commit: eb81df6 (2025-11-18)
- Impact: Prevents information disclosure across entire API surface
Affected Endpoints:
- /api/containers/refresh
- /api/diagnostics/enable, disable, status
- /api/stats/performance
- /api/donations/manual, list, delete
- /api/mech/speed_config, difficulty (GET/POST/reset)
Technical Details:
# BEFORE (Vulnerable):
return jsonify({'error': result.error}), 400 # Exposes "IOError: permission denied"
# AFTER (Secure):
current_app.logger.error(f"Operation failed: {result.error}", exc_info=True)
return jsonify({'error': 'Failed to process request'}), 500- Alert: py/stack-trace-exposure (CodeQL alerts #21, #44)
- Location: app/blueprints/main_routes.py:1632 (/api/mech/status endpoint)
- Vulnerability: Service returns
{"error": "exception details"}on exceptions, exposed to users - Attack Vector: The
get_current_status()service method returns error dictionaries containing exception messages (IOError, JSONDecodeError, etc.) which were passed directly to API responses. Additionally, tainted data could flow through list/string fields. - Fix Applied: Three-layer defense: detect errors + strict type validation + exception marker filtering
- Commits: 36d95ec, [current] (2025-11-18)
- Impact: Complete prevention of exception exposure through status endpoint
Technical Details:
# BEFORE (Vulnerable):
status = reset_service.get_current_status() # May return {"error": "File I/O error: ..."}
return jsonify({
'success': True,
'status': status # Error details + tainted data exposed to user
})
# AFTER (Secure - Three layers):
status = reset_service.get_current_status()
# Layer 1: Detect and handle error responses
if isinstance(status, dict) and "error" in status:
current_app.logger.error(f"Mech status service error: {status['error']}", exc_info=True)
return jsonify({'error': 'Failed to retrieve mech status'}), 500
# Layer 2: Strict type validation for complex fields
raw_glvl_values = status.get('glvl_values', [])
safe_glvl_values = []
if isinstance(raw_glvl_values, list):
for val in raw_glvl_values:
if isinstance(val, (int, float)) and not isinstance(val, bool):
safe_glvl_values.append(val) # Only numeric values
# Layer 3: Exception marker filtering for strings
next_level_name = status.get('next_level_name', 'Unknown')
if not isinstance(next_level_name, str) or \
any(x in str(next_level_name) for x in ['Exception', 'Error:', 'Traceback']):
next_level_name = 'Unknown'
# Build safe status with fully validated fields
safe_status = {
'donations_count': int(status.get('donations_count', 0))
if isinstance(status.get('donations_count'), (int, float)) else 0,
'glvl_values': safe_glvl_values, # Validated list
'next_level_name': next_level_name, # Filtered string
# ... all fields with type validation
}
return jsonify({'success': True, 'status': safe_status})Security Rationale: Multi-layer defense ensures no exception data can leak through any field type:
- Error detection catches explicit error responses from service layer
- Type validation ensures only expected data types (int, float, str) are included
- Exception marker filtering prevents exception strings in text fields
- List validation prevents malicious data in array fields (glvl_values)
This comprehensive approach satisfies CodeQL's taint tracking by breaking all possible data flow paths from potentially unsafe service responses.
The Discord bot token can be provided via environment variable for enhanced security.
# Set in docker-compose.yml
environment:
DISCORD_BOT_TOKEN: "your_token_here"Alternatively, configure via Web UI at http://your-server:9374
Security Benefits:
- Token not stored in plaintext when using environment variables
- Token not in version control
- Environment-based configuration
- Automatic fallback to Web UI configuration
Important: This application requires access to the Docker socket. Only deploy in trusted environments.
- Read-only Docker socket mounting (configured in docker-compose.yml)
- Non-root user execution (uid 1000, gid 1000)
- Resource limits (CPU, memory)
- Alpine Linux base with minimal attack surface
docker-compose up -d# Check container runs as non-root
docker exec ddc id
# Check resource limits
docker stats ddc
# Verify Docker socket permissions
docker exec ddc ls -la /var/run/docker.sock- Strong password hashing (PBKDF2-SHA256, 600,000 iterations)
- Secure session cookies
- Rate limiting on authentication
-
Set strong Flask secret key via environment variable:
FLASK_SECRET_KEY="$(openssl rand -hex 32)" -
Set admin password:
- Recommended: Set
DDC_ADMIN_PASSWORDenvironment variable before first start - Alternative: If not set, temporary password is
setup- change immediately via Web UI
- Recommended: Set
-
Enable HTTPS in production environments (recommended)
# In docker-compose.yml or .env file
FLASK_SECRET_KEY="your-64-character-random-secret-key"
DISCORD_BOT_TOKEN="your-discord-token-here"
DDC_ADMIN_PASSWORD="your-secure-admin-password"# Generate Flask secret key
openssl rand -hex 32
# Use this in your docker-compose.yml or .env file- Set
DDC_ADMIN_PASSWORDin your docker-compose.yml or .env file - Start container:
docker-compose up -d - Access Web UI:
http://your-server:9374 - Login with:
admin/ yourDDC_ADMIN_PASSWORD - Configure Discord bot token
- Save configuration
- CodeQL security alerts resolved (XSS, Exception Exposure, URL Sanitization)
- Discord token via environment variable support
- Enhanced Docker socket security
- Non-root container execution
- Resource limits and restrictions
- Strong password hashing (PBKDF2-SHA256)
- Alpine Linux base (minimal vulnerabilities)
- Flask 3.1.1 and Werkzeug 3.1.3 (CVEs resolved)
- Enable HTTPS with valid certificates
- Implement comprehensive rate limiting
- Add security headers (HSTS, CSP)
- Regular dependency updates
- Security monitoring and logging
- Docker socket access provides significant container control
- Default credentials available for initial setup (must be changed)
- Some operations require elevated Docker permissions
# Recommended docker-compose.yml network configuration
networks:
ddc_network:
driver: bridge# Monitor container logs
docker logs ddc
# Check for security events
docker logs ddc | grep -i "security\|error\|warning"# Backup configuration securely
tar czf config_backup.tar.gz config/
# Store backups securely with restricted permissions
chmod 600 config_backup.tar.gz- Immediately rotate Discord bot token in Developer Portal
- Update environment variable or Web UI configuration with new token
- Restart DDC container:
docker-compose restart - Review logs for unauthorized access
- Check Discord server for suspicious activity
- Stop container immediately:
docker stop ddc - Review logs:
docker logs ddc - Check host system for signs of escape
- Rebuild from clean image
- Review and enhance security configuration
For security issues:
- Do not create public GitHub issues
- Report privately to project maintainers
- Include detailed reproduction steps
- Wait for confirmation before public disclosure
Note: Security is an ongoing process. Regularly review and update your security configuration. Monitor the GitHub repository for security updates and advisories.