Description
Symfony version(s) affected
5.4
Description
It is possible to encode a message payload that contains characters forbidden by Amazon SQS. PhpSerializer
used by default checks for binary streams and encodes them using base64, but it fails on detecting all characters forbidden by Amazon.
Code: InvalidMessageContents
Message: Invalid binary character '#xB' was found in the message body, the set of allowed characters is #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF].
Type: Sender
How to reproduce
Dispatch a message encoding a string containing illegal control character, like "vertical tab":
// Assuming we have default messenger transport configured for Amazon SQS
class MyMessage
{
public function __construct(public readonly string $payload) {}
}
// Example using dependency injection
public function __invoke(MessageBusInterface $messageBus) {
$message = new MyMessage("This is my very random string that happens to contain \x1B illegal character.");
$messageBus->dispatch($message); // HTTP 400 here
}
Possible Solution
The test done by PhpSerializer
seems insuficient:
public function encode(Envelope $envelope): array
{
$envelope = $envelope->withoutStampsOfType(NonSendableStampInterface::class);
$body = addslashes(serialize($envelope));
if (!preg_match('//u', $body)) {
$body = base64_encode($body);
}
return [
'body' => $body,
];
}
I would proposed to replace that if
statement with:
// (...)
if (preg_match('/[^\x20-\x{D7FF}\xA\xD\x9\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u', $body)) {
We may also make that test configurable, or just implement own serializer for amazon-sqs-messenger
using base64 encoding.
Additional Context
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html