Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
EmailHeaderSanitizer
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
2 / 2
3
100.00% covered (success)
100.00%
1 / 1
 assertSafeHeader
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 sanitizeHeader
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Modules\Mail\Application\Service;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use InvalidArgumentException;
12
13/**
14 * Email Header Injection Sanitizer & Validator (OWASP ASVS 5.2.2).
15 *
16 * Protects against CRLF injection, carriage return, and newline smuggling in mail headers:
17 * - From / To / Cc / Bcc addresses
18 * - Subject and Reply-To headers
19 *
20 * @package App\Modules\Mail\Application\Service
21 */
22final readonly class EmailHeaderSanitizer
23{
24    /**
25     * Validates that an email header string contains no carriage returns, newlines, or control chars.
26     *
27     * @param string $value Header value to inspect.
28     * @param string $headerName Context header name for exception messaging.
29     * @return string Validated trimmed string.
30     * @throws InvalidArgumentException When CRLF or illegal control character is detected.
31     */
32    public static function assertSafeHeader(string $value, string $headerName = 'Header'): string
33    {
34        if (preg_match('/[\x00-\x1F\x7F]/', $value) === 1) {
35            throw new InvalidArgumentException(
36                sprintf('Potential email header injection (CRLF) detected in %s.', $headerName)
37            );
38        }
39
40        return trim($value);
41    }
42
43    /**
44     * Strips any CRLF or illegal control characters from an input string.
45     *
46     * @param string $value Raw string.
47     * @return string Sanitized single-line string.
48     */
49    public static function sanitizeHeader(string $value): string
50    {
51        return trim((string) preg_replace('/[\x00-\x1F\x7F]+/', ' ', $value));
52    }
53}