Back to skill

Security audit

Google News Api Skill

Security checks for vulnerabilities and agentic risk

Overview

This news-search skill is mostly purpose-aligned, but it gives unsafe API-key handling guidance and has broad automatic-use instructions that could expose searches to BrowserAct without clear user control.

Review before installing. Use this only for searches you are comfortable sending to BrowserAct and Google News. Do not paste the BrowserAct API key into chat; configure it locally as BROWSERACT_API_KEY or through a secret manager. Stop the run manually if polling continues too long.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/google_news_api.py:105
Finding
API Key Disclosure Encouraged Through Chat## Vulnerability Details **File Location**: `scripts/google_news_api.py`, lines 105-110 **Vulnerability Type**: Sensitive credential exposure through insecure operational guidance **Risk Level**: Medium ### Vulnerable Code ```python if not api_key: print("\n[!] ERROR: BrowserAct API Key is missing.", flush=True) print("Please follow these steps:", flush=True) print("1. Go to: https://www.browseract.com/reception/integrations", flush=True) print("2. Copy your API Key.", flush=True) print("3. Set it as an environment variable (BROWSERACT_API_KEY) or provide it in the chat.", flush=True) sys.exit(1) ``` ### Technical Analysis The script explicitly advises users that they may provide the BrowserAct API key in chat. This is unnecessary because the implementation only reads the credential from the `BROWSERACT_API_KEY` environment variable. Entering a credential into a conversation can expose it to chat history, telemetry, logs, agent context, support tooling, or other systems that process or retain conversation content. This violates least-exposure principles for secrets and exceeds what is necessary for the declared news-retrieval functionality. The legitimate transmission of the key as a Bearer token to the declared BrowserAct HTTPS endpoint is required by the Skill. The vulnerability is specifically the instruction to disclose that key through a separate, unnecessary communication channel. ### Attack Path 1. A user runs the script without setting `BROWSERACT_API_KEY`. 2. The script instructs the user to provide the API key in chat. 3. The user follows that instruction and pastes the secret into the conversation. 4. The credential is retained or processed in chat history, logs, telemetry, or agent context. 5. An unauthorized party with access to any of those records obtains the key. 6. The exposed key is reused to invoke BrowserAct APIs under the victim's account. ### Impact Assessmen ...[truncated 476 chars]
Remediation
## Remediation Suggestions - Remove the phrase `or provide it in the chat`. - Require users to configure the key locally through `BROWSERACT_API_KEY` or an approved secret manager. - Explicitly warn users never to paste API keys into conversations, source files, command histories, or logs. - Where supported, use short-lived, narrowly scoped credentials and provide rotation and revocation instructions. - Ensure error messages never print the key or an authorization header. - Replace the affected message with guidance such as: ```python print( "Set BROWSERACT_API_KEY using a protected environment or secret manager. " "Do not paste API keys into chat.", flush=True, ) ```

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/google_news_api.py:60
Finding
Unbounded HTTP Requests and Task Polling Can Cause Indefinite Execution## Vulnerability Details **File Location**: `scripts/google_news_api.py`, lines 60-79 **Vulnerability Type**: Missing network timeouts and unbounded polling **Risk Level**: Medium ### Vulnerable Code ```python while True: try: status_response = requests.get(f"{API_BASE_URL}/get-task-status?task_id={task_id}", headers=headers) status_res = status_response.json() status = status_res.get("status") timestamp = datetime.datetime.now().strftime("%H:%M:%S") print(f"[{timestamp}] Task Status: {status}", flush=True) if status == "finished": print(f"[{timestamp}] Task finished successfully.", flush=True) break elif status in ["failed", "canceled"]: print(f"Error: Task {status}. Please check your BrowserAct dashboard.", flush=True) return None except Exception as e: timestamp = datetime.datetime.now().strftime("%H:%M:%S") print(f"[{timestamp}] Polling error: {e}. Retrying in 10s...", flush=True) time.sleep(10) ``` Related requests at lines 40 and 84 also omit explicit timeouts: ```python response = requests.post(f"{API_BASE_URL}/run-task-by-template", json=payload, headers=headers) ``` ```python task_info_response = requests.get(f"{API_BASE_URL}/get-task?task_id={task_id}", headers=headers) ``` ### Technical Analysis Every HTTP operation is issued without a `timeout`. A connection or response that stalls can therefore block execution for an implementation-dependent and potentially very long period. The status loop uses `while True` and has neither an overall deadline nor a maximum number of attempts. It terminates only if the remote service reports `finished`, `failed`, or `canceled`. Unknown, missing, or perpetually running statuses result in endless polling. Exceptions are also caught and retried indefinitely. The Skill documentation ...[truncated 1465 chars]
Remediation
## Remediation Suggestions - Set explicit connect and read timeouts on every `requests.get` and `requests.post` call, for example `timeout=(5, 30)`. - Add an overall polling deadline or maximum attempt count. - Count consecutive polling failures and stop after a bounded number of retries. - Validate HTTP status codes with `raise_for_status()` before parsing JSON. - Treat malformed responses and unknown statuses as bounded failures rather than polling forever. - Use exponential backoff with a maximum delay and optional jitter. - Return a clear timeout error so the documented outer retry policy can operate. - A suitable design would resemble: ```python deadline = time.monotonic() + 300 max_failures = 3 failures = 0 while time.monotonic() < deadline: try: status_response = requests.get( f"{API_BASE_URL}/get-task-status?task_id={task_id}", headers=headers, timeout=(5, 30), ) status_response.raise_for_status() status = status_response.json().get("status") failures = 0 except (requests.RequestException, ValueError) as exc: failures += 1 if failures >= max_failures: print(f"Error: Polling failed: {exc}", flush=True) return None time.sleep(10) continue if status == "finished": break if status in {"failed", "canceled"}: return None time.sleep(10) else: print("Error: Task polling timed out.", flush=True) return None ```
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Vague Triggers

High
Confidence
97% confidence
Finding
The manifest encourages proactive application for a very broad set of common research, monitoring, and summarization requests. That can cause the agent to invoke the skill without sufficiently clear user intent, resulting in unnecessary third-party data disclosure and unexpected external browsing behavior.

Credential Access

High
Category
Privilege Escalation
Content
return None

if __name__ == "__main__":
    # Get API Key from environment variable
    api_key = os.getenv("BROWSERACT_API_KEY")
    
    if len(sys.argv) < 2:
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill requires environment access and makes networked API calls, but it does not declare an explicit tool scope such as permissions or allowed-tools. This creates an authorization ambiguity where an agent may invoke broader capabilities than a user expects, weakening least-privilege controls and auditability.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill does not clearly warn users that their search terms will be transmitted to a third-party service and that returned results include external article links. This undermines informed consent and can expose sensitive research topics, company names, or personal-interest queries to external providers unexpectedly.

External Transmission

Medium
Category
Data Exfiltration
Content
# API Configuration
# TEMPLATE_ID extracted from official BrowserAct Google News API documentation
TEMPLATE_ID = "77638424152140851"
API_BASE_URL = "https://api.browseract.com/v2/workflow"

def run_google_news_task(api_key, keywords, date_range="past week", limit=30):
    """
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# 1. Start Task
    print(f"Starting task via BrowserAct API...", flush=True)
    try:
        response = requests.post(f"{API_BASE_URL}/run-task-by-template", json=payload, headers=headers)
        res = response.json()
    except Exception as e:
        print(f"Error: Connection to API failed - {e}", flush=True)
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.