streamflow/docs/ERROR_HANDLING_SECURITY.md
2025-12-17 00:42:43 +00:00

13 KiB

Error Handling and Logging Security Implementation

Overview

This document describes the comprehensive error handling and logging security implementation that addresses CWE-209: Information Exposure Through Error Messages. The system ensures that sensitive information such as file paths, stack traces, database details, and system internals are never exposed to end users.

Security Objectives

  1. Prevent Information Disclosure: Sanitize all error messages before sending to clients
  2. Secure Logging: Log full error details internally while exposing safe messages externally
  3. User-Friendly Messages: Provide meaningful feedback without technical details
  4. Audit Trail: Maintain comprehensive logs for security monitoring and debugging

Implementation Components

Backend Security

0. Process-Level Error Handlers (backend/server.js)

CWE-391 Compliance:

  • Catches all uncaught exceptions
  • Handles unhandled promise rejections
  • Graceful shutdown on SIGTERM/SIGINT
  • Server error handling
  • Logs all errors before exit

Handlers Implemented:

process.on('uncaughtException', handler)   // Catches sync exceptions
process.on('unhandledRejection', handler)  // Catches async rejections
process.on('SIGTERM', handler)             // Graceful shutdown
process.on('SIGINT', handler)              // Ctrl+C handling
server.on('error', handler)                // Server startup errors

Backend Security

1. Error Handler Utility (backend/utils/errorHandler.js)

Features:

  • Sanitizes error messages before client responses
  • Removes file paths, stack traces, and system information
  • Maps technical errors to user-friendly messages
  • Detects and filters sensitive patterns
  • Provides structured error responses

Error Types Handled:

  • Authentication & Authorization errors
  • Database constraint violations
  • File system errors (ENOENT, EACCES, ENOSPC)
  • Network errors (ECONNREFUSED, ETIMEDOUT, ENOTFOUND)
  • Validation errors
  • Rate limiting

Key Functions:

sanitizeError(error, defaultMessage)  // Sanitizes error for client
logError(error, context)              // Logs full error internally
errorMiddleware(err, req, res, next)  // Express middleware
asyncHandler(fn)                      // Wraps async routes
ErrorResponses.*                      // Standard error creators

2. Enhanced Logger (backend/utils/logger.js)

Security Features:

  • Automatically redacts passwords, tokens, secrets, and API keys
  • Separates error logs from combined logs
  • Supports production and development formats
  • File rotation (5MB files, keep 5 backups)
  • Structured JSON logging for analysis

Sensitive Data Redaction:

// Automatically redacts:
- "password": "[REDACTED]"
- "token": "[REDACTED]"
- "secret": "[REDACTED]"
- "apiKey": "[REDACTED]"
- "authorization": "Bearer [REDACTED]"
- "privateKey": "[REDACTED]"

Additional Helpers:

logger.security(action, details)           // Security event logging
logger.performance(operation, duration)    // Performance monitoring

3. Global Error Middleware (backend/server.js)

Integrated into Express application as the last middleware:

  • Catches all unhandled errors
  • Logs full details internally with context
  • Returns sanitized responses to clients
  • Includes timestamp and error code

Frontend Security

0. Window-Level Error Handlers (frontend/src/main.jsx)

CWE-391 Compliance:

  • Catches all window errors
  • Handles unhandled promise rejections
  • Service worker error handling
  • Prevents default browser error display

Handlers Implemented:

window.addEventListener('error', handler)              // Global errors
window.addEventListener('unhandledrejection', handler) // Promise rejections

Service Worker Protection: (frontend/public/service-worker.js)

self.addEventListener('error', handler)                // SW errors
self.addEventListener('unhandledrejection', handler)   // SW rejections

1. Error Handler Utility (frontend/src/utils/errorHandler.js)

Features:

  • Extracts user-friendly messages from API responses
  • Classifies errors by type (auth, permission, validation, network, server)
  • Determines error severity
  • Provides retry logic for transient failures
  • Never exposes technical details to UI

Key Functions:

getErrorMessage(error, defaultMessage)    // Extract safe message
isAuthError(error)                        // Check if auth error
isPermissionError(error)                  // Check if permission error
isValidationError(error)                  // Check if validation error
isNetworkError(error)                     // Check if network error
getErrorType(error)                       // Classify error type
formatError(error, options)               // Format for display
createErrorNotification(error, options)   // Create notification
retryRequest(fn, options)                 // Retry with backoff

2. Error Boundary Component (frontend/src/components/ErrorBoundary.jsx)

Purpose:

  • Catches JavaScript errors in React component tree
  • Prevents application crashes
  • Displays user-friendly fallback UI
  • Provides recovery options (reset, reload)
  • Does NOT expose stack traces to users

Features:

  • Automatic error counting
  • Reset functionality
  • Full page reload option
  • Localized messages

3. Error Notification Provider (frontend/src/components/ErrorNotificationProvider.jsx)

Global Notification System:

  • Context-based notification management
  • Automatic error type detection
  • Localized error titles and messages
  • Severity-based styling (error, warning, info, success)
  • Auto-dismiss with configurable duration

Usage:

const { showError, showSuccess, showWarning, showInfo } = useErrorNotification();

// Show error from API response
showError(error, { defaultMessage: 'Custom message' });

// Show success message
showSuccess('Operation completed successfully');

4. Enhanced API Client (frontend/src/utils/api.js)

Security Improvements:

  • Automatic error handling with sanitization
  • Timeout configuration (30 seconds)
  • Automatic retry for transient failures
  • Auth error detection and redirect
  • Silent token parsing errors
  • Development-only error logging

Internationalization

Error Message Translations

English (frontend/src/locales/en.json):

"errors": {
  "general": { "unexpected", "tryAgain", "contactSupport" },
  "network": { "title", "message", "timeout", "offline" },
  "auth": { "title", "required", "invalid", "failed", "sessionExpired" },
  "permission": { "title", "message", "adminRequired", "contactAdmin" },
  "validation": { "title", "invalidInput", "requiredField", "invalidFormat" },
  "server": { "title", "message", "unavailable", "maintenance", "overloaded" },
  "notFound": { "title", "message", "page", "resource" },
  "conflict": { "title", "message", "duplicate", "outdated" },
  "rateLimit": { "title", "message", "slowDown" }
}

Romanian (frontend/src/locales/ro.json): Full translations provided for all error categories.

Security Benefits

1. CWE-209 Mitigation

Before:

// Exposed internal details
res.status(500).json({ error: error.message });
// User sees: "ENOENT: no such file or directory, open '/app/data/db/users.db'"

After:

// Sanitized message
const sanitized = sanitizeError(error);
res.status(500).json({ error: sanitized.message });
// User sees: "An internal error occurred"

2. Stack Trace Protection

Before:

Error: Database error
    at /app/backend/routes/users.js:45:12
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

After:

{
  "error": "Database operation failed",
  "code": "DATABASE_ERROR",
  "timestamp": "2025-12-15T10:30:00.000Z"
}

3. Sensitive Data Redaction

Logs automatically redact:

  • Passwords
  • Authentication tokens
  • API keys
  • Secrets
  • Private keys
  • Authorization headers

4. Contextual Logging

Internal logs include:

  • Full error stack trace
  • Request method and path
  • User ID (if authenticated)
  • IP address
  • Timestamp
  • Additional context

Client responses include:

  • Safe error message
  • Error code
  • Timestamp
  • HTTP status code

Usage Examples

Backend Route with Error Handling

const { asyncHandler, ErrorResponses } = require('../utils/errorHandler');

router.get('/users/:id', asyncHandler(async (req, res) => {
  const user = await findUser(req.params.id);
  
  if (!user) {
    throw ErrorResponses.notFound('User not found');
  }
  
  res.json(user);
}));

Frontend Component with Error Handling

import { useErrorNotification } from '../components/ErrorNotificationProvider';
import { getErrorMessage } from '../utils/errorHandler';

function MyComponent() {
  const { showError, showSuccess } = useErrorNotification();
  
  const handleSubmit = async () => {
    try {
      await api.post('/users', data);
      showSuccess('User created successfully');
    } catch (error) {
      showError(error);
    }
  };
}

Custom Error Messages

// Backend
throw ErrorResponses.badRequest('Email address is already in use');

// Frontend automatically displays localized message
// No technical details exposed

Testing

Test Cases

  1. Database Errors

    • UNIQUE constraint → "Duplicate entry exists"
    • NOT NULL constraint → "Required field is missing"
    • Foreign key constraint → "Resource conflict"
  2. File System Errors

    • ENOENT → "File not found"
    • EACCES → "Access forbidden"
    • ENOSPC → "Service temporarily unavailable"
  3. Network Errors

    • ECONNREFUSED → "External service unavailable"
    • ETIMEDOUT → "Request timeout"
    • ENOTFOUND → "Network request failed"
  4. Authentication Errors

    • Invalid token → "Invalid or expired authentication token"
    • Missing auth → "Authentication required"
    • Expired session → "Your session has expired"

Manual Testing

# Test error sanitization
curl http://localhost:12345/api/nonexistent
# Should return: {"error": "Resource not found", ...}
# Should NOT expose file paths or stack traces

# Test authentication error
curl http://localhost:12345/api/users
# Should return: {"error": "Authentication required", ...}

# Test rate limiting
# Make 100+ rapid requests
# Should return: {"error": "Too many requests. Please try again later", ...}

Monitoring and Maintenance

Log Files

Location: /app/logs/

  • error.log - Error-level events only
  • combined.log - All application logs

Rotation: 5MB per file, keep 5 files

Security Events

Monitor for:

  • Unusual error patterns
  • Repeated authentication failures
  • Rate limit violations
  • Permission denied attempts
  • Database constraint violations

Performance Monitoring

const start = Date.now();
await performOperation();
logger.performance('operation_name', Date.now() - start);

Docker Integration

All changes are automatically included in Docker builds:

# Logs directory created with correct permissions
# Error handling utilities bundled
# Frontend error components included
# Translations packaged

PWA & Desktop App Compatibility

  • Error boundary works in all environments
  • Service worker error handling included
  • Electron app error logging configured
  • APK builds include error handling

Best Practices

DO:

Use ErrorResponses for standard errors Use asyncHandler for async routes Log errors with context using logError() Use useErrorNotification() in React components Provide user-friendly error messages Include error codes for debugging

DON'T:

Never send error.stack to clients Never expose file paths in error messages Never include database query details in responses Never log passwords or tokens Never use console.error() for sensitive data Never expose internal implementation details

Compliance

This implementation addresses:

  • CWE-209: Information Exposure Through Error Messages
  • CWE-391: Unchecked Error Condition
  • OWASP A01:2021: Broken Access Control
  • OWASP A07:2021: Identification and Authentication Failures
  • OWASP A09:2021: Security Logging and Monitoring Failures

Summary

The error handling and logging security implementation provides:

  1. Complete CWE-209 mitigation - No information leakage
  2. Complete CWE-391 compliance - No unhandled exceptions
  3. Secure logging - Full internal logs, safe external messages
  4. User-friendly errors - Clear, actionable messages
  5. Multi-language support - English and Romanian translations
  6. Global error handling - Process, window, and component level
  7. Structured logging - JSON format for analysis
  8. Automatic sanitization - Passwords, tokens, secrets redacted
  9. Docker integration - All changes bundled
  10. PWA/Desktop compatible - Works in all environments
  11. Service worker protection - Error handling in SW context
  12. Production-ready - Tested and documented

All existing features remain functional. No breaking changes introduced.