Back to skill

Security audit

Amazon Competitor Analyzer

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Amazon competitor-analysis tool, but users should know it sends ASINs to BrowserAct and writes local reports that may contain untrusted marketplace content.

Before installing, use this only with ASINs you are comfortable sending to BrowserAct. Prefer BROWSERACT_API_KEY via environment or a protected .env file instead of --api-key, keep the output directory intentional, and treat generated CSV files as untrusted when opening them in spreadsheet software.

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
amazon_competitor_analyzer.py:195
Finding

Spreadsheet Formula Injection in Generated CSV Reports

Content
View full analysis

Vulnerability Details

File Location: amazon_competitor_analyzer.py, lines 195-216
Vulnerability Type: CSV formula injection
Risk Level: Medium

Vulnerable Code

python
with open(output_path, 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow([
        'ASIN', 'Product Title', 'Brand', 'Price ($)', 'Original Price ($)',
        'Discount (%)', 'Rating', 'Reviews Count', 'Weight', 'Features'
    ])
    
    for asin, data in products.items():
        if data:
            try:
                product = data.get('results', {}).get('products', [{}])[0]
                writer.writerow([
                    asin,
                    product.get('product_info', {}).get('title', 'N/A')[:100],
                    product.get('product_info', {}).get('brand', 'N/A'),
                    product.get('pricing', {}).get('current_price', 'N/A'),
                    product.get('pricing', {}).get('original_price', 'N/A'),
                    product.get('pricing', {}).get('discount_percent', 'N/A'),
                    product.get('reviews', {}).get('average_rating', 'N/A'),
                    product.get('reviews', {}).get('total_count', 'N/A'),
                    product.get('specifications', {}).get('weight', 'N/A'),
                    ', '.join(product.get('specifications', {}).get('features', [])[:5])
                ])

Technical Analysis

The report generator writes externally sourced Amazon product data directly into CSV cells without neutralizing spreadsheet formula prefixes. Fields such as the product title, brand, weight, and features may be influenced by marketplace sellers or by compromised upstream scraping results.

A value beginning with =, +, -, or @ can be treated as a formula when the CSV file is opened in spreadsheet software. Standard CSV quoting controls field boundaries but does not prevent formula evaluation.

D ...[truncated 1383 chars]

Remediation
View remediation

Remediation Suggestions

Introduce a centralized CSV-cell sanitizer and apply it to every string originating from user input or external services.

python
def safe_csv_cell(value):
    if value is None:
        return "N/A"

    text = str(value)
    if text.startswith(("=", "+", "-", "@")):
        return "'" + text
    return text

Apply the function to the ASIN, product title, brand, weight, features, and any other value that may be represented as text:

python
writer.writerow([
    safe_csv_cell(asin),
    safe_csv_cell(product.get('product_info', {}).get('title', 'N/A')[:100]),
    safe_csv_cell(product.get('product_info', {}).get('brand', 'N/A')),
    safe_csv_cell(product.get('pricing', {}).get('current_price', 'N/A')),
    safe_csv_cell(product.get('pricing', {}).get('original_price', 'N/A')),
    safe_csv_cell(product.get('pricing', {}).get('discount_percent', 'N/A')),
    safe_csv_cell(product.get('reviews', {}).get('average_rating', 'N/A')),
    safe_csv_cell(product.get('reviews', {}).get('total_count', 'N/A')),
    safe_csv_cell(product.get('specifications', {}).get('weight', 'N/A')),
    safe_csv_cell(', '.join(
        product.get('specifications', {}).get('features', [])[:5]
    ))
])

Also add tests covering all common formula prefixes, leading whitespace, tabs, carriage returns, and newline-prefixed formulas. Document that generated reports contain untrusted marketplace content.

T09 · Insecure Skill Coding Practices

Note
Location
amazon_competitor_analyzer.py:342
Finding

BrowserAct API Key Can Be Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: amazon_competitor_analyzer.py, lines 342-348
Vulnerability Type: Sensitive credential exposure through process arguments
Risk Level: Low

Vulnerable Code

python
parser.add_argument("-k", "--api-key", help="BrowserAct API key")

args = parser.parse_args()

# Initialize with custom API key if provided
if args.api_key:
    global BROWSERACT_API_KEY
    BROWSERACT_API_KEY = args.api_key

Technical Analysis

The Skill permits users to pass the BrowserAct API key directly on the command line. Command-line arguments are commonly recorded in shell history and may be captured by process inspection tools, endpoint monitoring agents, CI job logs, terminal transcripts, or diagnostic systems.

The program already supports the BROWSERACT_API_KEY environment variable, so command-line transmission is not necessary for its declared functionality. Although environment variables also require careful handling, they avoid placing the secret directly in the command history and process command line.

The API key is otherwise sent as a Bearer token only to the documented HTTPS endpoint at https://api.browseract.com. No covert credential destination was identified.

Attack Path

  1. A user runs the analyzer with --api-key or -k.
  2. The complete invocation, including the key, is stored in shell history, CI logs, terminal records, or process telemetry.
  3. Another local user, administrator, monitoring-system operator, or party with access to those records retrieves the credential.
  4. The party uses the key to authenticate to BrowserAct as the victim.
  5. The exposed credential remains usable until it expires or is revoked.

Impact Assessment

Exposure does not grant local system privileges. It can grant the attacker the BrowserAct account capabilities assigned to the leaked API key, potentially including workflow execution, task access, quota consumption, ...[truncated 164 chars]

Remediation
View remediation

Remediation Suggestions

Remove the --api-key command-line option and require BROWSERACT_API_KEY through the environment or a protected credential provider. Fail clearly when no credential is available:

python
api_key = os.getenv("BROWSERACT_API_KEY")
if not api_key:
    parser.error(
        "BROWSERACT_API_KEY must be set in the environment"
    )

For interactive use, a non-echoing prompt can be offered instead:

python
import getpass

api_key = os.getenv("BROWSERACT_API_KEY")
if not api_key:
    api_key = getpass.getpass("BrowserAct API key: ")

Additional hardening should include:

  • Never logging the Authorization header or API key.
  • Restricting permissions on any .env file that stores the key.
  • Ensuring .env is excluded from source control.
  • Using narrowly scoped and short-lived credentials where BrowserAct supports them.
  • Redacting secrets from CI output and observability systems.
  • Rotating any key previously supplied through command-line arguments.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 53)May include surrounding context.

md
from typing import Dict, List, Optional, Any
from pathlib import Path

# Try to load .env file if python-dotenv is available
try:
    from dotenv import load_dotenv
    # Load .env from same directory as script

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 54)May include surrounding context.

md
from typing import Dict, List, Optional, Any
from pathlib import Path

# Try to load .env file if python-dotenv is available
try:
    from dotenv import load_dotenv
    # Load .env from same directory as script

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 106)May include surrounding context.

md
from typing import Dict, List, Optional, Any
from pathlib import Path

# Try to load .env file if python-dotenv is available
try:
    from dotenv import load_dotenv
    # Load .env from same directory as script

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 21)May include surrounding context.

python
from typing import Dict, List, Optional, Any
from pathlib import Path

# Try to load .env file if python-dotenv is available
try:
    from dotenv import load_dotenv
    # Load .env from same directory as script

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 24)May include surrounding context.

python
from typing import Dict, List, Optional, Any
from pathlib import Path

# Try to load .env file if python-dotenv is available
try:
    from dotenv import load_dotenv
    # Load .env from same directory as script

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 30)May include surrounding context.

python
from typing import Dict, List, Optional, Any
from pathlib import Path

# Try to load .env file if python-dotenv is available
try:
    from dotenv import load_dotenv
    # Load .env from same directory as script

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 26)May include surrounding context.

python
from dotenv import load_dotenv
    # Load .env from same directory as script
    script_dir = Path(__file__).parent
    env_file = script_dir / ".env"
    if env_file.exists():
        load_dotenv(env_file)
except ImportError:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 32)May include surrounding context.

python
from dotenv import load_dotenv
    # Load .env from same directory as script
    script_dir = Path(__file__).parent
    env_file = script_dir / ".env"
    if env_file.exists():
        load_dotenv(env_file)
except ImportError:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares environment, file write, and network capabilities but does not explicitly constrain or disclose tool scope via permissions or allowed-tools. This creates unnecessary ambiguity about what the skill may access or do at runtime, increasing the risk of overbroad execution and unintended data handling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill states it uses browseract.com for scraping but does not clearly warn users that provided ASINs and scraped product data will be transmitted to a third-party service. This is a data transparency and privacy issue because users may unknowingly send research targets and collected marketplace data to an external processor.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest describes scraping Amazon product data via BrowserAct and performing competitor analysis, but it does not indicate any need to inspect local configuration files or process environment state directly. The code loads a .env file from disk and populates process environment variables before use, which introduces local secret-reading capability beyond the core analysis function.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 45)May include surrounding context.

python
# Configuration
BROWSERACT_API_KEY = os.getenv("BROWSERACT_API_KEY", "")
WORKFLOW_TEMPLATE_ID = "77814333389670716"
API_BASE_URL = "https://api.browseract.com/v2/workflow"


class AmazonCompetitorAnalyzer:

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The skill transmits user-provided ASINs and associated workflow metadata to an external API endpoint. In context, this behavior is central to the skill's functionality, but it still creates a real data-exposure boundary and should be treated as a security/privacy risk if users are not informed or if usage occurs in sensitive environments.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 83)May include surrounding context.

python
}
        
        try:
            response = requests.post(
                f"{API_BASE_URL}/run-task-by-template",
                json=data,
                headers=self.headers,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill sends user-supplied product identifiers to a third-party service (BrowserAct) without any explicit notice, consent, or data-handling disclosure. Even though ASINs are not highly sensitive by themselves, in enterprise or research workflows they can reveal business intent, competitor targeting, and internal analysis priorities to an external provider.

Content

No source excerpt is available for this finding.

Tainted flow: 'task_id' from requests.get (line 92, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 108)May include surrounding context.

python
while time.time() - start_time < timeout:
            try:
                response = requests.get(
                    f"{API_BASE_URL}/get-task-status?task_id={task_id}",
                    headers=self.headers,
                    timeout=10

Tainted flow: 'task_id' from requests.get (line 92, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · amazon_competitor_analyzer.py (reported line 132)May include surrounding context.

python
def get_results(self, task_id: str) -> Optional[Dict]:
        """Get task results"""
        try:
            response = requests.get(
                f"{API_BASE_URL}/get-task?task_id={task_id}",
                headers=self.headers,
                timeout=30

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest focuses on collecting Amazon product data and analyzing competitor specifications, pricing, reviews, and visuals. In addition to analysis, the code generates CSV, Markdown, and JSON reports and creates output directories, which is a materially broader behavior than the manifest description suggests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The code automatically loads BROWSERACT_API_KEY from a .env file or environment variables, which is access to sensitive credentials. Although this is common implementation behavior, the file provides no user-facing warning or notice that local secrets will be read automatically.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.