@@ -2,28 +2,34 @@ import { pluginCollapsibleSections } from "@expressive-code/plugin-collapsible-s
22import { ExpressiveCodeTheme } from "@astrojs/starlight/expressive-code" ;
33import fs from "node:fs" ;
44import path from "node:path" ;
5+ import { fileURLToPath } from "node:url" ;
56
6- // Define allowed paths relative to project root
7+ // Define allowed paths relative to this config file's directory
78const ALLOWED_PATHS = [ "src/themes/expressive-code" ] ;
89
910function readFileSyncSafe ( url ) {
1011 if ( url . protocol !== "file:" ) {
1112 throw new Error ( "Invalid URL protocol" ) ;
1213 }
1314
14- // Convert URL to filesystem path and normalize
15- const filePath = path . normalize ( url . pathname ) ;
15+ // Convert URL to filesystem path and normalize (Windows-safe)
16+ const filePath = path . normalize ( fileURLToPath ( url ) ) ;
1617
17- // Ensure path is within allowed directories
18- const isAllowed = ALLOWED_PATHS . some ( ( allowedPath ) =>
19- filePath . includes ( path . normalize ( allowedPath ) )
20- ) ;
18+ // Resolve allowed directories relative to this file's directory
19+ const baseDir = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
20+ const allowedAbs = ALLOWED_PATHS . map ( ( p ) => path . resolve ( baseDir , p ) ) ;
21+
22+ // Ensure path is within one of the allowed directories using path.relative
23+ const isAllowed = allowedAbs . some ( ( allowedDir ) => {
24+ const rel = path . relative ( allowedDir , filePath ) ;
25+ return rel && ! rel . startsWith ( ".." ) && ! path . isAbsolute ( rel ) ;
26+ } ) ;
2127
2228 if ( ! isAllowed ) {
23- throw new Error ( " Access to this directory is not allowed" ) ;
29+ throw new Error ( ` Access to this file is not allowed: ${ filePath } ` ) ;
2430 }
2531
26- return fs . readFileSync ( url , "utf-8" ) ;
32+ return fs . readFileSync ( filePath , "utf-8" ) ;
2733}
2834
2935const jsoncStringLight = readFileSyncSafe (
0 commit comments