Back to skill

Security audit

Fake International Brand Detector

Security checks for vulnerabilities and agentic risk

Overview

This brand-checking skill is mostly purpose-aligned, but it has unsafe input handling and can produce overconfident authenticity verdicts from hard-coded or weak evidence.

Install only if you are comfortable with the skill sending brand names to public websites and Tavily, and treat its verdicts as leads rather than proof. Avoid using sensitive unreleased brand names, do not pass arbitrary URL-like strings as brand names, and require human review before making purchasing, legal, or reputational decisions from its output.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/detect_brand.py:17
Finding

User-Controlled URL Construction Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: scripts/detect_brand.py:17-26; equivalent patterns also occur in scripts/detect_brand_real.py:46-58 and scripts/detect_brand_v2.py:83-89
Vulnerability Type: Server-Side Request Forgery through insufficient URL validation
Risk Level: High

python
def check_website_exists(brand):
    """Check whether the brand website exists."""
    domains = [
        f"https://www.{brand}.com",
        f"https://{brand.lower()}.com",
        f"https://www.{brand}.net"
    ]

    for domain in domains:
        try:
            response = requests.get(
                domain,
                timeout=10,
                allow_redirects=True
            )

The other affected implementations use the same unvalidated brand value when building URLs:

python
domains = [
    f"https://www.{brand}.com",
    f"https://{brand.lower()}.com",
    f"https://www.{brand}.net"
]
python
domains = [f"www.{self.brand}.com", f"www.{self.brand}.com/en"]

for domain in domains:
    try:
        response = requests.get(
            f"https://{domain}",
            timeout=10,
            allow_redirects=True
        )

Technical Analysis

The required --brand argument is accepted as an unrestricted string and interpolated directly into a URL. Characters with URL semantics, including #, ?, /, and @, are not rejected or encoded. Consequently, the hostname interpreted by the HTTP client may differ from the intended brand.com hostname.

For example, a value containing a fragment delimiter can cause the appended .com text to be interpreted as a fragment rather than part of the hostname. The HTTP client may therefore connect to an attacker-selected host. The code also follows redirects automatically without validating the address of each redirect target.

No DNS-resolution checks reject loopback, private, link-local, multicast, or o ...[truncated 1618 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict brand values to a conservative format, such as ASCII letters, digits, and hyphens:
    python
    if not re.fullmatch(r"[A-Za-z0-9-]{1,63}", brand):
        raise ValueError("Invalid brand name")
    
  2. Reject dots, URL delimiters, whitespace, control characters, path separators, and percent-encoded delimiters.
  3. Construct URLs with urllib.parse rather than string interpolation.
  4. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, reserved, and unspecified ranges.
  5. Disable automatic redirects or validate the hostname and resolved IP address at every redirect hop.
  6. Apply an outbound network policy that permits only required public search and marketplace services.
  7. Add tests for malformed input, IPv4 and IPv6 literals, URL fragments, user-information syntax, alternate numeric IP formats, DNS rebinding, and redirect-to-private-address behavior.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/detect_brand_real.py:379
Finding

Predictable User-Controlled Temporary File Path Enables File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/detect_brand_real.py:379-380
Vulnerability Type: Path traversal and insecure temporary-file creation
Risk Level: Medium

python
with open(f"/tmp/{brand}_report.md", "w") as f:
    f.write(md_content)

Technical Analysis

The untrusted brand name is embedded directly into a filesystem path. The code does not reject path separators or traversal components and opens the resulting path in write mode. A value containing ../ can escape the intended /tmp location, subject to the generated _report.md suffix.

The filename is also predictable and created in a shared temporary directory without exclusive creation or symbolic-link protections. Another local process can pre-create the expected path as a symbolic link. When the report is generated, Python follows that link and truncates the linked target.

Attack Path

Path-traversal scenario:

  1. An attacker supplies a brand name containing traversal components and a chosen path.
  2. The application constructs /tmp/{brand}_report.md.
  3. Filesystem normalization resolves the traversal outside /tmp.
  4. The target file is opened with mode "w", causing creation or truncation.
  5. Report content is written to the selected path if the Skill account has permission.

Symbolic-link scenario:

  1. A local attacker predicts the report filename for a brand.
  2. The attacker creates that path in /tmp as a symbolic link to another file.
  3. The Skill opens the predictable path without exclusive or no-follow protections.
  4. The linked target is truncated and replaced with generated report content.

Impact Assessment

Exploitation can overwrite files writable by the Skill process. The exact impact depends on the runtime account and filesystem permissions. Under a privileged account, this could damage application configuration or other operational files; under an unprivileged account, it can still ...[truncated 255 chars]

Remediation
View remediation

Remediation Suggestions

  1. Use Python's tempfile module with unpredictable, securely created files:
    python
    import tempfile
    
    with tempfile.NamedTemporaryFile(
        mode="w",
        encoding="utf-8",
        prefix="brand_report_",
        suffix=".md",
        delete=False
    ) as report:
        report.write(md_content)
        report_path = report.name
    
  2. Do not include raw user input in a filesystem path.
  3. If a user-visible filename is required, derive it from a strict allowlist and verify that the resolved destination remains inside a dedicated report directory.
  4. Use exclusive file creation and protections against symbolic-link following.
  5. Give the Skill a private temporary directory with restrictive permissions rather than using a predictable shared /tmp path.
  6. Run the Skill under a dedicated, unprivileged account with no write access to sensitive application or system files.

other

Warning
Location
scripts/detect_brand_v2.py:144
Finding

Hard-Coded Evidence Produces Unsupported Brand Authenticity Findings

Content
View full analysis

Vulnerability Details

File Location: scripts/detect_brand_v2.py:144-157, scripts/detect_brand_v2.py:241-260, and scripts/detect_brand_v2.py:306-365
Vulnerability Type: Integrity failure caused by fabricated verification evidence
Risk Level: Medium

The sales-channel check records a Boots partnership without performing a query:

python
def check_sales_channels(self):
    """Check overseas sales channels."""
    print(f"\n🔍 Check 3/7: Overseas sales channel verification")

    channels = {"physical_stores": [], "online_partners": []}
    platforms = [("Boots UK", "UK"), ("CVS Pharmacy", "US")]
    for platform, region in platforms:
        try:
            if platform == "Boots UK":
                channels["online_partners"].append({
                    "platform": platform,
                    "location": region
                })
        except:
            continue

    return {
        "channels": channels,
        "quality_score": min(
            8.5,
            len(channels["physical_stores"]) * 1.0
            + len(channels["online_partners"]) * 2.0
        )
    }

The Amazon seller-location check assigns China as the seller location for every dynamically checked brand:

python
def check_amazon_seller_location(self):
    """New check 7/7: Amazon seller location."""
    print(f"\n🔍 Check 7/7: Amazon seller nationality verification")
    return {
        "amazon_de_seller_country": "CN",
        "amazon_uk_seller_country": "CN",
        "expected_countries": ["DE", "UK"],
        "match": False,
        "quality_score": 0
    }

The known-brand result generator also emits synthetic evidence, including fixed article counts, seller locations, and quality scores:

python
"media_exposure": {
    "found": known_info.get("media_coverage", False),
    "sources_checked": ["Forbes", "Reuters", "WebMD"],
    "articles_found": 10,

...[truncated 2864 chars]
Remediation
View remediation

Remediation Suggestions

  1. Return unknown or not_checked for every factor that was not actually queried.
  2. Never convert missing evidence into an adverse finding such as a Chinese seller location.
  3. Remove hard-coded retailer partnerships and seller nationalities from dynamic checks.
  4. Require each evidence item to include its source URL, retrieval timestamp, extraction method, and raw supporting field.
  5. Separate static fixtures and test data from production verification results.
  6. If known-brand records are retained, label them as cached assertions with provenance and an expiration date rather than presenting them as live checks.
  7. Exclude unavailable factors from confidence scoring, or reduce confidence explicitly when evidence is missing.
  8. Add schema-level evidence states such as verified, unverified, cached, failed, and not_applicable.
  9. Add regression tests ensuring that network failures and missing API credentials cannot create affirmative or adverse evidence.
  10. Require human review before emitting high-confidence accusations that a brand is fraudulent or falsely international.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (44)

Tainted flow: 'tavily_api_key' from os.environ.get (line 185, 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/detect_brand.py (reported line 219)May include surrounding context.

python
}
    
    try:
        response = requests.post(
            tavily_url,
            json={**tavily_params, "api_key": tavily_api_key},
            timeout=30

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The skill is documented entirely in Chinese and presents activation, usage, output examples, and guidance as if Chinese is the required interaction language, with no indication that users may choose another language. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill declares default automatic activation on broad keywords such as 'brand authenticity' and 'supplement brand', which can cause the agent to invoke this capability on ordinary user conversations without clear consent. Because the skill appears designed to perform investigative checks and potentially external lookups, broad auto-triggering increases the chance of unnecessary data handling, misclassification, and unintended workflow execution.

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 · SKILL.md (reported line 66)May include surrounding context.

python
import requests

response = requests.post(
    "http://localhost:8080/api/detect",
    json={"brand": "Nike", "mode": "quick"},
    headers={"Content-Type": "application/json"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · SKILL.md (reported line 66)May include surrounding context.

python
import requests

response = requests.post(
    "http://localhost:8080/api/detect",
    json={"brand": "Nike", "mode": "quick"},
    headers={"Content-Type": "application/json"}

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

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

python
import requests

response = requests.post(
    "http://localhost:8080/api/detect",
    json={"brand": "Nike", "mode": "quick"},
    headers={"Content-Type": "application/json"}

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file presents all operational guidance, examples, and safety notes exclusively in Chinese. Under the stated policy, forcing a specific language without offering the user a language or locale choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The JSON includes verdict text in Chinese ("✅ 真国际品牌") even though the rest of the data uses English field names and values, indicating a forced language choice in natural-language content. The file provides no opt-in, alternative locale, or documented reason for restricting output language, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The JSON includes verdict text in Chinese ("✅ 真国际品牌") even though the rest of the data uses English field names and values, indicating a forced language choice in natural-language content. The file provides no opt-in, alternative locale, or documented reason for restricting output language, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The JSON includes verdict text in Chinese ("✅ 真国际品牌") even though the rest of the data uses English field names and values, indicating a forced language choice in natural-language content. The file provides no opt-in, alternative locale, or documented reason for restricting output language, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The JSON includes verdict text in Chinese ("🚩 假国际品牌") even though the rest of the data uses English field names and values, indicating a forced language choice in natural-language content. The file provides no opt-in, alternative locale, or documented reason for restricting output language, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The JSON includes verdict text in Chinese ("🚩 假国际品牌") even though the rest of the data uses English field names and values, indicating a forced language choice in natural-language content. The file provides no opt-in, alternative locale, or documented reason for restricting output language, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file presents all instructions and scoring criteria only in Chinese, which can amount to a language/locale policy violation when no user opt-in or alternative language path is provided. The document does not state that the skill is intentionally limited to Chinese-speaking users or a China-specific compliance context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This manifest-style JSON includes user-facing classification text in Chinese, such as the verdict value on L019, without any indication that language selection is configurable or limited to a justified locale. The same pattern recurs throughout the file, which can violate language/locale policy when a skill implicitly forces one language for outputs.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring says the script verifies brands via 'Tavily Web Search + Browser' tools. In practice, most checks use requests against brand sites, Amazon, Reddit, and a Tavily call only in one function, with subprocess-based Google/curl fallbacks instead of any browser tool integration. This is an active mismatch between the documented implementation approach and the actual code path.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The natural-language strings, docstrings, CLI description, and all user-facing output are exclusively in Chinese, with no option to select another language or locale. Under the policy rule, forcing a specific language without user opt-in is a language/locale policy violation unless the constraint is explicitly documented and justified, which it is not here.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The function documentation says it checks overseas sales channels using a 'Google Places API alternative'. However, the code first queries Amazon search results and later runs a local 'google search' command, then returns a generic API-key-related result without performing a real Places-equivalent store lookup. That is a contradiction between the stated intent and the implemented behavior.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/detect_brand.py (reported line 98)May include surrounding context.

python
# 使用 Google 地图搜索实体店(简化)
    try:
        google_query = f"{brand} supplement stores near me"
        result = subprocess.run(
            ["google", "search", google_query],
            capture_output=True,
            timeout=10,

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 · scripts/detect_brand.py (reported line 175)May include surrounding context.

python
"""检查海外媒体报道 - 使用 Tavily Web Search API(从环境变量读取 Key)"""
    print(f"\n🔍 检查项 4/4: 海外媒体曝光")
    
    tavily_url = "https://api.tavily.com/search"
    tavily_params = {
        "query": f"{brand} brand history official website international supplements reviews",
        "search_depth": "advanced",

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 · scripts/detect_brand_v2.py (reported line 204)May include surrounding context.

python
"""检查海外媒体报道 - 使用 Tavily Web Search API(从环境变量读取 Key)"""
    print(f"\n🔍 检查项 4/4: 海外媒体曝光")
    
    tavily_url = "https://api.tavily.com/search"
    tavily_params = {
        "query": f"{brand} brand history official website international supplements reviews",
        "search_depth": "advanced",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sends user-supplied brand queries to third-party services such as Tavily, Google News, Amazon, and Reddit without clear user disclosure or consent. In a skill/agent context, this matters because user inputs may be sensitive business research terms, and silent transmission expands privacy, compliance, and data-handling risk.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

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

python
# 🛠️ 备用方案:通过 whois.domaintools.com 和新闻搜索
        try:
            import subprocess
            result = subprocess.run(
                ["curl", "-s", "https://news.google.com/search?q=brand+introduction+%26+official+website+%26+sustainability",
                 f"&q={brand} supplements reviews history site:*.com"],
                capture_output=True,

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This POST sends user-derived search content, and an API credential, to an external service. In isolation external transmission is expected for a search integration, but in an agent skill it becomes security-relevant when done without prominent disclosure or control, because it can expose sensitive investigation terms to third parties.

Content

Scanner excerpt · scripts/detect_brand.py (reported line 219)May include surrounding context.

python
}
    
    try:
        response = requests.post(
            tavily_url,
            json={**tavily_params, "api_key": tavily_api_key},
            timeout=30

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The code treats English presence as a positive quality signal by setting languages to ["en"] and scoring based on has_english, which encodes a language preference into the skill's behavior. This is a locale/language policy concern because users are not offered any choice or justification for privileging English content.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The hard-coded Tavily endpoint indicates built-in third-party data exfiltration capability tied to runtime environment credentials. In this skill, the broader context increases risk because the script performs multiple undisclosed external lookups and can silently expand user input into external intelligence-gathering queries.

Content

Scanner excerpt · scripts/detect_brand_real.py (reported line 190)May include surrounding context.

python
print(f"\n🔍 检查项 4/4: 海外媒体曝光")
    
    # 方法 1:Tavily API(如果配置了有效 Key)
    tavily_url = "https://api.tavily.com/search"
    api_key = getattr(subprocess.os.environ, "TAVILY_API_KEY", None)
    
    if api_key and len(api_key) > 8:

Static analysis

No suspicious patterns detected.