usebruno/bruno · error · Error

Invalid .env filename

Error message

Invalid .env filename

What it means

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'.

Source

Thrown at packages/bruno-electron/src/ipc/collection.js:858

      const format = getCollectionFormat(collectionPathname);
      const envFilePath = resolveEnvironmentFilePath(collectionPathname, environmentName, format);
      if (!fs.existsSync(envFilePath)) {
        throw new Error(`environment: ${envFilePath} does not exist`);
      }

      fs.unlinkSync(envFilePath);

      environmentSecretsStore.deleteEnvironment(collectionPathname, environmentName);
    } catch (error) {
      return Promise.reject(error);
    }
  });

  // Save .env file variables for collection
  ipcMain.handle('renderer:save-dotenv-variables', async (event, collectionPathname, variables, filename = '.env') => {
    try {
      if (!isValidDotEnvFilename(filename)) {
        throw new Error('Invalid .env filename');
      }

      validatePathIsInsideCollection(collectionPathname);

      const dotEnvPath = path.join(collectionPathname, filename);
      const content = utils.jsonToDotenv(variables);
      await writeFile(dotEnvPath, content);

      return { success: true };
    } catch (error) {
      console.error('Error saving .env file:', error);
      return Promise.reject(error);
    }
  });

  // Save .env file raw content for collection
  ipcMain.handle('renderer:save-dotenv-raw', async (event, collectionPathname, content, filename = '.env') => {
    try {

View on GitHub (pinned to 9bdd81c7bd)

Solutions

  1. Pass only '.env' or a string matching /^\.env\.[a-zA-Z0-9._-]+$/ (e.g. '.env.production').
  2. If the caller has a profile name like 'production', send filename as `.env.${profile}`.
  3. Run isValidDotEnvFilename on the caller side before invoking the IPC.

Example fix

// before
await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, 'production');

// after
const filename = profile ? `.env.${profile}` : '.env';
if (!/^\.env(\.[a-zA-Z0-9._-]+)?$/.test(filename)) throw new Error('bad dotenv filename');
await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename);
Defensive patterns

Strategy: validation

Validate before calling

// Replicates isValidDotEnvFilename (filesystem.js:520)
function isValidDotEnvFilename(filename) {
  if (!filename || typeof filename !== 'string') return false;
  const basename = path.basename(filename);
  if (basename !== filename) return false;
  return basename === '.env' || (basename.startsWith('.env.') && /^\.env\.[a-zA-Z0-9._-]+$/.test(basename));
}
if (!isValidDotEnvFilename(filename)) throw new Error('invalid dotenv filename');

Type guard

function isDotEnvFilename(filename) {
  return typeof filename === 'string'
    && path.basename(filename) === filename
    && (filename === '.env' || /^\.env\.[a-zA-Z0-9._-]+$/.test(filename));
}

Try / catch

try {
  await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename);
} catch (e) {
  if (/Invalid \.env filename/.test(e.message)) {
    filename = filename.startsWith('.env') ? filename : `.env.${filename}`;
    await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13). Data as JSON: /api/errors/0d805fa035d29bb9. Report an issue: GitHub.