fix: harden URL validation against hostname bypasses (Codex P1)

Codex review found that metadata IPs could be reached via hex
(0xA9FEA9FE), decimal (2852039166), octal, trailing dot, and IPv6
bracket forms. Now normalizes hostnames before checking the blocklist
and probes numeric IP representations via URL constructor.

Also moves URL validation before page allocation in newTab() to
prevent zombie tabs on rejection (Codex P3).

5 new test cases for bypass variants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-03-18 23:46:48 -07:00
parent b57195c051
commit 10329e918f
3 changed files with 65 additions and 6 deletions

View File

@@ -42,6 +42,26 @@ describe('validateNavigationUrl', () => {
expect(() => validateNavigationUrl('http://metadata.google.internal/computeMetadata/v1/')).toThrow(/cloud metadata/i);
});
it('blocks metadata hostname with trailing dot', () => {
expect(() => validateNavigationUrl('http://metadata.google.internal./computeMetadata/v1/')).toThrow(/cloud metadata/i);
});
it('blocks metadata IP in hex form', () => {
expect(() => validateNavigationUrl('http://0xA9FEA9FE/')).toThrow(/cloud metadata/i);
});
it('blocks metadata IP in decimal form', () => {
expect(() => validateNavigationUrl('http://2852039166/')).toThrow(/cloud metadata/i);
});
it('blocks metadata IP in octal form', () => {
expect(() => validateNavigationUrl('http://0251.0376.0251.0376/')).toThrow(/cloud metadata/i);
});
it('blocks IPv6 metadata with brackets', () => {
expect(() => validateNavigationUrl('http://[fd00::]/')).toThrow(/cloud metadata/i);
});
it('throws on malformed URLs', () => {
expect(() => validateNavigationUrl('not-a-url')).toThrow(/Invalid URL/i);
});