Back to skill

Security audit

Linkfox 亚马逊广告

Security checks across malware telemetry and agentic risk

Overview

The skill appears to be a legitimate Amazon Ads integration, but it handles credentials and business reports with several under-scoped behaviors that warrant review before installation.

Review this skill carefully before installing. Use it only in an environment where Amazon Ads credentials and reports can be stored locally, avoid untrusted environment variables for API host configuration, do not bind report-serving features to non-local interfaces, and prefer disabling or cleaning persisted outputs if the skill supports it.

SkillSpector

By NVIDIA
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 Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (21)

Tainted flow: 'req' from os.environ.get (line 45, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=60) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""
Confidence
95% confidence
Finding
with urlopen(req, timeout=60) as response:

Tainted flow: 'req' from os.environ.get (line 40, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=60) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""
Confidence
93% confidence
Finding
with urlopen(req, timeout=60) as response:

Tainted flow: 'req' from os.environ.get (line 42, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=60) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""
Confidence
97% confidence
Finding
with urlopen(req, timeout=60) as response:

Tainted flow: 'req' from os.environ.get (line 42, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=60) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""
Confidence
88% confidence
Finding
with urlopen(req, timeout=60) as response:

Tainted flow: 'req' from os.environ.get (line 42, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=60) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""
Confidence
94% confidence
Finding
with urlopen(req, timeout=60) as response:

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The module silently adds a persistence layer that writes full API responses and session metadata to local disk under multiple fallback directories. In this skill context, API responses may contain advertising data, identifiers, and possibly token-bearing or otherwise sensitive operational information, so unrelated local retention expands exposure beyond the stated helper role.

Intent-Code Divergence

Medium
Confidence
81% confidence
Finding
The docstring describes this file as a narrow shared helper for auth and listing, but the implementation also includes mutation and persistent output capabilities. This mismatch is risky because consumers may trust-import the module without realizing it can modify upstream state and persist retrieved data locally, reducing transparency and informed consent.

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The script advertises that it will POST to an ad-type-specific endpoint, constructs `entity_path`, and retrieves an access token, but the actual `mutate_entity()` call does not pass either value. This creates a dangerous mismatch between the documented/validated operation and the real network action, so callers may believe they are creating one ad type while the helper may target a different endpoint or use implicit defaults, causing unintended remote mutations in an advertising account.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The script downloads potentially sensitive Amazon Ads report data, then starts an HTTP server to expose the extracted file and returns the URL. Although the default bind address is localhost, the host is user-configurable and the feature is enabled by default, which can unintentionally disclose report contents to other local users, browser extensions, forwarded ports, or network peers if bound non-locally.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The docstring states the script only acts as an asynchronous report executor, but the implementation also hosts downloaded report contents over HTTP. This mismatch is dangerous because operators may underestimate the skill's exposure behavior and run it in environments where local serving of sensitive data is not acceptable.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The skill hard-codes a requirement that onboarding must use a specific channel value ('workbuddy') regardless of user choice or deployment context. This can override normal user consent and routing expectations, causing actions such as account registration or authentication to occur under an unintended platform context, which may misbind accounts, misattribute activity, or violate tenant/channel separation assumptions.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill explicitly instructs writing full API responses to persistent disk, and those responses can contain sensitive token material and account-linked metadata. Even if stdout masking is mentioned elsewhere, persistent raw JSON storage increases the risk of credential leakage through local compromise, backups, logs, or later accidental disclosure.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The document instructs downloading and installing another skill from a remote ZIP URL without any integrity verification, provenance check, or safety warning. This creates a supply-chain risk: a compromised hosting endpoint or swapped archive could introduce malicious code or unsafe instructions into the agent environment.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill instructs persisting full API/report responses to local disk under a predictable path, but does not require user consent, retention limits, or redaction. Amazon Ads reports can contain sensitive business data, so silent persistence increases the risk of unintended disclosure to other local users, backup systems, logs, or later tool invocations.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill directs the agent to expose extracted report data through a temporary local HTTP URL, but gives no privacy warning and treats the link as a normal output artifact. Even when bound to 127.0.0.1, locally hosted sensitive data can be accessed by other local processes, browser extensions, malware, shared-user environments, or accidentally surfaced in logs and transcripts.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The code trusts SESSION_ID from the environment and later uses it as part of the on-disk session path and metadata, which can expose a sensitive identifier and tie persisted artifacts to external runtime context without user awareness. In security-sensitive auth tooling, environment values often carry tenant, job, or session correlation data that should not be silently recorded to disk.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
emit_result() serializes and writes the full result payload to disk unconditionally before deciding whether to print only a summary. For an auth-related skill, response bodies can include tokens, account identifiers, user data, or error details, so this creates durable local copies of sensitive data in multiple writable locations, including potentially shared or weakly protected temp/workspace directories.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
emit_result() serializes and writes complete API responses to disk, then updates session indexes, without explicit warning or consent at the point of use. In a credentialed Amazon Ads management skill, this can leave sensitive business data and metadata on shared or weakly protected hosts, creating unnecessary local data exposure.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Sensitive report contents are served over a temporary HTTP endpoint by default, without requiring an explicit user-facing acknowledgment at execution time. In a reporting skill handling ad/account data, surprise exposure of downloaded content materially increases the chance of accidental disclosure.

Ssd 3

Medium
Confidence
97% confidence
Finding
The required behavior is to write complete API responses to disk, and the same skill defines endpoints that return access and refresh tokens plus account identifiers. In this context, mandatory disk persistence materially raises exposure of credentials and user-associated advertising account data beyond the immediate runtime need.

Credential Access

High
Category
Privilege Escalation
Content
print(f"🔑 Fetching access token for profileId={profile_id}…", file=sys.stderr)
    result = call_gateway(STORE_TOKENS_ENDPOINT, {"profileId": int(profile_id)})
    if "error" in result or "accessToken" not in result:
        print(f"❌ Failed to get access token: {result}", file=sys.stderr)
        sys.exit(1)
    return result["accessToken"]
Confidence
78% confidence
Finding
access token

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

No suspicious patterns detected.