|
102 | 102 | <tr> |
103 | 103 | <td style="padding: 24px; color: #333333; font-size: 16px; line-height: 1.5"> |
104 | 104 | <p style="margin: 0 0 12px"><strong>Date</strong><br />' . $date->format('m/d/Y H:i:s') . '</p> |
105 | | - <p style="margin: 0 0 12px"><strong>Name</strong><br />' . $name .'</p> |
| 105 | + <p style="margin: 0 0 12px"><strong>Name</strong><br />' . $name . '</p> |
106 | 106 | <p style="margin: 0 0 12px"><strong>Email</strong><br /><a href="mailto:' . $email . '" style="color: #4a90e2; text-decoration: none">' . $email . '</a></p> |
107 | 107 | <p style="margin: 0 0 12px"><strong>Message</strong><br />' . $message . '</p> |
108 | 108 | <hr style="border: none; border-top: 1px solid #dddddd; margin: 24px 0" /> |
@@ -194,15 +194,21 @@ function validateRecaptcha(string $token): void |
194 | 194 | } |
195 | 195 |
|
196 | 196 | /** |
197 | | - * Sanitize input to prevent header injection and XSS |
| 197 | + * Sanitize input to prevent header injection, XSS, and control characters |
198 | 198 | * |
199 | 199 | * @param string $data Raw input string |
200 | | - * @return string Cleaned and safe input |
| 200 | + * @return string Sanitized and safe string |
201 | 201 | */ |
202 | 202 | function sanitize(string $data): string |
203 | 203 | { |
204 | | - $data = preg_replace('/[\r\n]+/', ' ', $data); // Prevent email header injection |
205 | | - return trim(htmlspecialchars($data, ENT_QUOTES, 'UTF-8')); // Escape HTML |
| 204 | + // Remove null bytes and other control characters (except \t) |
| 205 | + $data = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/u', '', $data); |
| 206 | + |
| 207 | + // Prevent header injection by replacing line breaks with spaces |
| 208 | + $data = preg_replace('/\r|\n/', ' ', $data); |
| 209 | + |
| 210 | + // Escape HTML entities (with strict quote handling and UTF-8 safety) |
| 211 | + return trim(htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8', true)); |
206 | 212 | } |
207 | 213 |
|
208 | 214 | /** |
|
0 commit comments