Back to skill

Security audit

Airdrop Monitor CN

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches an airdrop-monitoring tool, but its billing path can perform real charges with weak guardrails and its monitor fetches arbitrary configured URLs.

Install only if you are comfortable with a Chinese-language monitoring tool that can contact configured announcement URLs and, when SkillPay environment variables are set, can charge a user before running. Do not run verify_billing.py with production credentials unless you intend to create a real charge. Use trusted HTTPS-only source configs, avoid local/private-network URLs, pin dependencies, and keep scheduled runs separate from paid billing unless repeated charges are intentional.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
monitor.py:49
Finding

Configuration-Controlled Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: monitor.py:49-54 and monitor.py:112-126
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: High

Vulnerable Code

python
def fetch_text(url: str, timeout: int = 20) -> str:
    r = requests.get(url, timeout=timeout, headers={"User-Agent": "airdrop-monitor-cn/0.2"})
    r.raise_for_status()
    text = r.text
    text = re.sub(r"\s+", " ", text)
    return text[:15000]

The request destination is read directly from the configuration:

python
results: List[SourceResult] = []
for proj in cfg["projects"]:
    pname = proj.get("name", "unknown")
    for src in proj.get("sources", []):
        sname = f"{pname}:{src.get('name', 'source')}"
        surl = src["url"]
        try:
            text = fetch_text(surl)
        except Exception as e:
            text = f"fetch_error: {e}"

        h = digest(text)
        old_h = state["sources"].get(surl, "")
        changed = old_h != "" and old_h != h

Technical Analysis

The application accepts source URLs from a JSON configuration and passes them directly to requests.get() without validating the scheme, hostname, port, or resolved IP address. The requests library also follows HTTP redirects by default.

Consequently, any party that can create, replace, or influence the monitor configuration can make the application issue requests to destinations reachable from the host, including:

  • Loopback services such as 127.0.0.1 or localhost
  • Private network services
  • Link-local addresses and cloud metadata endpoints
  • Services exposed on nonstandard ports
  • Public endpoints that redirect to internal destinations

The checks in detect_risks() do not mitigate this issue because they run only after the network request has already occurred. They also do not inspect resolved addresses or redirect targets.

Attack Path

  1. An attacker obtains the abil ...[truncated 1346 chars]
Remediation
View remediation

Remediation Suggestions

  • Parse each URL before making a request and allow only explicitly supported schemes, preferably HTTPS.
  • Reject URLs containing embedded credentials, fragments, unexpected ports, or malformed hostnames.
  • Resolve the hostname and reject every address that is loopback, private, link-local, multicast, reserved, unspecified, or otherwise nonpublic.
  • Explicitly block known cloud metadata destinations, including link-local metadata addresses and provider-specific metadata hostnames.
  • Disable automatic redirects with allow_redirects=False, or validate the scheme, hostname, port, and resolved IP address of every redirect target before following it.
  • Consider an explicit allowlist of approved project domains when the monitored sources are known in advance.
  • Apply outbound firewall or proxy controls so the process cannot reach internal networks or metadata services.
  • Protect against DNS rebinding by validating resolved addresses and ensuring that the actual connection uses an approved address.
  • Set response-size limits while streaming the body rather than downloading the full response before truncation.

T09 · Insecure Skill Coding Practices

Warning
Location
verify_billing.py:24
Finding

Billing Self-Check Performs an Unconfirmed Production Charge

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:50-54 and verify_billing.py:24-31
Vulnerability Type: Unintended Financial Transaction
Risk Level: Medium

Vulnerable Code

The documentation describes the operation as a quick self-check:

markdown
Quick self-check:

```bash
python verify_billing.py --user-id discord_123456 --amount 0.001
text

The referenced verification utility performs an actual charge:

```python
try:
    out["balance"] = get_balance(args.user_id)
except Exception as e:
    out["balance_error"] = str(e)

try:
    out["charge"] = charge_user(args.user_id, amount=args.amount)
except Exception as e:
    out["charge_error"] = str(e)

Technical Analysis

The verification command is presented as a self-check, but verify_billing.py unconditionally calls charge_user() after checking the balance. That function sends a request to the configured production billing endpoint. If valid production credentials are present, the command may debit the specified user.

There is no confirmation prompt, explicit live-transaction flag, dry-run mode, or prominent warning that executing the documented check can create a real financial transaction. The script also attempts to create a payment link after the charge operation.

Attack Path

  1. An operator configures valid production values for SKILL_BILLING_API_KEY and SKILL_ID.
  2. The operator follows the documented “Quick self-check” instructions, reasonably expecting a non-destructive connectivity or configuration test.
  3. The script checks the supplied user's balance.
  4. The script then invokes charge_user() with the supplied amount.
  5. The billing service processes a real charge if the account and credentials are valid.
  6. Repeated execution can produce repeated charges.

Impact Assessment

The issue does not provide additional system privileges to an attacker. Its impact is financial and operatio ...[truncated 362 chars]

Remediation
View remediation

Remediation Suggestions

  • Make balance and authentication checks the default verification behavior.
  • Require an explicit flag such as --confirm-live-charge before invoking charge_user().
  • Display the user identifier, amount, endpoint environment, and a prominent live-charge warning before requesting confirmation.
  • Provide a dedicated --dry-run mode that validates configuration without submitting a transaction.
  • Use a billing sandbox or test endpoint for integration checks whenever the provider supports one.
  • Rename the documentation section from “self-check” to “live billing test” if a real charge remains part of the procedure.
  • Prevent accidental repeated execution by using an idempotency key when supported by the billing API.
  • Separate payment-link generation from billing verification so unrelated side effects require separate explicit commands.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Open-Ended Third-Party Dependency Version

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1 and SKILL.md:30
Vulnerability Type: Unpinned Dependency and Non-Reproducible Installation
Risk Level: Low

Vulnerable Code

text
requests>=2.31.0

The documented installation process resolves the dependency directly:

bash
pip install -r requirements.txt

Technical Analysis

The dependency declaration accepts any requests release newer than or equal to version 2.31.0. It does not use an exact version, a lock file, or package hashes.

This does not establish that the current dependency is malicious. However, it makes installations non-reproducible and allows future upstream releases to enter the environment without project-specific review. Security behavior can therefore change between installations, and a compromised, defective, or unexpectedly incompatible future release could be installed automatically.

The absence of hashes also means the installer does not verify artifacts against project-approved digests.

Attack Path

  1. A future dependency release or one of its transitive dependencies becomes compromised, defective, or incompatible.
  2. An operator runs the documented pip install -r requirements.txt command.
  3. Package resolution selects the newer release because it satisfies the open-ended >=2.31.0 constraint.
  4. The package is installed without comparison against a project-reviewed lock file or cryptographic hash set.
  5. The affected package executes with the privileges of the Python environment during installation or application runtime.

Impact Assessment

The potential scope is the Python environment and user account performing installation or running the application. If an accepted package release were compromised, it could access application data, billing environment variables, network resources, and files available to that account.

This is a supply-chain hardening weakness rather than evide ...[truncated 63 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin requests and all transitive dependencies to reviewed exact versions.
  • Generate and commit a lock file using a dependency-management tool appropriate for the project.
  • Record cryptographic hashes for approved distributions and install with pip's --require-hashes option.
  • Prefer trusted package indexes configured explicitly in deployment environments.
  • Update dependencies through a controlled process that includes vulnerability scanning, changelog review, and automated tests.
  • Use automated dependency-update tooling to propose reviewed upgrades rather than accepting all future releases at installation time.
  • Rebuild lock files periodically so security fixes can be adopted without sacrificing reproducibility.
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (24)

Tainted flow: 'HEADERS' from os.environ.get (line 8, 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 · billing.py (reported line 26)May include surrounding context.

python
payload = {"user_id": user_id, "skill_id": SKILL_ID}
    if amount is not None:
        payload["amount"] = amount
    resp = requests.post(
        f"{BILLING_URL}/charge",
        headers=HEADERS,
        json=payload,

Tainted flow: 'HEADERS' from os.environ.get (line 8, credential/environment) → requests.get (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 · billing.py (reported line 46)May include surrounding context.

python
def get_balance(user_id: str) -> float:
    _ensure_config()
    resp = requests.get(
        f"{BILLING_URL}/balance",
        params={"user_id": user_id},
        headers=HEADERS,

Tainted flow: 'HEADERS' from os.environ.get (line 8, 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 · billing.py (reported line 58)May include surrounding context.

python
def get_payment_link(user_id: str, amount: float = 8) -> str:
    _ensure_config()
    resp = requests.post(
        f"{BILLING_URL}/payment-link",
        headers=HEADERS,
        json={"user_id": user_id, "amount": amount},

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · README-BILLING.md (reported line 14)May include surrounding context.

python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt cp .env.example .env

edit .env with your real SKILL_BILLING_API_KEY + SKILL_ID

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · README-BILLING.md (reported line 15)May include surrounding context.

source .venv/bin/activate pip install -r requirements.txt cp .env.example .env

edit .env with your real SKILL_BILLING_API_KEY + SKILL_ID

text

## 2) Runtime env

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented functionality emphasizes announcement monitoring, but the analysis indicates billing verification may be implemented prominently enough to diverge from the stated purpose. Even if billing is described as optional, unclear separation between monitoring and payment logic can cause operators to grant broader access or run code paths they did not intend, especially where external charging actions are involved.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented functionality emphasizes announcement monitoring, but the analysis indicates billing verification may be implemented prominently enough to diverge from the stated purpose. Even if billing is described as optional, unclear separation between monitoring and payment logic can cause operators to grant broader access or run code paths they did not intend, especially where external charging actions are involved.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module performs external billing and payment-link generation, which expands the skill's capabilities beyond pure monitoring and introduces privacy and trust risks. In this skill context, the description mentions optional charging, so this is not overtly malicious, but undisclosed or weakly governed monetization logic can still surprise users and trigger unwanted charges or data sharing.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This script performs live financial operations by calling both charge_user and get_payment_link, despite the skill being presented as an airdrop-monitoring assistant. That mismatch is dangerous because operators or reviewers may run it as a harmless verification utility, but it can trigger real account charges and payment flows unrelated to the advertised purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code uses billing credentials from environment variables and executes sensitive financial actions that are not necessary for the core monitoring workflow described by the skill. In the context of an airdrop-monitoring assistant, unrelated access to billing APIs increases the risk of hidden monetization, misuse of credentials, and unauthorized charges if the script is run in a real environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file includes prescribed UX text for insufficient balance entirely in Chinese, but nowhere indicates that the skill is China-specific or that users can choose their preferred language. This can violate language/locale policy because it implicitly forces a specific language on users without opt-in.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description and title present the skill as Chinese-only (e.g. '空投任务与公告监控助手' and 'Airdrop Monitor CN (实战版)') with no indication that users may choose another language or locale. This can violate language/locale policy when a skill imposes a specific language without opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The payment error message is hard-coded in Chinese, and the module title also indicates a CN-specific variant, but the CLI and usage text do not disclose that the skill is Chinese-only or provide any language opt-in. This creates a locale/language policy issue because users may receive forced language output without prior choice.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes a local/web monitoring assistant for airdrop announcements, deadline clues, risk keywords, and action lists. Reading billing credentials and skill identifiers from environment variables introduces a payment/account integration capability that is not part of the core monitoring purpose as stated in the description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The charge operation transmits a user identifier and skill identifier to an external billing service without any visible notice, consent, or minimization in this module. Even if legitimate, this creates privacy risk and can violate user expectations because billing-related identifiers are shared off-platform as part of normal execution.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

This request externally transmits user_id, skill_id, and potentially amount to a billing endpoint. External transmission is expected for payment processing, but it is still security-relevant because it involves identity-linked billing metadata leaving the local skill environment.

Content

Scanner excerpt · billing.py (reported line 26)May include surrounding context.

python
payload = {"user_id": user_id, "skill_id": SKILL_ID}
    if amount is not None:
        payload["amount"] = amount
    resp = requests.post(
        f"{BILLING_URL}/charge",
        headers=HEADERS,
        json=payload,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The balance lookup sends the user's identifier to an external service, which is a privacy-relevant data transfer even if no charge occurs. In a monitoring assistant, silent external lookup of user-linked billing status is more sensitive because it is ancillary to the core task and may not be expected by users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Generating a payment link sends user billing data to a third-party service without any visible user-facing explanation in the code path. This can expose user identifiers and transaction context to an external processor in a way that is not clearly tied to the monitoring function unless the user explicitly initiated payment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

The payment-link request sends user_id and amount to an external billing service, which constitutes a meaningful outbound data transfer. In context, this is plausibly legitimate monetization, but it remains a privacy and trust concern if triggered without explicit user awareness.

Content

Scanner excerpt · billing.py (reported line 58)May include surrounding context.

python
def get_payment_link(user_id: str, amount: float = 8) -> str:
    _ensure_config()
    resp = requests.post(
        f"{BILLING_URL}/payment-link",
        headers=HEADERS,
        json={"user_id": user_id, "amount": amount},

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code emits user-facing risk messages, action items, exceptions, and markdown report content entirely in Chinese. Because the file does not provide user opt-in, language selection, or a documented region-specific justification, it violates the language/locale policy for natural-language behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script is labeled as a 'Quick billing integration check,' but it can perform an actual charge with no strong warning, dry-run default, or confirmation step. A user may reasonably execute it for diagnostics and unknowingly charge an account, making the behavior unsafe even if the amount is small.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
91% confidence
Finding

The dependency is specified as requests>=2.31.0, which allows resolution to many future versions and does not guarantee a reproducible or reviewed install set. In a monitoring skill that fetches remote content, this weakens supply-chain control and can result in unexpected vulnerable or behavior-changing versions being installed.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
83% confidence
Finding

requests has multiple historical advisories, and because the manifest does not pin an exact version, there is no way to verify at review time whether deployments will install a fixed or affected release. For a skill that monitors external pages and may process attacker-controlled URLs or redirects, uncertainty around the installed HTTP client version increases exposure to known client-side request handling flaws.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.