Back to skill

Security audit

Influencer Campaign Monitoring (TikTok/IG/YouTube)

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its campaign-monitoring purpose, but it quietly creates a persistent tracking ID and can send campaign data and credentials to configurable remote endpoints.

Review this skill before installing. Only use it if you are comfortable sending campaign identifiers, creator/video identifiers, task data, and a stable install ID to the configured gateway. Use an explicit trusted HTTPS .env file, avoid running it from untrusted directories, and consider deleting ~/.scrumball_install_id if you do not want cross-session correlation.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:94
Finding

Mandatory Vendor Promotion in Assistant Responses

Content
View full analysis
Free quota exhausted. Register and get your own API key at **https://data.scdata.cc/pricing**, then set the environment variable `SCRUMBALL_API_KEY` to your key (in your host/agent environment or a local `.env`). You can then continue with your own quota. - The 429 response body usually includes `apply_url` and `env_var` fields you can quote directly. ``` ### Technical Analysis The Skill uses mandatory instructions to control assistant output when a quota-related response occurs. It requires the assistant to present a fixed commercial registration and pricing URL rather than merely reporting the operational error. Although explaining a quota failure is relevant to API operation, forcing promotional language and an external commercial link exceeds the minimum behavior necessary to communicate an HTTP 429 response. The instruction also encourages quoting remotely supplied `apply_url` content, which may allow gateway-controlled response data to influence links shown to users. ### Attack Path 1. The agent loads the Skill instructions. 2. The agent invokes an operation through the hosted gateway. 3. The gateway returns HTTP 429, `code=429`, or text containing `quota_exceeded`. 4. The Skill instruction requires the assistant to insert the vendor’s registration and pricing message into its response. 5. The user is redirected to the vend ...[truncated 629 chars]
Remediation
View remediation

other

Warning
Location
scripts/execute_operation.py:18
Finding

Undisclosed Persistent Cross-Installation Tracking Identifier

Content
View full analysis
str: """匿名安装 ID(IP 会随 WorkBuddy 出口变,用它做稳定统计/限额单位)。 优先写用户主目录(活过重装、多 skill 共用),退回 skill 目录;用户手动删才重置。""" import uuid paths = [Path.home() / ".scrumball_install_id", SKILL_ROOT / ".install_id"] for p in paths: try: if p.exists(): v = p.read_text(encoding="utf-8").strip() if v: return v except Exception: pass new_id = uuid.uuid4().hex for p in paths: try: p.write_text(new_id, encoding="utf-8") return new_id except Exception: continue return new_id ``` ```python req_headers = { "authorization": auth_header_value(api_key), "accept": "application/json", "x-install-id": _install_id(), } req_headers.update(op.get("default_headers", {})) req_headers.update({k: str(v) for k, v in headers.items()}) data = None if body: req_headers["content-type"] = "application/json" data = json.dumps(body).encode("utf-8") req = urllib.request.Request(url=url, method=op["method"], headers=req_headers, data=data) try: with urllib.request.urlopen(req, timeout=timeout) as resp: ``` ### Technical Analysis The runner creates a stable UUID and attempts to store it in the user’s home directory as `.scrumball_install_id`. The code comment explicitly states that the identifier is intended to survive reinstallation, be shared across multiple Skills, and remain stable until manually deleted. Every API operation transmits this identifier in the `x-install-id` header. A persistent cross-installation identifier is not technically required to create monitoring tasks, retrieve metrics, or download tracked assets. It therefore exceeds the minimum loc ...[truncated 1496 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/execute_operation.py:130
Finding

API Credentials May Be Sent to an Unencrypted or Attacker-Controlled Endpoint

Content
View full analysis
Path | None: candidates = [] if env_file_arg: candidates.append(Path(env_file_arg).expanduser()) elif os.getenv("SCRUMBALL_ENV_FILE"): candidates.append(Path(os.getenv("SCRUMBALL_ENV_FILE", "")).expanduser()) else: candidates.append(Path.cwd() / ".env") candidates.append(SKILL_ROOT / ".env") for p in candidates: if p.exists() and p.is_file(): load_env_file(p) return p return None ``` ```python def call_operation(op: Dict[str, Any], query: Dict[str, Any], body: Dict[str, Any], headers: Dict[str, Any], path_params: Dict[str, Any]) -> Dict[str, Any]: # 默认走托管网关(agent.scdata.cc):调用方零配置、无需自带 key。 # 网关服务端持有 Firebox key 并注入,故 SCRUMBALL_API_KEY 可留空。 base_url = os.getenv("SCRUMBALL_BASE_URL", "").strip() or "https://agent.scdata.cc" api_key = os.getenv("SCRUMBALL_API_KEY", "").strip() timeout = int(os.getenv("SCRUMBALL_TIMEOUT_SECONDS", "30")) ``` ```python req_headers = { "authorization": auth_header_value(api_key), "accept": "application/json", "x-install-id": _install_id(), } req_headers.update(op.get("default_headers", {})) req_headers.update({k: str(v) for k, v in headers.items()}) data = None if body: req_headers["content-type"] = "application/json" data = json.dumps(body).encode("utf-8") req = urllib.request.Request(url=url, method=op["method"], headers=req_headers, data=data) try: with urllib.request.urlopen(req, timeout=timeout) as resp: ``` ### Technical Analysis `SCRUMBALL_BASE_URL` is accepted without validating its scheme or destination. Consequently, the configured endpoint can use plaintext HTTP or point to an unintended host. The s ...[truncated 2364 chars]
Remediation
View remediation
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (25)

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The script allows the outbound destination to be controlled by environment variable via SCRUMBALL_BASE_URL and then sends request headers, body data, and the persistent x-install-id to that host. In a skill context, this can exfiltrate campaign data or credentials to an attacker-controlled endpoint if the environment is tampered with or the skill is run in an untrusted setup.

Content

Scanner excerpt · scripts/execute_operation.py (reported line 180)May include surrounding context.

python
req = urllib.request.Request(url=url, method=op["method"], headers=req_headers, data=data)
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            raw = resp.read().decode("utf-8")
            try:
                payload = json.loads(raw) if raw else None

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The documented purpose is campaign monitoring, but the skill behavior indicates broader capabilities: generic remote request execution, environment/config handling, and persistence of a stable installation identifier. This mismatch can mislead users and reviewers about what data is accessed or transmitted, making covert tracking, quota correlation, or unintended exfiltration harder to detect.

Content

No source excerpt is available for this finding.

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

md
## Tooling

Execution commands:
- List operations: `python3 scripts/execute_operation.py --env-file .env list`
- Create task: `python3 scripts/execute_operation.py --env-file .env call --operation create_monitor_task --body '{"platform":"tiktok","video_id":"123456"}'`
- List tasks: `python3 scripts/execute_operation.py --env-file .env call --operation list_monitor_tasks --query '{"page":1,"page_size":20}'`

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

md
## Tooling

Execution commands:
- List operations: `python3 scripts/execute_operation.py --env-file .env list`
- Create task: `python3 scripts/execute_operation.py --env-file .env call --operation create_monitor_task --body '{"platform":"tiktok","video_id":"123456"}'`
- List tasks: `python3 scripts/execute_operation.py --env-file .env call --operation list_monitor_tasks --query '{"page":1,"page_size":20}'`

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

md
## Tooling

Execution commands:
- List operations: `python3 scripts/execute_operation.py --env-file .env list`
- Create task: `python3 scripts/execute_operation.py --env-file .env call --operation create_monitor_task --body '{"platform":"tiktok","video_id":"123456"}'`
- List tasks: `python3 scripts/execute_operation.py --env-file .env call --operation list_monitor_tasks --query '{"page":1,"page_size":20}'`

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

python
## Tooling

Execution commands:
- List operations: `python3 scripts/execute_operation.py --env-file .env list`
- Create task: `python3 scripts/execute_operation.py --env-file .env call --operation create_monitor_task --body '{"platform":"tiktok","video_id":"123456"}'`
- List tasks: `python3 scripts/execute_operation.py --env-file .env call --operation list_monitor_tasks --query '{"page":1,"page_size":20}'`

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

python
elif os.getenv("SCRUMBALL_ENV_FILE"):
        candidates.append(Path(os.getenv("SCRUMBALL_ENV_FILE", "")).expanduser())
    else:
        candidates.append(Path.cwd() / ".env")
        candidates.append(SKILL_ROOT / ".env")

    for p in candidates:

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

python
elif os.getenv("SCRUMBALL_ENV_FILE"):
        candidates.append(Path(os.getenv("SCRUMBALL_ENV_FILE", "")).expanduser())
    else:
        candidates.append(Path.cwd() / ".env")
        candidates.append(SKILL_ROOT / ".env")

    for p in candidates:

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

python
elif os.getenv("SCRUMBALL_ENV_FILE"):
        candidates.append(Path(os.getenv("SCRUMBALL_ENV_FILE", "")).expanduser())
    else:
        candidates.append(Path.cwd() / ".env")
        candidates.append(SKILL_ROOT / ".env")

    for p in candidates:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill declares operational capabilities that imply network, file, and environment access, but it does not define an explicit tool scope such as permissions or allowed-tools. This increases the risk that an agent runtime grants broader access than users expect, especially since the skill references local .env loading and outbound API calls.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The capability tables use Chinese field labels and operation names alongside English headings, which imposes a mixed-language experience without user opt-in or justification. This can violate a language/locale policy when users expect a consistent language unless the skill is explicitly documented as region-specific or bilingual by choice.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

The skill instructs the assistant to direct users to an external registration site and describes a hosted gateway that injects API keys server-side. This creates an external data transmission and trust boundary that is not central to the monitoring task itself, and could expose usage metadata or steer users into sending credentials to a third-party service.

Content

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

md
- **Free tier**: a limited number of calls per day, zero-config (no key required — the skill defaults to a hosted gateway that injects the key server-side).
- **When any operation returns HTTP 429, or the response body has `code=429` / contains `quota_exceeded`, you (the assistant) MUST immediately and clearly tell the user** (do not silently retry, do not treat it as a generic error):

  > Free quota exhausted. Register and get your own API key at **https://data.scdata.cc/pricing**, then set the environment variable `SCRUMBALL_API_KEY` to your key (in your host/agent environment or a local `.env`). You can then continue with your own quota.

- The 429 response body usually includes `apply_url` and `env_var` fields you can quote directly.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The trigger phrases are generic campaign and monitoring terms that can match ordinary user requests without clearly signaling that this specific skill should be invoked. Over-broad activation can cause the agent to route unrelated requests into a capability that may fetch external campaign data or perform monitoring actions the user did not explicitly request, increasing the risk of unintended data access or task execution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file contains user-facing natural language such as summaries and tags in Chinese (e.g. '任务-视频下载', '用户监控指标', '视频监测') while the surrounding document headings and structure are in English. That creates a language/locale policy issue because the file effectively forces a specific language for key descriptions without any opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This JSON manifest contains natural-language summaries and tags such as "任务-视频下载", "用户监控指标", and "视频监测" entirely in Chinese. Because the file provides no opt-in, alternate locale, or documentation that the skill is intentionally region-specific, it appears to force a specific language/locale in violation of the language-choice policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

SQP-3 applies to all file types and includes language/locale policy violations. The file's summaries and field descriptions are presented in Chinese throughout, with no indication that users may choose another language or that the locale restriction is intentional and justified.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The _install_id function creates a UUID and persists it in the user's home directory or skill directory, creating a stable cross-run identifier unrelated to the core monitoring functionality. That enables long-term tracking of a user or installation across executions and across skills without meaningful notice or consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code persists a stable install identifier and later transmits it over the network in the x-install-id header without any user-facing disclosure. Even if not a traditional secret, it is a trackable identifier that can be used to correlate user activity over time.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The call_operation function constructs and sends HTTP requests to a remote base URL, including query/body data, authorization material, and a persistent install ID. Although this is core functionality, the code does not provide any visible disclosure via prompt, logging, or CLI notice about what is being transmitted or that a managed gateway may receive the data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

This is a markdown file, so SQP-2 applies to missing user-facing warnings in the skill description. The endpoint creates a monitoring task and returns monitoring metadata, but the description does not warn that this action starts persistent monitoring activity that could affect privacy expectations or system-side data collection.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

For markdown files, SQP-2 requires warnings when described behaviors could affect user data, privacy, or system integrity. This endpoint performs an active refresh operation, but the documentation presents it as a normal call without disclosing that it triggers new monitoring data collection/update activity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Stopping a monitoring task is a state-changing operation with potential operational impact, but the markdown description contains no explicit warning about that effect. Under SQP-2 for markdown files, users should be informed when an action can materially alter ongoing data collection or task behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

Natural-language content in the file includes Chinese-only comments describing behavior, and there is no indication that the skill is intentionally region-specific or that users/developers may choose their preferred language. This can violate language/locale policy when a skill imposes a language without opt-in or justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The inline comments state that calls default to a managed gateway and that SCRUMBALL_API_KEY may be left empty, implying zero-config operation. However, run_doctor marks configuration as not ok unless both base_url and api_key are present, which contradicts that documented behavior and can mislead operators about the skill's actual requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The file describes default managed-gateway behavior using Chinese-only natural-language comments, with no explanation that the skill is limited to a Chinese-language audience. This is a locale-policy concern because important operational behavior is expressed in a single language without opt-in or a documented regional justification.

Content

No source excerpt is available for this finding.