Harden legacy file paths and Twilio webhook validation

This commit is contained in:
2026-04-26 18:14:16 -04:00
parent 8491b308eb
commit 0ea192d55b
4 changed files with 317 additions and 15 deletions
@@ -22,6 +22,7 @@ public class WebhooksController : ControllerBase
{
private readonly ApplicationDbContext _context;
private readonly IConfiguration _configuration;
private readonly IWebHostEnvironment _environment;
private readonly ILogger<WebhooksController> _logger;
// CTIA-standard opt-out keywords (case-insensitive)
@@ -39,10 +40,12 @@ public class WebhooksController : ControllerBase
public WebhooksController(
ApplicationDbContext context,
IConfiguration configuration,
IWebHostEnvironment environment,
ILogger<WebhooksController> logger)
{
_context = context;
_configuration = configuration;
_environment = environment;
_logger = logger;
}
@@ -269,16 +272,22 @@ public class WebhooksController : ControllerBase
};
/// <summary>
/// Validates the incoming Twilio webhook request using HMAC-SHA1. Skips validation when the
/// auth token is unconfigured so the endpoint works in local development without real Twilio credentials.
/// Validates the incoming Twilio webhook request using HMAC-SHA1. Local development may skip
/// validation when the auth token is unconfigured, but shared environments fail closed.
/// </summary>
private bool ValidateTwilioRequest()
{
var authToken = _configuration["Twilio:AuthToken"];
if (string.IsNullOrWhiteSpace(authToken) || authToken.StartsWith("your-"))
{
_logger.LogDebug("Twilio auth token not configured; skipping signature validation");
return true;
if (_environment.IsDevelopment())
{
_logger.LogDebug("Twilio auth token not configured in development; skipping signature validation");
return true;
}
_logger.LogError("Twilio auth token is not configured; rejecting webhook request");
return false;
}
var signature = Request.Headers["X-Twilio-Signature"].FirstOrDefault() ?? string.Empty;