-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
securitySecurity related issuesSecurity related issues
Description
Security Issue
Severity: Severe
Related PR: #30
Description
Error handlers return detailed internal information that aids attackers in reconnaissance and exploitation.
Vulnerable Code
- Webhook Error Handler (
backend/app/api/webhooks.py:54,93):
except Exception as e:
print(f"❌ Webhook error: {e}")
return {"status": "error", "message": str(e)} # ❌ Full exception exposed- Kestra Client (
backend/app/core/kestra_client.py):
except Exception as e:
return {"success": False, "error": str(e)} # ❌ Raw exception stringInformation Disclosed
Stack Traces (likely in development mode):
- Internal file paths
- Python version and library versions
- Database connection strings
- Function names and code structure
Error Messages May Reveal:
Connection refused→ Internal service down/unreachableName or service not known→ Invalid hostname (internal network)Timeout→ Service exists but slow/overloadedKeyError: 'field'→ Expected data structureImportError→ Missing dependencies or version mismatch
Example Attack
# Probe internal services
curl -X POST http://api/kestra/trigger \
-d '{"repository_url": "http://internal-service:8080/"}'
# Response reveals:
# {"success": false, "error": "ConnectionError: Cannot connect to internal-service:8080"}
# Attacker now knows: internal network layout, service names, portsSecurity Impact
- Reconnaissance: Attackers learn system architecture
- Version Detection: Identifies vulnerable dependencies
- Path Disclosure: Reveals file system structure
- Service Discovery: Maps internal network topology
- Exploit Development: Detailed errors help craft exploits
Remediation
- Generic Error Messages for Users:
import logging
logger = logging.getLogger(__name__)
try:
result = await kestra.trigger_flow(url, branch)
except Exception as e:
logger.error("Flow trigger failed", exc_info=True) # Log full details
return {
"success": False,
"error": "Failed to trigger workflow" # Generic message
}- Error Classification:
class SafeError(Exception):
"""Errors safe to expose to users."""
pass
def handle_error(e: Exception) -> dict:
if isinstance(e, SafeError):
return {"error": str(e)}
else:
logger.error("Internal error", exc_info=True)
return {"error": "An internal error occurred"}- Global Exception Handler:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception):
logger.error(
"Unhandled exception",
exc_info=exc,
extra={"path": request.url.path, "method": request.method}
)
if os.getenv("ENV") == "production":
return JSONResponse(
status_code=500,
content={"error": "Internal server error"}
)
else:
# Development only
return JSONResponse(
status_code=500,
content={"error": str(exc), "type": type(exc).__name__}
)- Validate Before Processing:
def validate_repository_url(url: str):
if not url.startswith("https://github.com/"):
raise SafeError("Only GitHub HTTPS URLs are supported")
# More validation...Configuration
# .env
ENV=production # Controls error verbosity
DEBUG=falseFiles to Update
backend/app/api/webhooks.pybackend/app/core/kestra_client.pybackend/app/api/routes.pybackend/app/main.py(global handler)
Assignee: @haroon0x
Metadata
Metadata
Assignees
Labels
securitySecurity related issuesSecurity related issues