T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/browser-use-agent.sh:7
- Finding
- Arbitrary Python Code Execution Through Unsafely Generated Source Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/browser-use-agent.sh:7-18, 32-54`; duplicated in the wrapper generated by `scripts/install.sh:63-78, 89-117` **Vulnerability Type**: Python source-code injection through unsanitized shell arguments **Risk Level**: High ### Vulnerable Code ```bash TASK="${1:?Usage: $0 \"task description\" [--model MODEL] [--max-steps N]}" shift MODEL="gpt-4o-mini" MAX_STEPS=12 while [[ $# -gt 0 ]]; do case "$1" in --model) MODEL="$2"; shift 2 ;; --max-steps) MAX_STEPS="$2"; shift 2 ;; *) echo "Unknown option: $1"; exit 1 ;; esac done if [[ "$MODEL" == claude* ]] || [[ "$MODEL" == anthropic* ]]; then LLM_IMPORT="from langchain_anthropic import ChatAnthropic" LLM_INIT="ChatAnthropic(model='$MODEL', api_key=os.environ['ANTHROPIC_API_KEY'])" else LLM_IMPORT="from langchain_openai import ChatOpenAI" LLM_INIT="ChatOpenAI(model='$MODEL', api_key=os.environ['OPENAI_API_KEY'])" fi cat > /tmp/_bu_task.py << PYEOF import asyncio, os $LLM_IMPORT from browser_use import Agent async def run(): llm = $LLM_INIT agent = Agent(task="""$TASK""", llm=llm) result = await agent.run(max_steps=$MAX_STEPS) final = result.final_result() if final: print(final.extracted_content if hasattr(final, 'extracted_content') else str(final)) else: for r in result.all_results: if r.extracted_content: print(r.extracted_content) asyncio.run(run()) PYEOF xvfb-run "$VENV_DIR/bin/python3" /tmp/_bu_task.py ``` ### Technical Analysis The wrapper constructs a Python program by directly interpolating three caller-controlled values: - `TASK` is inserted inside a triple-quoted Python string. - `MODEL` is inserted inside a single-quoted Python string. - `MAX_STEPS` is inserted as an unrestricted Python expression. None of these values are escaped or validated for the context in which they are inserted. A crafted task can terminate the tripl ...[truncated 1851 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace generated Python source with a fixed, reviewed Python entry point. 2. Pass the task and model as ordinary command-line arguments or through a serialized JSON document, then read them using `argparse` or `json`. 3. Parse `--max-steps` as a decimal integer in the shell or Python and enforce a reasonable range. 4. Validate the model against an explicit allowlist instead of placing an arbitrary model string into source code. 5. Do not use `eval`, dynamic imports, or shell interpolation as an alternative. 6. Apply the fix both to `scripts/browser-use-agent.sh` and to the wrapper template in `scripts/install.sh`. A safe design would invoke a fixed program in the following form: ```bash exec xvfb-run "$VENV_DIR/bin/python3" "$SCRIPT_DIR/browser_use_agent.py" \ --task "$TASK" \ --model "$MODEL" \ --max-steps "$MAX_STEPS" ``` The Python program should consume these as data rather than executable source. ]]>
