Description
During a static code review of cli.py, two critical issues were identified in the global initialization block handling the BROWSER_USE_API_KEY fallback:
-
Cleartext Key Exposure (Security): The fallback mechanism uses the built-in input() function to collect the user's API key (os.environ['BROWSER_USE_API_KEY'] = input(...)). This echoes the sensitive API key in cleartext to the terminal, making it vulnerable to shoulder surfing and terminal history logging.
-
Unbound Local Variable Risk (Stability): If the initial ChatBrowserUse instantiation fails and the user selects n at the prompt, the code executes a pass. Consequently, llm_instance and page_extraction_llm remain uninitialized. When downstream Typer commands attempt to access these global instances, the application will crash with a NameError or UnboundLocalError.
Steps to reproduce
Note: Identified via static program analysis. Theoretical reproduction steps below:
1.Run the CLI tool in an environment where BROWSER_USE_API_KEY is not set or invalid.
-
At the prompt Set BROWSER_USE_API_KEY? (y/n):, type y.
-
Paste an API key and observe that the key is printed to the screen in plain text (Security Issue).
-
Alternatively, at the first prompt, type n.
-
Attempt to run any CLI command that utilizes the LLM. Observe the application crashing due to undefined variables (Stability Issue).
Expected behavior
-
The CLI should securely prompt for the API key by masking the input. Since typer is already a project dependency, typer.prompt("Enter your BROWSER_USE_API_KEY", hide_input=True) should be used instead of standard input().
-
If the user declines to provide a key (inputs n), the script should either gracefully exit using typer.Exit() with a helpful warning, or initialize a safe fallback state to prevent unhandled exceptions downstream.
Actual behavior
The API key is visibly echoed on the screen during input, and the script silently continues execution with undefined core LLM variables if the user skips the fallback prompt.
Additional context
Using typer.prompt(..., hide_input=True) is the standard best practice for handling secrets in Typer-based CLI applications and requires minimal refactoring.
Description
During a static code review of cli.py, two critical issues were identified in the global initialization block handling the BROWSER_USE_API_KEY fallback:
Cleartext Key Exposure (Security): The fallback mechanism uses the built-in input() function to collect the user's API key (os.environ['BROWSER_USE_API_KEY'] = input(...)). This echoes the sensitive API key in cleartext to the terminal, making it vulnerable to shoulder surfing and terminal history logging.
Unbound Local Variable Risk (Stability): If the initial ChatBrowserUse instantiation fails and the user selects n at the prompt, the code executes a pass. Consequently, llm_instance and page_extraction_llm remain uninitialized. When downstream Typer commands attempt to access these global instances, the application will crash with a NameError or UnboundLocalError.
Steps to reproduce
Note: Identified via static program analysis. Theoretical reproduction steps below:
1.Run the CLI tool in an environment where BROWSER_USE_API_KEY is not set or invalid.
At the prompt Set BROWSER_USE_API_KEY? (y/n):, type y.
Paste an API key and observe that the key is printed to the screen in plain text (Security Issue).
Alternatively, at the first prompt, type n.
Attempt to run any CLI command that utilizes the LLM. Observe the application crashing due to undefined variables (Stability Issue).
Expected behavior
The CLI should securely prompt for the API key by masking the input. Since typer is already a project dependency, typer.prompt("Enter your BROWSER_USE_API_KEY", hide_input=True) should be used instead of standard input().
If the user declines to provide a key (inputs n), the script should either gracefully exit using typer.Exit() with a helpful warning, or initialize a safe fallback state to prevent unhandled exceptions downstream.
Actual behavior
The API key is visibly echoed on the screen during input, and the script silently continues execution with undefined core LLM variables if the user skips the fallback prompt.
Additional context
Using typer.prompt(..., hide_input=True) is the standard best practice for handling secrets in Typer-based CLI applications and requires minimal refactoring.