Back to skill

Security audit

利润核算专家

Security checks across malware telemetry and agentic risk

Overview

This is a real LinkFox profit-analysis workflow, but it bundles broad account, payment, upload, scheduling, catalog-write, memory, and telemetry capabilities that need careful review before installation.

Install only if you trust LinkFox with your marketplace research data and API key. Expect ASINs, product images, keywords, reports, and account/onboarding data to be sent to LinkFox services and saved locally under session directories. Do not set LinkFox endpoint override environment variables unless you control and trust the destination. Before use, confirm any public upload, scheduled task, product-center write, payment/order action, or remembered parameter is intentional.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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
Findings (514)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
timed_out = False
    try:
        proc = subprocess.run(
            [sys.executable, str(main_script), params_str],
            capture_output=True,
            text=True,
Confidence
95% confidence
Finding
The helper executes whatever script path is supplied via --script using subprocess.run, with only an existence check and no allowlist, confinement, or verification that the target belongs to the intended skill. In an agent setting, this creates a generic local code-execution wrapper that can run unintended or attacker-chosen scripts, which is especially risky because the skill is supposed to perform profit calculation, not arbitrary program dispatch.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run_script(script_path: Path, args: list[str], cwd: Path, timeout: int = 30) -> tuple[int, str, str]:
    """跑一次脚本,返回 (returncode, stdout, stderr)。"""
    try:
        proc = subprocess.run(
            [sys.executable, str(script_path), *args],
            capture_output=True,
            text=True,
Confidence
96% confidence
Finding
This code launches Python scripts from a user-supplied skill directory using subprocess.run(). Although it avoids shell=True, it still executes arbitrary local code from that directory, so any malicious script placed under scripts/ will run with the verifier's privileges. In the context of a profit-calculation skill, this execution capability is unnecessary and materially increases the attack surface.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
timed_out = False
    try:
        proc = subprocess.run(
            [sys.executable, str(main_script), params_str],
            capture_output=True,
            text=True,
Confidence
95% confidence
Finding
The code executes a script path supplied via the CLI (`--script`) using `subprocess.run`, which creates a generic local code-execution primitive. Although it avoids shell injection by passing an argument list, it still allows arbitrary Python files to be launched and therefore can execute untrusted local code if an attacker can influence the script path or workflow inputs.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
timed_out = False
    try:
        proc = subprocess.run(
            [sys.executable, str(main_script), params_str],
            capture_output=True,
            text=True,
Confidence
94% confidence
Finding
The wrapper executes a script path supplied via the `--script` argument using `subprocess.run`, which gives the caller a generic code-execution primitive. Although arguments are passed as a list rather than through a shell, this still broadens the skill from profit calculation into arbitrary local program execution, which is dangerous in an agent context where inputs may be influenced by untrusted prompts or tool chains.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=120) 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
96% confidence
Finding
The request ultimately uses environment-controlled values in security-sensitive places: the destination base URL can be overridden by LINKFOX_TOOL_GATEWAY and sensitive headers include the API key and session metadata. This means an attacker who can influence the runtime environment can redirect authenticated traffic to an arbitrary host and exfiltrate credentials or query data. In an agent skill context, environment variables are often trusted implicitly, which makes this more dangerous than ordinary configuration use.

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

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
96% confidence
Finding
The POST destination is derived from environment-controlled base URLs and can send sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, and generated API tokens to attacker-chosen endpoints if those environment variables are overridden. Because this script performs authentication and token exchange, SSRF/exfiltration via env-configured endpoints is materially dangerous, not just a generic configurability issue.

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

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
95% confidence
Finding
The urllib request target is built from environment-controlled gateway base URLs and includes the Authorization header populated from LINKFOX API key material. An attacker who can influence environment variables can redirect these authenticated requests to an external server and capture credentials or force unintended network access.

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

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
95% confidence
Finding
The code builds request destinations from environment-controlled base URLs and then sends authentication material, SMS-login data, and token-related payloads to those endpoints via requests.post. If an attacker can influence environment variables in the runtime, they can redirect these calls to attacker-controlled infrastructure and capture phone numbers, verification codes, access tokens, refresh tokens, and generated API keys.

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

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
95% confidence
Finding
The gateway request path uses environment-derived base URLs and sends the API key in the Authorization header through urllib.request.urlopen. An attacker who can set LINKFOX_AGENT_API_URL or related variables can exfiltrate the API key and influence all account/package/order operations, enabling credential theft and misuse of paid account capabilities.

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

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
93% confidence
Finding
The POST destination is derived from environment-controlled base URLs, and the request can carry sensitive authentication material such as access tokens, API keys, phone numbers, and SMS codes. In a skill environment where deployers or wrappers may influence environment variables, this creates an SSRF/exfiltration path that can redirect secrets to attacker-controlled infrastructure.

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

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
93% confidence
Finding
The gateway request URL is also built from environment-controlled base configuration and is used with the Authorization header populated from the API key. If an attacker can influence environment variables, they can cause authenticated requests to be sent to a malicious host, leaking the API key and enabling unauthorized account actions.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=120) 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
The request sent via urlopen includes multiple attacker-influenced environment variables in headers, and the destination base URL is also overridable through LINKFOX_TOOL_GATEWAY. In an agent/runtime context, this can exfiltrate API keys, session identifiers, and task metadata to an untrusted endpoint if the environment is manipulated, making the tainted flow a real data-leak risk rather than a mere implementation detail.

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

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
95% confidence
Finding
The code builds request destinations from environment-controlled base URLs and then sends sensitive data, including SMS login details, bearer tokens, and API-token operations, to those endpoints with requests.post. In a hostile or misconfigured runtime, an attacker can redirect traffic to attacker-controlled infrastructure and capture credentials or tokens, making this a real SSRF/exfiltration risk rather than a harmless configuration pattern.

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

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
94% confidence
Finding
The gateway URL is derived from environment variables and used by urllib.request.urlopen with the API key in the Authorization header. If an attacker can influence the environment, they can redirect this request stream to a malicious server and harvest the LinkFox API key or manipulate package/order operations.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=120) 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
92% confidence
Finding
The request sent via urlopen includes multiple environment-derived values in headers, and the destination base URL is also overrideable through LINKFOX_TOOL_GATEWAY. That creates a real exfiltration path: if an attacker can influence environment variables or skill execution context, the script can send API keys, session identifiers, and app metadata to an arbitrary remote endpoint.

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

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
97% confidence
Finding
The code builds request destinations from environment-controlled base URLs and then sends sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys to those endpoints. In a skill/runtime environment where env vars can be influenced by a host or attacker, this creates an SSRF/exfiltration path that can redirect credentials and onboarding traffic to attacker-controlled infrastructure.

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

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
97% confidence
Finding
The gateway client uses an environment-derived base URL and attaches the API key in the Authorization header before calling urlopen. If the environment points to an attacker-controlled host, the skill will disclose the API key and perform arbitrary outbound requests, which is especially dangerous in an agent execution environment.

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

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
95% confidence
Finding
The script builds request destinations from environment-controlled base URLs and then sends sensitive data to them via requests.post. Because this file handles phone numbers, SMS codes, access tokens, refresh tokens, API tokens, and account metadata, an attacker who can influence environment variables can redirect these secrets to an arbitrary host, creating a credential exfiltration path.

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

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
94% confidence
Finding
The gateway URL is also derived from environment variables and used in urllib.request.urlopen with the Authorization header populated from LINKFOX API keys. If an attacker can set the environment, they can cause the client to send the bearer credential and business requests to an attacker-controlled server, leaking secrets and enabling account misuse.

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

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=120) 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
The request URL and outbound headers are influenced by environment variables, including LINKFOX_TOOL_GATEWAY and session metadata, and the code sends the API key in an Authorization header to whatever gateway is configured. If an attacker can control the environment or execution context, they can redirect requests to an attacker-controlled host and exfiltrate credentials and query data.

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

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
92% confidence
Finding
The POST target is ultimately derived from environment-configurable base URLs, so a caller who can influence environment variables can redirect authentication traffic and sensitive payloads to an attacker-controlled endpoint. This is especially dangerous here because the same flow handles phone numbers, SMS codes, access tokens, refresh tokens, and API-token issuance during onboarding.

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

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
91% confidence
Finding
The gateway request URL is built from environment-derived base configuration and then used in urlopen with the API key attached in the Authorization header. If an attacker can set or influence those environment variables, they can exfiltrate the API key and redirect package, order, and account queries to malicious infrastructure.

Tainted flow: 'script' from os.environ.get (line 108, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
env["PYTHONIOENCODING"] = "utf-8"

    try:
        r = subprocess.run(
            [sys.executable, str(script), params],
            capture_output=True, text=True, encoding="utf-8",
            errors="replace", env=env, timeout=30,
Confidence
88% confidence
Finding
The script path can fall back to a location derived from HOME, which is taken from the environment and then executed via Python. If an attacker can influence the process environment or place a malicious file at that fallback path, this becomes arbitrary code execution under the privileges of the current process.

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

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
94% confidence
Finding
The code builds request destinations from environment-controlled base URLs and then sends sensitive authentication material such as SMS login data, access tokens, refresh tokens, uid headers, and API-token requests to those endpoints. If an attacker can influence environment variables in the skill runtime, they can redirect these calls to attacker-controlled infrastructure and harvest credentials or session data.

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

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
95% confidence
Finding
The gateway URL is derived from environment variables and used by urllib to send authenticated API requests containing the agent API key in the Authorization header. An attacker controlling the environment can reroute these requests to capture API keys, user/order data, or manipulate downstream behavior such as plan listing and order creation.

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
skills/linkfox-task-scheduler/references/api.md:57