Back to Blog
security

Secure Browser Automation Credentials Are Not Optional

Why storing passwords in environment variables and CLI arguments is a security risk—and how vault-backed automation fixes it

February 11, 2026 by NMC Interactive
browser automation security credentials bitwarden 1password vault

Secure Browser Automation Credentials Are Not Optional

If you’re passing passwords through CLI arguments or environment variables, you’re one history | grep away from a credential leak.

Browser automation has a dirty secret: most developers handle credentials wrong.

Not maliciously. Not carelessly. Just… normally. The way every tutorial shows. The way that seems fine until it isn’t.

Here’s what “normal” looks like:

# ❌ Wrong: Credentials in CLI (visible in shell history)
my-tool login --username="admin@company.com" --password="SuperSecret123!"

# ❌ Wrong: Credentials in environment (inherited by child processes)
export API_PASSWORD="SuperSecret123!"
node automation.js

# ❌ Wrong: Credentials in config (often committed to git)
cat config.json
{
  "password": "SuperSecret123!"
}

These patterns are everywhere. They’re also fundamentally insecure.

The Problem with “Normal”

Shell History Never Forgets

That CLI argument with your password? It’s now in ~/.bash_history or ~/.zsh_history. Forever. Accessible to any process running as your user. Backed up to your dotfiles repo. Maybe synced to your other machines.

# Anyone with access to your account can find this:
$ history | grep password
  247  my-tool login --password="SuperSecret123!"

Environment Variables Leak

When you export a variable, it doesn’t stay in your shell. It propagates to every child process. That debugging tool you ran? It saw your password. That npm package with 3 dependencies? It could have logged process.env somewhere.

Config Files Get Committed

.gitignore is a safety net with holes. Developers accidentally commit credentials to git every day. GitHub’s secret scanning catches some, but not all. And once it’s in git history, it’s there forever—even if you “remove” it.

What Secure Looks Like

The solution isn’t complicated. It’s just different:

# ✅ Right: No credentials in CLI
browser-secure navigate https://github.com --site=github

# Credentials live in your vault (Bitwarden, 1Password, etc.)
# Retrieved on-demand, used immediately, cleared from memory
# Never touch disk, never enter shell history

This is how Browser Secure handles credentials. The flow is simple:

  1. Authenticate to your vault once (bw login, op signin)
  2. Vault stays encrypted at rest
  3. Credentials retrieved via secure API when needed
  4. Used immediately, then cleared from memory
  5. Session timeout auto-clears everything (30 min default)

Why Vaults Work

Password managers like Bitwarden and 1Password are designed for exactly this problem:

FeatureProtection
AES-256 encryptionCredentials encrypted at rest
Memory safetyDecrypted only when needed, cleared immediately after
No shell historyCredentials never touch command line
Access loggingKnow when credentials are retrieved
Master passwordOne strong password protects everything

A Real Example

Let’s say you’re automating a GitHub workflow. Here’s the insecure way:

# automation.sh - DON'T DO THIS
#!/bin/bash
GITHUB_TOKEN="ghp_xxxxxxxxxxxx"
export GITHUB_TOKEN
curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user/repos

Problems:

  • Token in shell script (committed to git?)
  • Token in environment (leaked to subprocesses)
  • Token never expires (if stolen, attacker has permanent access)

Here’s the vault-backed way:

# Unlock vault once per session
export BW_SESSION=$(bw unlock --raw)

# Browser Secure retrieves token from vault on-demand
browser-secure navigate https://github.com --site=github
browser-secure act "click the API tokens section"
browser-secure extract "copy the active token"

The token never appears in:

  • Shell history
  • Environment variables
  • Config files
  • Process listings

It lives in your encrypted vault. Period.

The Approval Gate Pattern

Even with vaults, some actions are too sensitive to automate blindly. Browser Secure uses approval gates:

Action TierExamplesApproval Required
Read-onlyNavigate, screenshot, extractNone
Form fillClick, type, selectPrompt
Authenticationfill_password, submit_loginAlways
DestructiveDelete, purchase2FA if enabled

You stay in control. The tool doesn’t act on your behalf without confirmation.

Session Isolation

Browser Secure creates isolated sessions:

  • Time-bounded — 30 minute default timeout
  • UUID-based work directories — No overlap between sessions
  • Network restrictions — Blocks localhost/private IPs to prevent pivot attacks
  • Secure cleanup — Overwrite + delete, not just rm

If something goes wrong, the blast radius is contained.

Chrome Profile Isolation

There’s another layer: Chrome profile separation.

Most developers run automation in their personal Chrome profile. That’s a mistake. Your personal profile has:

  • Gmail cookies
  • Banking session tokens
  • Personal browsing history
  • Saved passwords for other sites

If a malicious script runs during automation, it can access all of that.

Browser Secure supports isolated automation profiles:

# Create dedicated automation profile
browser-secure profile --create "Automation-Only"

# Use it for automation
browser-secure navigate https://target-site.com --profile "Automation-Only"
AspectPersonal ProfileAutomation Profile
ExtensionsAll personal onesOnly automation extensions
CookiesPersonal logins, bankingOnly target sites
HistoryPersonal browsingAutomation sessions only
SecurityLinked to your Google accountIsolated, no personal data

Audit Everything

Security without visibility isn’t security. Browser Secure maintains immutable audit logs:

{
  "event": "BROWSER_SECURE_SESSION",
  "sessionId": "bs-20260211054500-abc123",
  "site": "github.com",
  "actions": ["navigate", "fill_password", "submit_login"],
  "chainHash": "sha256:a3f5b2..."
}
  • SHA-256 chain hashing — Tamper-evident: any modification breaks the chain
  • 30-day retention — Configurable
  • Action-level detail — Know exactly what happened when

The Bottom Line

You have three options for handling automation credentials:

  1. Insecure — CLI args, env vars, config files (what most tutorials teach)
  2. Enterprise — Automation Anywhere, UiPath (expensive, complex, GUI-heavy)
  3. Vault-native — Browser Secure (free, CLI-first, secure by default)

Option 1 is how breaches happen. Option 2 is overkill for most developers. Option 3 is what we built.

Secure browser automation credentials aren’t optional. They’re foundational.


Get Started

# Install Browser Secure
git clone https://github.com/NMC-Interactive/browser-secure.git
cd browser-secure && npm install && npm run build && npm link

# Or let Clawdbot handle it:
# "Clone https://github.com/NMC-Interactive/browser-secure and install for me"

Next: Learn about Chrome profile isolation for automation or building secure AI agents.


Browser Secure is part of the OpenClaw ecosystem. Free, open-source, and designed for developers who care about security.