Back to skill

Security audit

1688-product-search

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to provide the advertised 1688 product search features, but it handles account tokens and user-supplied image URLs in ways that need review before installation.

Install only if you are comfortable giving the skill 1688 account API credentials and allowing it to cache tokens for reuse across 1688 skills. Avoid using untrusted image URLs, and prefer a version that stores tokens in a protected secret store, redacts token output, validates image URL destinations, and avoids passing secrets on the command line.

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 (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/auth.py:18
Finding

OAuth Tokens Stored in a Shared Cache Without Enforced File Permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/auth.py:121
Finding

Live Access Token Disclosed Through Standard Output

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/product_search.py:112
Finding

Arbitrary Image URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
str: import tempfile from urllib.parse import urlparse parsed = urlparse(image_url) suffix = os.path.splitext(parsed.path)[-1] or '.jpg' if suffix.lower() not in ('.jpg', '.jpeg', '.png', '.webp', '.gif', '.bmp'): suffix = '.jpg' with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp_file: local_path = tmp_file.name response = requests.get(image_url, timeout=30, stream=True) response.raise_for_status() with open(local_path, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) return local_path ``` Equivalent unrestricted fetching occurs in `scripts/image_search_handler.py:38-52, 125-145` and `scripts/product_search_updated.py:47-67, 115-165`. ### Technical Analysis The URL is controlled by the caller and is passed directly to `requests.get()`. The code does not: - Restrict the scheme to HTTPS. - Reject loopback, private, link-local, multicast, or reserved destinations. - Resolve and validate the destinati ...[truncated 2338 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/product_search_updated.py:115
Finding

Predictable Temporary Files Permit Local Symlink Overwrite Attacks

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fixed_image_upload.py:87
Finding

Application Secret and Access Token Accepted Through Process Arguments

Content
View full analysis
") sys.exit(1) image_path = sys.argv[1] app_key = sys.argv[2] app_secret = sys.argv[3] token = sys.argv[4] try: image_id = fixed_upload_image(image_path, app_key, app_secret, token) ``` ### Technical Analysis The script requires the AppSecret and access token to be supplied as command-line arguments. Process arguments can be exposed through process-listing tools, system monitoring, audit records, crash reports, command histories, job definitions, and orchestration telemetry. Unlike ordinary search parameters, these values are authentication credentials. Passing them through argv exceeds the minimum exposure necessary for image upload, particularly because the rest of the project already supports protected credential retrieval from environment variables. ### Attack Path 1. An operator invokes the script with an AppSecret and live access token in the command line. 2. While the process runs, another local process or monitoring agent records its argument vector. 3. The invoking shell may also retain the full command in history. 4. An attacker with access to process telemetry, history, or job logs retrieves the credentials. 5. The attacker uses the access token directly or uses the AppSecret with other OAuth material to impersonate the application. ### Impact Assessment A disclosed access token grants the associated 1688 API permissions for its lifetime. Disclosure of the AppSecret compromises the application's signing secret and may enable request signing or token operations when combined with an authorization code or refresh token. The operating-sys ...[truncated 147 chars]
Remediation
View remediation
Vulnerability Patterns
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (74)

Tainted flow: 'token_url' from os.getenv (line 75, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/auth.py (reported line 84)May include surrounding context.

python
}
        
        try:
            response = requests.post(token_url, data=data, timeout=10)
            response.raise_for_status()
            token_data = response.json()

Tainted flow: 'token_url' from os.getenv (line 76, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/auth_fixed.py (reported line 85)May include surrounding context.

python
}
        
        try:
            response = requests.post(token_url, data=data, timeout=10)
            response.raise_for_status()
            token_data = response.json()

Tainted flow: 'url' from os.getenv (line 85, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/image_search_handler.py (reported line 86)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=30)
        response.raise_for_status()
        return response.json()

Tainted flow: 'url' from os.getenv (line 85, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/image_search_handler.py (reported line 120)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 384, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 51)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 384, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 82)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 384, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 143)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 416, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 192)May include surrounding context.

python
params['_aop_signature'] = sign

        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=30)
        response.raise_for_status()
        result = response.json()

Tainted flow: 'url' from os.getenv (line 416, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 417)May include surrounding context.

python
params['_aop_signature'] = sign

        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=30)
        response.raise_for_status()
        result = response.json()

Tainted flow: 'url' from os.getenv (line 191, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 232)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 191, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 258)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 191, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 284)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 191, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 310)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 191, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 359)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 191, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search.py (reported line 385)May include surrounding context.

python
params['_aop_signature'] = sign
    
    url = f"{BASE_URL}/{url_path}"
    response = requests.post(url, data=params, timeout=15)
    response.raise_for_status()
    return response.json()

Tainted flow: 'url' from os.getenv (line 68, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_fixed.py (reported line 69)May include surrounding context.

python
}
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=30)
        response.raise_for_status()
        
        result = response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 99)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=30)
        response.raise_for_status()
        result = response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 150)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=15)
        response.raise_for_status()
        return response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 215)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=15)
        response.raise_for_status()
        return response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 246)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=15)
        response.raise_for_status()
        return response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 272)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=15)
        response.raise_for_status()
        return response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 297)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=15)
        response.raise_for_status()
        return response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 323)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=15)
        response.raise_for_status()
        return response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 349)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=15)
        response.raise_for_status()
        return response.json()

Tainted flow: 'url' from os.getenv (line 149, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/product_search_updated.py (reported line 373)May include surrounding context.

python
params['_aop_signature'] = sign
        
        url = f"{BASE_URL}/{url_path}"
        response = requests.post(url, data=params, timeout=15)
        response.raise_for_status()
        return response.json()

Static analysis

No suspicious patterns detected.