T09 · Insecure Skill Coding Practices
- Location
scripts/browser-use/setup.sh:113- Finding
Activation Helper Executes Dotenv Files as Shell Code
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly coherent for browser-based testing, but its browser-use setup creates persistent helpers that can execute project .env files as shell code and overexpose credentials.
Review before installing. Only use this skill against localhost or staging with throwaway accounts and sanitized data. Do not source the generated activate.sh inside untrusted repositories unless you remove the project .env sourcing behavior first; prefer explicitly exported, limited LLM credentials. Consider pinning dependencies and using local models for sensitive applications.
scripts/browser-use/setup.sh:113Activation Helper Executes Dotenv Files as Shell Code
scripts/browser-use/config.py:34Configuration Automatically Imports Unrelated Secrets into the Process Environment
scripts/browser-use/setup.sh:66Setup Installs Mutable and Unhashed Third-Party Artifacts
The Ollama reachability check performs a network request to a URL derived directly from the environment variable OLLAMA_BASE_URL. In adversarial or untrusted execution environments, this enables SSRF-style behavior or unintended outbound connections during module import, potentially reaching internal services or attacker-controlled hosts without explicit user action.
import urllib.error
try:
urllib.request.urlopen(f"{_OLLAMA_BASE_URL.replace('/v1', '')}/api/tags", timeout=1)
except (urllib.error.URLError, ConnectionError, OSError):
import warnings
The declared description is about browser-based end-to-end verification and Playwright/Expect/browser-use execution policy. The supplied code chunk does not implement browser testing, flow verification, Playwright authoring, safety gates for production/cookies, or any E2E execution logic. Instead, it is a support/config module for choosing an LLM backend based on environment variables and checking Ollama availability. While this may be related to infrastructure used by a browser-use tool, the chunk’s actual behavior is materially different from the declared primary purpose and includes capabilities/resources (reading .env, using API keys, contacting Ollama) not represented in the description. Therefore this is a clear description-behavior mismatch.
The declared description is about an operational testing skill: deciding how to run browser-based verification, executing ephemeral or durable e2e checks, and following specific evidence and safety rules. The supplied code chunk does not perform browser verification or test authoring; it only prepares a local browser-use environment by creating a venv, installing dependencies, installing Chromium, and generating helper/config files. While this setup supports the broader skill, its actual behavior is materially different from the declared primary purpose. Additionally, the activation helper sources .env files and exposes provider configuration behavior that is not mentioned in the description. This is more than an implementation detail because the code’s direct function is environment provisioning, not e2e verification.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
browser-use needs an LLM to drive the agent. The skill auto-detects your provider from standard environment variables — no hardcoded endpoints:
# Set ONE of these in your shell or .env — the skill does the rest
export OPENAI_API_KEY="sk-..." # OpenAI
export GEMINI_API_KEY="AIza..." # Google Gemini
export DASHSCOPE_API_KEY="sk-..." # Alibaba DashScope / Qwen
Expanding scope to production testing directly conflicts with the skill metadata that forbids production use. In this skill's context, the browser agent can click, type, and submit forms autonomously, so allowing production dramatically increases the risk of real data modification, destructive actions, or accidental interaction with live accounts.
Reading credentials from .env files is common, but automatically reading them from the current directory and home directory during import expands the trust boundary and can expose the process to repository-planted secrets or configuration injection. In an agent skill that may execute inside untrusted workspaces, this increases the risk of unintended credential use and redirection of outbound requests.
def _load_dotenv():
"""Load .env file from CWD or home if present (minimal, no deps)."""
for env_path in [Path.cwd() / ".env", Path.home() / ".env"]:
if env_path.exists():
for line in env_path.read_text().splitlines():
Including both the working directory and home directory as implicit credential sources allows untrusted local files to influence secrets and provider configuration without user awareness. This is particularly risky in automation or agent workflows where the current repository may be attacker-controlled and the import alone triggers the behavior.
def _load_dotenv():
"""Load .env file from CWD or home if present (minimal, no deps)."""
for env_path in [Path.cwd() / ".env", Path.home() / ".env"]:
if env_path.exists():
for line in env_path.read_text().splitlines():
line = line.strip()
The helper advertises automatic loading of API keys from generic .env files and immediately executes those files in the current shell. In practice this is both credential exposure and code-execution risk: a malicious project .env can steal existing tokens, overwrite provider endpoints, or exfiltrate secrets when the user activates the environment.
export BROWSER_USE_VENV="$_VENV_DIR"
# Load LLM API keys from .env files if available
for _envfile in "$HOME/.env" "$(pwd)/.env"; do
if [ -f "$_envfile" ]; then
set -a
Sourcing "$_envfile" on line 114 treats a .env file as executable shell input. Because one of the searched paths is the current working directory, a repository or workspace can plant a malicious .env that runs commands and accesses credentials during activation, which is especially dangerous in an automation/browser-use skill that commonly handles API keys.
export BROWSER_USE_VENV="$_VENV_DIR"
# Load LLM API keys from .env files if available
for _envfile in "$HOME/.env" "$(pwd)/.env"; do
if [ -f "$_envfile" ]; then
set -a
. "$_envfile"
Without declared permissions the skill's intent is opaque and cannot be validated.
The skill is configured to trigger on broad, common phrases like 'test my web app' or 'verify this in the browser,' which can cause unintended invocation in contexts where the user did not intend this specific high-capability workflow. Because the skill can lead to browser automation, shell commands, installs, and networked testing steps, overbroad routing increases the chance of accidental execution against the wrong target or with unnecessary capability use.
The invocation examples include everyday requests such as 'does it actually work' and 'smoke test the UI,' which are semantically broad and likely to overlap with normal developer conversation. In a skill that may initiate browser-driven testing and optional installation paths, ambiguous activation expands the attack surface for prompt-routing mistakes and unintended side effects.
The document states a safety gate of 'never production,' but later capability text says the agent can test 'localhost, staging, production.' That contradiction weakens operator safeguards and can lead users or downstream agents to run exploratory browser automation against production despite the stated restriction.
The file instructs users to provide API keys for external LLM providers and implies browser-observed content will be sent to those providers, but it does not prominently warn that page content, DOM data, screenshots, and possibly sensitive test data may leave the local environment. For an AI-driven browser tool, that omission materially affects privacy and data-handling risk.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
The module automatically loads .env files from the current working directory and the user's home directory, treating local files as trusted configuration sources. In a skill or agent context that may run in arbitrary repositories, a malicious project can plant a .env file that silently changes provider selection, base URLs, or credentials and influences later network behavior.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# --- Provider definitions ---
# Each entry: (env_var_name, default_base_url, default_model)
_PROVIDERS = [
("OPENAI_API_KEY", "https://api.openai.com/v1", "gpt-4o"),
("ANTHROPIC_API_KEY", "https://api.anthropic.com/v1", "claude-sonnet-4-20250514"),
("GEMINI_API_KEY", "https://generativelanguage.googleapis.com/v1beta/openai", "gemini-2.5-flash"),
("DASHSCOPE_API_KEY", "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", "qwen-max"),
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# Each entry: (env_var_name, default_base_url, default_model)
_PROVIDERS = [
("OPENAI_API_KEY", "https://api.openai.com/v1", "gpt-4o"),
("ANTHROPIC_API_KEY", "https://api.anthropic.com/v1", "claude-sonnet-4-20250514"),
("GEMINI_API_KEY", "https://generativelanguage.googleapis.com/v1beta/openai", "gemini-2.5-flash"),
("DASHSCOPE_API_KEY", "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", "qwen-max"),
("GROQ_API_KEY", "https://api.groq.com/openai/v1", "llama-3.3-70b-versatile"),
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
("ANTHROPIC_API_KEY", "https://api.anthropic.com/v1", "claude-sonnet-4-20250514"),
("GEMINI_API_KEY", "https://generativelanguage.googleapis.com/v1beta/openai", "gemini-2.5-flash"),
("DASHSCOPE_API_KEY", "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", "qwen-max"),
("GROQ_API_KEY", "https://api.groq.com/openai/v1", "llama-3.3-70b-versatile"),
("OPENROUTER_API_KEY", "https://openrouter.ai/api/v1", "openai/gpt-4o"),
]
The generated activation helper sources $HOME/.env and $(pwd)/.env using the shell '.' builtin, which executes the files as shell code rather than safely parsing simple KEY=VALUE pairs. That means any attacker-controlled or untrusted .env in the current directory can run arbitrary commands whenever a user sources activate.sh, and the browser-testing context increases risk because this helper is intended to load powerful API credentials automatically.