Error Handling & Security Headers
Error Handling
Implemented Controls
Error Pages
lib/git_gud_web/controllers/error_html.ex— HTML error pages (404, 500, etc.)lib/git_gud_web/controllers/error_json.ex— JSON error responses- Consistent error format across HTML and JSON endpoints
- Generic messages that don’t leak implementation details
Authentication Errors
- Hook/auth failures log warnings with IP address
- Runner protocol errors return Twirp-style error codes (e.g.,
unauthenticated,invalid_argument) - Generic messages for auth failures — no stack traces or internal details
Runner Protocol Error Handling
runner_controller.ex— Twirp error responses with structured error codes- Protobuf error messages include
codeandmessagefields - Connect-Go client compatibility verified
Database Error Handling
- Ecto changeset errors returned to clients
- No raw SQL errors exposed (Ecto catches and wraps errors)
- Constraint violation errors handled gracefully
Security Headers
Implemented Controls
Browser Pipeline (:browser pipeline)
put_secure_browser_headersplug- Sets standard security headers
- Applied to all browser routes
- Includes:
X-Frame-Options,X-Content-Type-Options,X-XSS-Protection
Session Cookies
- SameSite=Lax on session cookies
- Secure flag for HTTPS-only transmission
- HttpOnly flag on session cookies (prevents JavaScript access)
Runner Protocol Responses
Connection: closeheader on runner protocol responses- Prevents HTTP/1.1 keep-alive framing attacks
- Bandit + forgejo-runner Connect-Go compatibility
Content-Type Headers
- All JSON responses:
application/json - All HTML responses:
text/html - Prevents MIME-type confusion attacks
Security Observations
Medium
No Content-Security-Policy (CSP) header
- CSP provides defense-in-depth against XSS and data injection
- Restricts sources for scripts, styles, images, fonts, etc.
- Recommendation: add CSP header via Plug
- Start with
Content-Security-Policy-Report-Onlyfor testing - Example:
default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; - Gradually tighten as issues are resolved
- Start with
X-Frame-Options not explicitly set
put_secure_browser_headersmay set this, but verify it’s not being strippedX-Frame-Options: DENYprevents clickjacking attacks- Recommendation: explicitly set header via Plug
put_resp_header(conn, "x-frame-options", "deny")
X-Content-Type-Options not explicitly set
put_secure_browser_headersmay set this, but verify it’s not being strippedX-Content-Type-Options: nosniffprevents MIME-type sniffing- Recommendation: explicitly set header
put_resp_header(conn, "x-content-type-options", "nosniff")
No CORS configuration
- Phoenix default applies (permissive)
- API endpoints may be vulnerable to cross-origin attacks
- Recommendation: add CORS headers for API endpoints
cors_pluglibrary or custom Plug- Restrict to known origins for public APIs
- Block all origins for private APIs
LiveDashboard accessible in development
- Phoenix LiveDashboard at
/dashboard/* - Exposes runtime metrics, process info, logger, IEx console
- Critical: IEx console allows arbitrary code execution
- Recommendation: disable
dev_routesin productionconfig :git_gud, GitGudWeb.Endpoint, dev_routes: false- Or restrict to admin users only via plug
MailboxPreview accessible in development
- Swoosh MailboxPreview at
/dev/mailbox - Exposes received emails (including magic links with tokens)
- Recommendation: disable in production
config :swoosh, local: false
Low
Error messages may leak implementation details
- Some error responses include
inspect(reason)which may expose internal state - Example:
actions_artifact_controller.ex:99—Jason.encode!(%{"error" => inspect(reason)}) - Recommendation: use generic error messages for 4xx responses
- Only expose detailed errors for 5xx responses in development mode
Stack traces in development
- Phoenix may display stack traces in development
- Could leak sensitive information (file paths, database queries, etc.)
- Recommendation: ensure
debug_errors: trueis disabled in productionconfig :phoenix, :debug_errors, false
No centralized error monitoring
- Sentry integration exists (
GitGud.SentryClient) but not examined in detail - Verify error monitoring is configured in production
- Recommendation: ensure Sentry DSN is configured via
SENTRY_DSNenvironment variable - Add custom error handlers for critical paths