@@ -29,6 +29,22 @@ export class MediaValidationError extends Error {
2929 }
3030}
3131
32+ async function assertNoSymbolicLinkSegments ( filePath : string ) : Promise < void > {
33+ const root = path . parse ( filePath ) . root ;
34+ const relative = path . relative ( root , filePath ) ;
35+ let current = root ;
36+ for ( const segment of relative . split ( path . sep ) ) {
37+ if ( ! segment ) continue ;
38+ current = path . join ( current , segment ) ;
39+ const segmentStat = await fs . lstat ( current ) ;
40+ if ( segmentStat . isSymbolicLink ( ) ) {
41+ throw new MediaValidationError (
42+ "Media path must not traverse a symbolic link or reparse point." ,
43+ ) ;
44+ }
45+ }
46+ }
47+
3248export function isMp4Container (
3349 bytes : Uint8Array ,
3450 totalSize : number = bytes ?. byteLength ?? 0 ,
@@ -65,11 +81,9 @@ async function assertRegularFile(filePath: string): Promise<{
6581 return process . platform === "win32" ? resolved . toLowerCase ( ) : resolved ;
6682 } ;
6783 if ( normalizeForCompare ( realPath ) !== normalizeForCompare ( resolvedInput ) ) {
68- // realpath changed the path: an intermediate link or reparse point was
69- // traversed. The leaf-link case was rejected above.
70- throw new MediaValidationError (
71- "Media path must not traverse a symbolic link or reparse point." ,
72- ) ;
84+ // realpath can also expand a harmless Windows 8.3 path alias. Inspect each
85+ // segment so only an actual symlink or junction is rejected.
86+ await assertNoSymbolicLinkSegments ( resolvedInput ) ;
7387 }
7488 const stat = await fs . stat ( realPath ) ;
7589 if ( ! stat . isFile ( ) ) {
0 commit comments