Back to skill

Security audit

Linkfox 亚马逊广告

Security checks for vulnerabilities and agentic risk

Overview

This Amazon Ads skill is mostly purpose-aligned, but it handles advertising credentials and business data with several under-scoped exposure paths users should review first.

Install only if you trust LinkFox with Amazon Ads account access and advertising-spend changes. Before use, avoid custom gateway/login environment variables, disable report HTTP serving unless needed, do not bind report serving to non-loopback addresses, store API keys in a real secret manager rather than shell startup files, and require explicit confirmation before any create/update/budget/bid operation.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (5)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:208
Finding

Skill instructions override the agent's runtime identity and onboarding behavior

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/report/get_report.py:286
Finding

User-controlled bind address can expose sensitive advertising reports without authentication

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/manager/_common.py:40
Finding

Unvalidated gateway overrides can receive LinkFox API keys and Amazon access tokens

Content
View full analysis
dict: api_key = get_api_key() data = json.dumps(payload).encode("utf-8") req = Request( endpoint, data=data, headers={ "Authorization": api_key, "Content-Type": "application/json", "User-Agent": "LinkFox-Skill/1.0", }, method="POST", ) try: with urlopen(req, timeout=150) as resp: return json.loads(resp.read().decode("utf-8")) ``` ```python def get_access_token(profile_id: int) -> str: 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"] ``` ```python def _developer_proxy_call(region: str, path: str, method: str, access_token: str, profile_id: int, body: str | None, content_type: str | None, query_string: str | None) -> dict: payload: dict[str, Any] = { "region": region, "path": path, "method": method, "amzAccessToken": access_token, "profileId": int(profile_id), } return call_gateway(DEVELOPER_PROXY_ENDPOINT, payload) ``` ### Technical Analysis The gateway base URL can be replaced throug ...[truncated 2075 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
references/linkfox-amazon-ads-auth.md:135
Finding

Onboarding Skill installation uses a mutable archive without integrity verification

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
references/onboarding.md:11
Finding

Onboarding guidance persists API keys in plaintext shell configuration

Content
View full analysis
"` - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.zshrc && source ~/.zshrc` - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.bashrc && source ~/.bashrc` - 变量名 `LINKFOX_AGENT_API_KEY`(主推)或 `LINKFOXAGENT_API_KEY`(老规范)任一即可 ``` These instructions direct the user to store the API key permanently through `setx` or by appending it to shell startup files. ### Technical Analysis The onboarding workflow returns the API key and recommends persisting it directly in environment configuration. On macOS and Linux, the credential is written as plaintext to `.zshrc` or `.bashrc`. The command itself may also be retained in shell history. On Windows, `setx` persists the value as a user environment variable, where it may be accessible to other processes running as that user. Shell initialization files are commonly copied into backups, diagnostic bundles, dotfile repositories, or support archives. Their permissions may also be broader than appropriate for secret material. The approach therefore increases the lifetime and exposure surface of a credential used for authenticated and potentially billable gateway operations. ### Attack Path 1. The user completes onboarding and receives an API key. 2. The user executes the provided persistence command. 3. The API key is written to a shell configuration file, user environment storage, and potentially command history. 4. Malware, another same-user process, an accidental dotfile commit, a backup reader, or a support-bundle recipient obtains the plaintext key. 5. The exposed key is reused against LinkFox services until it is revoked or expires. ### Impact Assessment An attacker can exerc ...[truncated 305 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (91)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The request destination is derived from environment variables, allowing a caller or surrounding runtime to redirect this script to an arbitrary host. Because the script automatically includes the authorization API key in the Authorization header, a malicious override can exfiltrate credentials and receive sensitive request data intended for the trusted LinkFox gateway.

Content

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

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The request destination is derived from environment variables (LINKFOX_TOOL_GATEWAY or AMAZON_ADS_BASE_URL) and is used directly in urlopen without validation or allowlisting. An attacker who can influence the runtime environment can redirect this authenticated request, including the Authorization API key, to an attacker-controlled endpoint, causing credential exfiltration and potentially unauthorized access to downstream services.

Content

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

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

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

Critical
Category
Data Flow
Confidence
93% confidence
Finding

The request destination is derived from environment variables (LINKFOX_TOOL_GATEWAY or AMAZON_ADS_BASE_URL) and then used directly in urlopen without allowlisting or validation. In a hostile or misconfigured runtime, an attacker who can influence environment variables can redirect this authenticated request, including the Authorization API key, to an attacker-controlled endpoint, causing credential exfiltration and unintended outbound access.

Content

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

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

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

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The request destination is derived from environment-controlled base URL settings and is then used for a credentialed outbound POST. If an attacker can influence LINKFOX_TOOL_GATEWAY or AMAZON_ADS_BASE_URL, the script will send the Authorization API key and token-refresh payload to an arbitrary host, creating a server-side credential exfiltration path.

Content

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

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

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

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The request target is derived from environment variables (LINKFOX_TOOL_GATEWAY or AMAZON_ADS_BASE_URL) and then used directly in urlopen while sending the Authorization API key header. If an attacker can influence the environment, they can redirect the request to an attacker-controlled endpoint and exfiltrate the API key and requested token data; the skill context is especially sensitive because this script retrieves advertising access and refresh tokens.

Content

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

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The code builds request destinations from environment variables via _login_base() and _agent_user_base(), then sends sensitive authentication material such as SMS login data, access tokens, refresh tokens, generated API tokens, and user identifiers to those URLs. In a skill/agent environment, environment variables are often externally configurable, so an attacker who can influence them can redirect these requests to a malicious host and exfiltrate credentials.

Content

Scanner excerpt · scripts/onboarding.py (reported line 196)May include surrounding context.

python
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 = ""

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The gateway URL is derived from environment variables and used in urlopen with an Authorization header containing the LinkFox API key. If an attacker can control LINKFOX_AGENT_API_URL or LINKFOX_TOOL_GATEWAY, they can redirect gateway calls to an arbitrary server and capture the API key and account/order data.

Content

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

python
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

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

This skill explicitly supports refreshing and retrieving Amazon Ads access credentials, making it a credential-handling component with real token exposure risk if downstream skills, logs, or stdout leak the returned values. The danger is increased by the documented behavior of writing full responses to disk and, for small responses or with --inline, printing full JSON to stdout, which may include accessToken and refreshToken.

Content

Scanner excerpt · references/linkfox-amazon-ads-auth.md (reported line 49)May include surrounding context.

md
### 步骤 4:刷新过期令牌

- 【输入】`profileId` 或 `authRecordId`
- 【动作】下游返回 HTTP 401 或错误体含 `expired`/`unauthorized`/`access token` 时,调 `refresh_token.py`
- 【输出】新的 `accessToken`(有效期 1 小时)

## 核心概念

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The refreshToken and storeTokens interfaces are documented as returning live accessToken and refreshToken values. In the context of this skill, that is security-sensitive because bearer tokens grant API access; if exposed through logs, saved JSON artifacts, chat context, or unauthorized skill chaining, they can be reused to access or manipulate the connected Amazon Ads account.

Content

Scanner excerpt · references/linkfox-amazon-ads-auth.md (reported line 257)May include surrounding context.

md
### 4. 刷新令牌 — `/amazonAds/refreshToken`

`accessToken` 1 小时有效;过期后下游返回 HTTP 401 或错误体含 `expired` / `unauthorized` / `access token`。

**请求**(`authRecordId` 和 `profileId` 二选一):
| 参数 | 类型 | 说明 |

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · references/onboarding.md (reported line 14)May include surrounding context.

md
��后:`python scripts/onboarding.py login <phone> <code>`(workbuddy 宿主加 `--channel workbuddy`)
   - 拿到 `api_key` 后把下面三平台配置转发给用户,提示重启会话生效:
     - Windows PowerShell(永久):`setx LINKFOX_AGENT_API_KEY "<key>"`
     - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.zshrc && source ~/.zshrc`
     - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.bashrc && source ~/.bashrc`
     - 变量名 `LINKFOX_AGENT_API_KEY`(主推)或 `LINKFOXAGENT_API_KEY`(老规范)任一即可

**billing 场景**:`errcode=402` 或消息含 `积分/余额/quota/insufficient/充值/套餐到期`。
- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单,否则输出编号清单让用户选
- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`(通常 `wechat/alipay`)
- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先�

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

python
#!/usr/bin/env python3
"""
Amazon Ads Token Refresh - LinkFox Skill
Calls /amazonAds/refreshToken to refresh access token

Usage:
  python refresh_token.py '{"authRecordId": 123}'

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/manager/_common.py (reported line 7)May include surrounding context.

python
#!/usr/bin/env python3
"""
Amazon Ads Token Refresh - LinkFox Skill
Calls /amazonAds/refreshToken to refresh access token

Usage:
  python refresh_token.py '{"authRecordId": 123}'

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/manager/_common.py (reported line 131)May include surrounding context.

python
#!/usr/bin/env python3
"""
Amazon Ads Token Refresh - LinkFox Skill
Calls /amazonAds/refreshToken to refresh access token

Usage:
  python refresh_token.py '{"authRecordId": 123}'

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/manager/_common.py (reported line 135)May include surrounding context.

python
#!/usr/bin/env python3
"""
Amazon Ads Token Refresh - LinkFox Skill
Calls /amazonAds/refreshToken to refresh access token

Usage:
  python refresh_token.py '{"authRecordId": 123}'

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/report/get_report.py (reported line 173)May include surrounding context.

python
#!/usr/bin/env python3
"""
Amazon Ads Token Refresh - LinkFox Skill
Calls /amazonAds/refreshToken to refresh access token

Usage:
  python refresh_token.py '{"authRecordId": 123}'

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/report/get_report.py (reported line 394)May include surrounding context.

python
#!/usr/bin/env python3
"""
Amazon Ads Token Refresh - LinkFox Skill
Calls /amazonAds/refreshToken to refresh access token

Usage:
  python refresh_token.py '{"authRecordId": 123}'

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

On token fetch failure, the code prints the entire result object to stderr. If the gateway includes sensitive diagnostic data, token material, account identifiers, or backend error payloads, this can leak secrets into logs, consoles, CI output, or telemetry systems where stderr is captured.

Content

Scanner excerpt · scripts/manager/_common.py (reported line 132)May include surrounding context.

python
def get_access_token(profile_id: int) -> str:
    """Fetch access token for the given profileId via /amazonAds/storeTokens."""
    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)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script validates and constructs an ad-type-specific path in entity_path, but the actual API mutation call never uses that path and instead calls mutate_entity(...) without an endpoint argument. This creates a dangerous mismatch between documented behavior and actual behavior: callers may believe they are creating one SB ad subtype while the request is sent to a different default endpoint or malformed route, potentially causing unintended ad creation, failed operations, or writes to the wrong API resource.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/report/get_report.py (reported line 397)May include surrounding context.

python
print(f"❌ Failed to get access token: {tokens_result}", file=sys.stderr)
        sys.exit(1)
    access_token = tokens_result["accessToken"]
    print("✓ Access token retrieved", file=sys.stderr)

    # Step 2: 获取待轮询的 reportId —— 两种来源
    #   (a) 调用方直接传 reportId(例如上次超时但报告仍在跑)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill description is broad enough to trigger on generic Amazon advertising requests, including high-impact write operations such as bid, budget, and status changes. In an agentic environment, overly broad invocation criteria increase the chance the skill is selected when the user intended only discussion or analysis, which can lead to unnecessary account access or unintended ad mutations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill states that report retrieval exposes extracted JSON through a temporary local HTTP server on 127.0.0.1, but the top-level description does not clearly warn users that sensitive advertising data will be served over a reachable local endpoint. This creates unnecessary local data exposure risk because other local processes, browser extensions, malware, or co-tenant software on the host may access the report during the exposure window.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill persistently writes full API responses to local storage, including authorization and advertising-management data, without giving a prominent up-front warning in the descriptive sections. Persistent storage of sensitive business data and possibly token-bearing responses expands the attack surface through disk disclosure, backups, shared workspaces, and later unintended reuse.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This markdown file presents all operational instructions and examples in Chinese, which effectively forces a specific language for users. The policy allows locale constraints only when the skill offers user choice or clearly documents a justified region-specific limitation, neither of which is stated here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The primary description is written as a Chinese-only instruction set and does not indicate that the skill can respond in other languages or let the user choose a locale. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

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 · references/linkfox-amazon-ads-auth.md (reported line 305)May include surrounding context.


curl 示例

bash
export KEY=$LINKFOXAGENT_API_KEY