{"record":{"id":"0d805fa035d29bb9","repo":"usebruno/bruno","slug":"invalid-env-filename","errorCode":null,"errorMessage":"Invalid .env filename","messagePattern":"Invalid \\.env filename","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-electron/src/ipc/collection.js","lineNumber":858,"sourceCode":"      const format = getCollectionFormat(collectionPathname);\n      const envFilePath = resolveEnvironmentFilePath(collectionPathname, environmentName, format);\n      if (!fs.existsSync(envFilePath)) {\n        throw new Error(`environment: ${envFilePath} does not exist`);\n      }\n\n      fs.unlinkSync(envFilePath);\n\n      environmentSecretsStore.deleteEnvironment(collectionPathname, environmentName);\n    } catch (error) {\n      return Promise.reject(error);\n    }\n  });\n\n  // Save .env file variables for collection\n  ipcMain.handle('renderer:save-dotenv-variables', async (event, collectionPathname, variables, filename = '.env') => {\n    try {\n      if (!isValidDotEnvFilename(filename)) {\n        throw new Error('Invalid .env filename');\n      }\n\n      validatePathIsInsideCollection(collectionPathname);\n\n      const dotEnvPath = path.join(collectionPathname, filename);\n      const content = utils.jsonToDotenv(variables);\n      await writeFile(dotEnvPath, content);\n\n      return { success: true };\n    } catch (error) {\n      console.error('Error saving .env file:', error);\n      return Promise.reject(error);\n    }\n  });\n\n  // Save .env file raw content for collection\n  ipcMain.handle('renderer:save-dotenv-raw', async (event, collectionPathname, content, filename = '.env') => {\n    try {","sourceCodeStart":840,"sourceCodeEnd":876,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-electron/src/ipc/collection.js#L840-L876","documentation":"Thrown by 'renderer:save-dotenv-variables' when isValidDotEnvFilename(filename) returns false. That validator requires filename to be exactly '.env' or to match /^\\.env\\.[a-zA-Z0-9._-]+$/, with no path separators (basename must equal the whole input). The default filename parameter is '.env'.","triggerScenarios":"Passing a filename like 'env', '.env/extra', 'prod.env', '.Env', '../.env', or any name not starting with '.env'. Passing undefined/null or a path with directory separators.","commonSituations":"Frontend sends the bare profile name instead of '.env.<profile>'. User types a custom dotenv filename that doesn't follow the .env* convention. Path traversal attempt blocked by the basename check.","solutions":["Pass only '.env' or a string matching /^\\.env\\.[a-zA-Z0-9._-]+$/ (e.g. '.env.production').","If the caller has a profile name like 'production', send filename as `.env.${profile}`.","Run isValidDotEnvFilename on the caller side before invoking the IPC."],"exampleFix":"// before\nawait window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, 'production');\n\n// after\nconst filename = profile ? `.env.${profile}` : '.env';\nif (!/^\\.env(\\.[a-zA-Z0-9._-]+)?$/.test(filename)) throw new Error('bad dotenv filename');\nawait window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename);","handlingStrategy":"validation","validationCode":"// Replicates isValidDotEnvFilename (filesystem.js:520)\nfunction isValidDotEnvFilename(filename) {\n  if (!filename || typeof filename !== 'string') return false;\n  const basename = path.basename(filename);\n  if (basename !== filename) return false;\n  return basename === '.env' || (basename.startsWith('.env.') && /^\\.env\\.[a-zA-Z0-9._-]+$/.test(basename));\n}\nif (!isValidDotEnvFilename(filename)) throw new Error('invalid dotenv filename');","typeGuard":"function isDotEnvFilename(filename) {\n  return typeof filename === 'string'\n    && path.basename(filename) === filename\n    && (filename === '.env' || /^\\.env\\.[a-zA-Z0-9._-]+$/.test(filename));\n}","tryCatchPattern":"try {\n  await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename);\n} catch (e) {\n  if (/Invalid \\.env filename/.test(e.message)) {\n    filename = filename.startsWith('.env') ? filename : `.env.${filename}`;\n    await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename);\n  } else throw e;\n}","preventionTips":["Always pass '.env' or '.env.<profile>' with profile chars limited to [A-Za-z0-9._-].","Map UI profile labels to '.env.<label>' at the call boundary, never send the bare label.","Never allow path separators in the dotenv filename (blocked by the basename check)."],"tags":["ipc","validation","dotenv","path-traversal","bruno"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}