@@ -3,7 +3,10 @@ import { mkdtemp, mkdir, rm, symlink, writeFile } from 'node:fs/promises'
33import { tmpdir } from 'node:os'
44import { join } from 'node:path'
55import { afterEach , describe , it } from 'node:test'
6- import { isBrowserRequestAllowed } from './browser-network-policy.ts'
6+ import {
7+ isBrowserPageNavigationAllowed ,
8+ isBrowserRequestAllowed ,
9+ } from './browser-network-policy.ts'
710import {
811 flushPreviewStaleForTest ,
912 getStaticPreviewServer ,
@@ -41,7 +44,6 @@ describe('static browser preview server', () => {
4144 assert . equal ( second . url , first . url )
4245 assert . match ( first . url , / ^ h t t p : \/ \/ l o c a l h o s t : \d + \/ $ / )
4346 assert . equal ( isStaticPreviewUrl ( first . url ) , true )
44- assert . equal ( isStaticPreviewUrl ( first . url . replace ( 'localhost' , '127.0.0.1' ) ) , false )
4547 assert . equal ( isStaticPreviewUrl ( 'http://localhost:9/' ) , false )
4648 assert . equal (
4749 isBrowserRequestAllowed ( {
@@ -71,6 +73,33 @@ describe('static browser preview server', () => {
7173 assert . equal ( await stylesheet . text ( ) , 'body { color: plum; }' )
7274 } )
7375
76+ it ( 'keeps prototype isolation when its listener is opened through an IP alias' , async ( ) => {
77+ const root = await temporaryRoot ( 'copse-static-preview-alias-' )
78+ await writeFile ( join ( root , 'index.html' ) , '<h1>Prototype</h1>' )
79+ const preview = await getStaticPreviewServer ( root )
80+ const alias = preview . url . replace ( 'localhost' , '127.0.0.1' )
81+ assert . equal ( await ( await fetch ( alias ) ) . text ( ) , '<h1>Prototype</h1>' )
82+ for ( const host of [ '127.0.0.1' , '[::ffff:127.0.0.1]' , 'localhost.' , 'preview.localhost' ] ) {
83+ const url = preview . url . replace ( 'localhost' , host )
84+ assert . equal ( isStaticPreviewUrl ( url ) , true )
85+ assert . equal ( isBrowserPageNavigationAllowed ( url , 'https://example.com/leak' ) , false )
86+ assert . equal ( isBrowserPageNavigationAllowed ( url , new URL ( 'next.html' , url ) . href ) , true )
87+ assert . equal (
88+ isBrowserRequestAllowed ( {
89+ documentUrl : url ,
90+ url : 'https://example.com/theme.css' ,
91+ resourceType : 'stylesheet' ,
92+ allowedOrigins : [ 'https://example.com' ] ,
93+ } ) ,
94+ false ,
95+ )
96+ }
97+ assert . equal ( isStaticPreviewUrl ( preview . url . replace ( 'http:' , 'https:' ) ) , false )
98+ assert . equal ( isStaticPreviewUrl ( preview . url . replace ( 'localhost' , 'example.com' ) ) , false )
99+ await shutdownStaticPreviewServers ( )
100+ assert . equal ( isStaticPreviewUrl ( alias ) , false )
101+ } )
102+
74103 it ( 'reports a preview stale for any file it served, not just the entry page' , async ( ) => {
75104 const root = await temporaryRoot ( 'copse-static-preview-served-' )
76105 await mkdir ( join ( root , 'assets' ) )
0 commit comments