@@ -394,7 +394,10 @@ const downloadFromURL = async function (command, options, argumentName, function
394394 folderContents . map ( async ( { download_url : downloadUrl , name } ) => {
395395 try {
396396 const res = await fetch ( downloadUrl )
397- const finalName = path . basename ( name , '.js' ) === functionName ? `${ nameToUse } .js` : name
397+ // SAFE:
398+ const finalName = path . basename ( name , '.js' ) === functionName
399+ ? `${ nameToUse } .js`
400+ : path . basename ( name ) // ← strip any directory components
398401 const dest = fs . createWriteStream ( path . join ( fnFolder , finalName ) )
399402 res . body ?. pipe ( dest )
400403 } catch ( error_ ) {
@@ -744,14 +747,20 @@ const registerEFInToml = async (funcName, options) => {
744747 * @returns
745748 */
746749// @ts -expect-error TS(7006) FIXME: Parameter 'functionsDir' implicitly has an 'any' t... Remove this comment to see the full error message
747- const ensureFunctionPathIsOk = function ( functionsDir , name ) {
748- const functionPath = path . join ( functionsDir , name )
749- if ( fs . existsSync ( functionPath ) ) {
750- log ( `${ NETLIFYDEVLOG } Function ${ functionPath } already exists, cancelling...` )
751- process . exit ( 1 )
750+ const ensureFunctionPathIsOk = function ( functionsDir , name ) {
751+ // Prevent path traversal: reject names like "../../evil"
752+ const resolvedFunctionsDir = path . resolve ( functionsDir )
753+ const functionPath = path . join ( resolvedFunctionsDir , name )
754+ if ( ! functionPath . startsWith ( resolvedFunctionsDir + path . sep ) ) {
755+ log ( `${ NETLIFYDEVERR } Invalid function name: "${ name } " resolves outside the functions directory.` )
756+ process . exit ( 1 )
757+ }
758+ if ( fs . existsSync ( functionPath ) ) {
759+ log ( `${ NETLIFYDEVLOG } Function ${ functionPath } already exists, cancelling...` )
760+ process . exit ( 1 )
761+ }
762+ return functionPath
752763 }
753- return functionPath
754- }
755764
756765// Scans `functions-templates/<lang>` for a template whose `.mjs` metadata
757766// `name` matches. Returns its `functionType` and the language folder it lives
0 commit comments