{"record":{"id":"81c9a0892368577d","repo":"usebruno/bruno","slug":"invalid-env-filename-81c9a0","errorCode":null,"errorMessage":"Invalid .env filename","messagePattern":"Invalid \\.env filename","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-electron/src/ipc/global-environments.js","lineNumber":171,"sourceCode":"      return {\n        globalEnvironments,\n        activeGlobalEnvironmentUid\n      };\n    } catch (error) {\n      console.error('Error in renderer:get-global-environments:', error);\n      return Promise.reject(error);\n    }\n  });\n\n  // Save workspace .env file variables\n  ipcMain.handle('renderer:save-workspace-dotenv-variables', async (event, { workspacePath, variables, filename = '.env' }) => {\n    try {\n      if (!workspacePath) {\n        throw new Error('Workspace path is required');\n      }\n\n      if (!isValidDotEnvFilename(filename)) {\n        throw new Error('Invalid .env filename');\n      }\n\n      const dotEnvPath = path.join(workspacePath, filename);\n      const content = jsonToDotenv(variables);\n      await writeFile(dotEnvPath, content);\n\n      return { success: true };\n    } catch (error) {\n      console.error('Error saving workspace .env file:', error);\n      return Promise.reject(error);\n    }\n  });\n\n  // Save workspace .env file raw content\n  ipcMain.handle('renderer:save-workspace-dotenv-raw', async (event, { workspacePath, content, filename = '.env' }) => {\n    try {\n      if (!workspacePath) {\n        throw new Error('Workspace path is required');","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-electron/src/ipc/global-environments.js#L153-L189","documentation":"`isValidDotEnvFilename` requires basename === filename (no path separators) and a match of `.env` or `.env.<letters/digits/._->`. Anything else - a subdirectory, a non-.env name like `secret.txt`, or undefined - is rejected to prevent path traversal and arbitrary file writes.","triggerScenarios":"Passing `filename: 'environments/.env'` (basename !== filename), `filename: 'foo.env'` (doesn't start with `.env`), `filename: '../../etc/passwd'`, or undefined.","commonSituations":"UI defaulting the filename wrongly; user typing a custom name; passing the full path instead of just the basename.","solutions":["Omit `filename` to use the default `.env`.","Pass only the basename: `.env`, `.env.staging`, `.env.local`.","Never include directory separators in the filename argument."],"exampleFix":"// before\ninvoke('renderer:save-workspace-dotenv-variables', { workspacePath, variables, filename: 'config/.env' });\n// after\ninvoke('renderer:save-workspace-dotenv-variables', { workspacePath, variables, filename: '.env' });","handlingStrategy":"validation","validationCode":"const path = require('path');\nconst validEnvName = (f) => typeof f === 'string' && path.basename(f) === f && /^\\.env(\\.[a-zA-Z0-9._-]+)?$/.test(f);","typeGuard":"const isDotEnvFilename = (f) => typeof f === 'string' && path.basename(f) === f && /^\\.env(\\.[a-zA-Z0-9._-]+)?$/.test(f);","tryCatchPattern":null,"preventionTips":["Let the UI pick from a fixed list of allowed env filenames.","Never concatenate user input into the filename argument."],"tags":["env","validation","path-traversal","ipc"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}