@@ -106,13 +106,27 @@ if (!serverConfig.DISABLE_MANAGER) router.use('/manager', new ViewsRouter().rout
106106
107107router . get ( '/assets/*' , ( req , res ) => {
108108 const fileName = req . params [ 0 ] ;
109+
110+ // Security: Reject paths containing traversal patterns
111+ if ( ! fileName || fileName . includes ( '..' ) || fileName . includes ( '\\' ) || path . isAbsolute ( fileName ) ) {
112+ return res . status ( 403 ) . send ( 'Forbidden' ) ;
113+ }
114+
109115 const basePath = path . join ( process . cwd ( ) , 'manager' , 'dist' ) ;
116+ const assetsPath = path . join ( basePath , 'assets' ) ;
117+ const filePath = path . join ( assetsPath , fileName ) ;
110118
111- const filePath = path . join ( basePath , 'assets/' , fileName ) ;
119+ // Security: Ensure the resolved path is within the assets directory
120+ const resolvedPath = path . resolve ( filePath ) ;
121+ const resolvedAssetsPath = path . resolve ( assetsPath ) ;
122+
123+ if ( ! resolvedPath . startsWith ( resolvedAssetsPath + path . sep ) && resolvedPath !== resolvedAssetsPath ) {
124+ return res . status ( 403 ) . send ( 'Forbidden' ) ;
125+ }
112126
113- if ( fs . existsSync ( filePath ) ) {
114- res . set ( 'Content-Type' , mimeTypes . lookup ( filePath ) || 'text/css' ) ;
115- res . send ( fs . readFileSync ( filePath ) ) ;
127+ if ( fs . existsSync ( resolvedPath ) ) {
128+ res . set ( 'Content-Type' , mimeTypes . lookup ( resolvedPath ) || 'text/css' ) ;
129+ res . send ( fs . readFileSync ( resolvedPath ) ) ;
116130 } else {
117131 res . status ( 404 ) . send ( 'File not found' ) ;
118132 }
0 commit comments