Pii Leakage in Aspnet with Bearer Tokens
Pii Leakage in Aspnet with Bearer Tokens — how this specific combination creates or exposes the vulnerability
In ASP.NET applications, PII leakage with Bearer Tokens commonly occurs when token handling logic unintentionally exposes sensitive data in logs, error messages, or responses. A typical pattern is storing user identifiers or scopes directly within the token payload or reflecting token details in HTTP responses without proper controls.
Consider an endpoint that returns user profile information and echoes the Authorization header value without redaction:
// Example of vulnerable behavior in an ASP.NET Core controller
[Authorize(AuthenticationSchemes = "Bearer")]
[ApiController]
[Route("[controller]")]
public class ProfileController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
var authHeader = Request.Headers["Authorization"].ToString();
// Vulnerable: including raw token in response
return Ok(new { User = User.Identity.Name, AuthHeader = authHeader });
}
}
If this response is logged or cached, the Bearer Token may be stored in plaintext alongside PII such as the username, creating a compound exposure. Attackers who gain access to logs or error reports can recover both the PII and the token, leading to account compromise.
Additionally, misconfigured CORS or HTTP caching can cause tokens and associated PII to be stored in browser history or intermediate caches. For example, if an ASP.NET app sets permissive CORS policies and does not mark responses containing tokens as private, a cached response may be served to unauthorized users, leaking both PII and authentication material.
Another vector involves error handling that includes token details in exception messages. In ASP.NET, unhandled exceptions that surface in development error pages or logs might include the Authorization header value, especially if developers inadvertently include the header in diagnostic strings. This can expose PII bound to the token (such as user ID or email) and the token itself.
Middleware that inspects or enriches requests must also avoid propagating tokens in logs or diagnostics. Even when using standard authentication handlers, custom logging that concatenates user claims with token strings can inadvertently create searchable stores of PII and credentials. These patterns align with common OWASP API Top 10 risks such as excessive data exposure and insufficient logging/monitoring.
Bearer Tokens-Specific Remediation in Aspnet — concrete code fixes
Remediation focuses on ensuring Bearer Tokens are never reflected in responses, logs, or error messages, and that PII is minimized and protected at the application layer.
1. Avoid echoing the Authorization header in responses. Instead, extract only the necessary claims after validating the token:
// Secure pattern: do not return the token; use claims from User
[Authorize(AuthenticationSchemes = "Bearer")]
[ApiController]
[Route("[controller]")]
public class ProfileController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
var userId = User.FindFirst("sub")?.Value;
var email = User.FindFirst("email")?.Value;
// Return only necessary, consented data
return Ok(new { UserId = userId, Email = email });
}
}
2. Configure logging to redact or exclude Authorization headers. In ASP.NET Core, you can filter sensitive headers in diagnostic sources:
// In Program.cs or Startup.cs
builder.Logging.AddFilter("Microsoft.AspNetCore.HttpLogging", LogLevel.Warning);
// Or use a custom filter to scrub headers
app.Use(async (context, next) =>
{
var originalBody = context.Response.Body;
try
{
await next.Invoke();
}
finally
{
// Ensure no token is written to logs inadvertently
// Use structured logging with property filters instead of raw header capture
}
});
3. Apply data protection and cache-control headers to reduce caching of sensitive responses:
[HttpGet]
[ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)]
[Authorize(AuthenticationSchemes = "Bearer")]
public IActionResult Get()
{
// Response will not be stored by shared caches
return Ok(new { Message = "Private data" });
}
4. Use policy-based authorization to ensure users only access their own data, reducing unnecessary PII exposure in responses:
services.AddAuthorization(options =>
{
options.AddPolicy("OwnData", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c => c.Type == "sub") &&
context.Resource is HttpContext httpContext &&
httpContext.Request.RouteValues["id"]?.ToString() == context.User.FindFirst("sub")?.Value));
});
5. Rotate and scope tokens appropriately. Short-lived access tokens with limited scopes reduce the impact if PII is inadvertently associated with a token. Store refresh tokens securely server-side and avoid embedding PII in token payloads.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |