fix(notifications): validate Twilio AccountSid format at save — closes the un-escaped URI interpolation door

Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
Joseph Doherty
2026-07-10 04:36:19 -04:00
parent 37cf7c1a44
commit 40088a2123
4 changed files with 90 additions and 19 deletions
@@ -226,6 +226,15 @@
return;
}
// The AccountSid is interpolated un-escaped into the Twilio request URI, so reject
// any malformed SID client-side too (the ManagementActor enforces the same guard
// server-side; keep the message identical).
if (!System.Text.RegularExpressions.Regex.IsMatch(_accountSid.Trim(), "^AC[0-9a-fA-F]{32}$"))
{
_formError = "Account SID must match Twilio's format: 'AC' followed by 32 hex characters.";
return;
}
var typedAuthToken = string.IsNullOrWhiteSpace(_authToken) ? null : _authToken.Trim();
try
@@ -1897,6 +1897,11 @@ public class ManagementActor : ReceiveActor
var configs = await repo.GetAllSmsConfigurationsAsync();
var config = configs.FirstOrDefault(c => c.Id == cmd.SmsConfigId)
?? throw new ManagementCommandException($"SmsConfiguration with ID {cmd.SmsConfigId} not found.");
// The AccountSid is interpolated un-escaped into the Twilio request URI
// (SmsNotificationDeliveryAdapter). Reject any value that is not a well-formed
// Twilio SID at save time, closing the URI-injection door before it is persisted.
if (!System.Text.RegularExpressions.Regex.IsMatch(cmd.AccountSid, "^AC[0-9a-fA-F]{32}$"))
throw new ManagementCommandException("Account SID must match Twilio's format: 'AC' followed by 32 hex characters.");
config.AccountSid = cmd.AccountSid;
config.FromNumber = cmd.FromNumber;
config.MessagingServiceSid = cmd.MessagingServiceSid;