secure_errors
Secure-by-default error handling for HTTP services (OWASP C10). Part of the SunLit Security Libraries workspace.
The problem this crate solves
Most Rust web services accidentally leak internal details — SQL fragments, hostnames, stack traces — through error responses. This crate enforces a three-layer model:
AppError— internal layer, full detail, never serialized to the wire.PublicError— the only type that may be serialized to HTTP responses. Stable, redaction-safe.ErrorClassification— operational metadata: retryability, alerting hints, signals.
A single source-of-truth mapper (http::into_response_parts) turns AppError into HTTP responses, so an axum service and an actix-web service emit byte-identical wire payloads for the same error.
Install
[]
= "0.1.2" # default: axum
# For actix-web instead of axum:
# secure_errors = { version = "0.1.2", default-features = false, features = ["actix-web"] }
# Both at once (e.g. workspace with services on both):
# secure_errors = { version = "0.1.2", features = ["axum", "actix-web"] }
Quick example (axum)
use ;
use AppError;
use ErrorMappingLayer;
async
async
let app = new
.route
.route
.layer;
// Both routes emit a stable PublicError JSON. /throttled adds Retry-After: 30.
// Internal details (dependency name, validation code) never reach the client.
Quick example (actix-web)
use ;
use AppError;
async
new
.bind?
.run
.await
See examples/actix_error_minimal.rs for a complete runnable service.
Design invariants
PublicErroris the only type that may reach an HTTP wire.http::into_response_partsis the only place that maps errors to HTTP status codes — guaranteed cross-framework parity.- No internal text (SQL fragments, hostnames, stack traces, validation reason codes) may appear in
PublicError. - The internal
AppError::Internal { detail }variant carries free-form detail for logs; the public response says only "internal_error".
Feature flags
| Flag | Default | Enables |
|---|---|---|
axum |
✅ | middleware::ErrorMappingLayer (tower) and impl IntoResponse for AppError |
actix-web |
off | impl actix_web::ResponseError for AppError (see actix module) |
Compatibility
- MSRV: 1.78
#![forbid(unsafe_code)],#![deny(missing_docs)],#![deny(clippy::all, clippy::pedantic)]
Status
Alpha.
Related crates
Part of the SunLit Security Libraries workspace:
| Crate | Purpose |
|---|---|
security_core |
Shared types, identity, classification, severity, redaction. |
security_events |
Security logging and tamper-evident audit chain. |
secure_output |
Context-aware output encoders (HTML, JSON, URL, JS, CSS, XML, LDAP, shell). |
secure_data |
Secrets, envelope encryption, Argon2id, FIPS, mobile storage. |
secure_network |
TLS policy, SPKI pinning, mTLS, cleartext detection. |
secure_device_trust |
Native-client device trust and session certificates. |
secure_resilience |
RASP and environment-detection policy. |
secure_privacy |
PII classification, consent, retention, pseudonymization. |
secure_boundary |
Input validation, security headers, boundary protections. |
secure_identity |
JWT/OIDC, MFA, sessions, biometric step-up. |
secure_authz |
Typed deny-by-default authorization with device-trust predicates. |
Getting help
- Questions, ideas, design discussions — open a GitHub Discussion.
- Bug reports — use the bug-report template in GitHub Issues.
- Security issues — please do not open a public issue. See SECURITY.md for the responsible-disclosure process.
Contributing
Contributions are welcome. Please read CONTRIBUTING.md and the Code of Conduct before opening a PR.
License
Dual-licensed under MIT or Apache-2.0 at your option.