Skip to content

Prevent internal error details from reaching API clients and add safe Kiroo replay IDs #378

Description

@anshul23102

Summary

Unhandled exceptions must not expose internal details to API clients.

The current pattern returns a generic response in some controllers. It does not provide a consistent final error boundary. Express can return a stack trace when an error reaches its default error handler. The application also needs a safe way to correlate a client error with a reproducible Kiroo capture.

Use @kiroo/sdk for request/response replay IDs. Do not use Kiroo as the only production error log. Kiroo captures the request and response. It does not capture the JavaScript stack trace.

Kiroo prerequisite

Release a Kiroo version that meets these requirements before this application uses Kiroo captures in production.

  1. Redact sensitive values in all captured locations:
    • request headers;
    • response headers;
    • request-body fields;
    • response-body fields;
    • URL query parameters.
  2. Preserve recursive, case-insensitive redaction for object keys.
  3. Provide configuration for application-specific redaction:
    • redactKeys;
    • redactHeaders;
    • redactQueryParams;
    • a custom redaction callback, if supported.
  4. Include safe default redaction for credential fields and common personal-data fields.
  5. Sanitize response headers before Kiroo stores them. @kiroo/sdk 0.1.2 stores res.getHeaders() without sanitization.
  6. Document that the Supabase bucket must be private, that capture access must be restricted, and that retention must meet the application's privacy policy.
  7. Document that Kiroo does not capture a JavaScript stack trace. The application must keep stack traces in protected server-side logs.
  8. Update the Kiroo error example. It must not return internal error text such as "Downstream timeout" to a client.
  9. Add tests for nested fields, case variants, query parameters, request headers, and response headers.

@kiroo/sdk 0.1.2 already provides an X-Kiroo-Replay-ID header and captures all responses with status >=400, even when sampleRate is 0.

Application changes

  1. Register a final Express error-handling middleware after all routes.
  2. Log the error, stack trace, HTTP method, route, and Kiroo replay ID to protected server-side logs.
  3. Return a generic 500 response for unexpected errors.
  4. Include the Kiroo replay ID in the generic error response.
  5. Do not return err.message, err.stack, database errors, upstream error payloads, or internal file paths.
  6. Keep Kiroo capture middleware before routes and the final error handler.
  7. Configure sampleRate: 0 if the application must capture only error responses. Kiroo still captures status codes >=400.

Example response shape:

const replayId = res.get("X-Kiroo-Replay-ID");

res.status(500).json({
  success: false,
  message: "Internal server error",
  data: { replayId }
});

Debugging workflow

  1. A client receives a generic error response and replayId.
  2. The operator locates the protected server-side error log by replayId.
  3. The operator uses the replay ID with Kiroo to fetch and replay the sanitized request locally.
  4. The operator uses the protected server-side log for the stack trace.

Acceptance criteria

  • API clients never receive stack traces or unexpected internal error details.
  • The final Express error handler handles errors that reach it.
  • Each error response contains the Kiroo replay ID.
  • Production logs contain the stack trace and the same replay ID.
  • Kiroo captures redact the configured credentials and personal data from bodies, headers, and URL query parameters.
  • Kiroo storage is private and has documented retention and access controls.
  • Tests cover the final error handler and Kiroo redaction behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions