fix(@angular/build): escape hostname in host-validation 403 error page - #33673
fix(@angular/build): escape hostname in host-validation 403 error page#33673deprrous wants to merge 1 commit into
Conversation
The Host header value was interpolated directly into the HTML response without entity encoding. While browsers set Host automatically (preventing direct exploitation), a raw HTTP request with HTML metacharacters in the Host header would reflect unescaped content in a text/html response. Add escapeHtml() to encode &, <, >, and " before interpolation.
There was a problem hiding this comment.
Code Review
This pull request introduces an escapeHtml utility function to sanitize the hostname displayed in the 403 HTML error page of the host check middleware, mitigating potential HTML injection. The reviewer suggested optimizing this function by using a single regular expression with a character map lookup instead of chained .replace calls, and extending it to escape single quotes (') to ensure robust XSS prevention.
| function escapeHtml(value: string): string { | ||
| return value | ||
| .replace(/&/g, '&') | ||
| .replace(/</g, '<') | ||
| .replace(/>/g, '>') | ||
| .replace(/"/g, '"'); | ||
| } |
There was a problem hiding this comment.
The current implementation of escapeHtml uses multiple chained .replace calls with regular expressions, which results in multiple string allocations and full-string scans. Additionally, it does not escape the single quote ('), which is a standard HTML entity that should be escaped to prevent potential XSS vulnerabilities in attribute contexts.
Using a single regular expression with a character class and a map lookup is more efficient and allows us to easily include the single quote (') in the escaped characters.
function escapeHtml(value: string): string {
const entityMap: Record<string, string> = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
};
return value.replace(/[&<>"']/g, (s) => entityMap[s]);
}|
Thank you for reporting this and submitting a PR. We are closing this as it is not an exploitable security vulnerability. For a reflected XSS attack to be exploitable against a victim, an attacker must be able to trick a victim's browser into sending the malicious payload to the server. Since |
Problem
The
html403()function inhost-check-middleware.tsinterpolatesreq.headers.hostdirectly into an HTML response without entity encoding:The response is served with
Content-Type: text/html. A raw HTTP request with HTML metacharacters in theHostheader reflects unescaped content.Reproduction
ng serve --host 0.0.0.0 --port 4200 curl -s -H 'Host: <img src=x onerror=alert(document.domain)>' http://127.0.0.1:4200/Response body contains the unescaped payload in a
text/htmlresponse.Fix
Add
escapeHtml()to encode&,<,>, and"before interpolation into the HTML template.