Back to skill

Security audit

TikTok/Instagram/YouTube Influencer Discovery

Security checks for vulnerabilities and agentic risk

Overview

This skill does influencer research as advertised, but it quietly creates a durable tracking ID and can send API credentials and campaign queries to a user-configured gateway without strong destination safeguards.

Review this skill before installing. It is coherent for influencer discovery, but only use it with a trusted HTTPS gateway and a trusted env file, and be aware it creates a persistent local install identifier that the gateway can use to correlate requests over time.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

other

Warning
Location
scripts/execute_operation.py:18
Finding

Undisclosed Persistent Cross-Skill 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 ``` The persistent value is transmitted with every operation: ```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()}) ``` ### Technical Analysis Every API operation creates or reads a stable UUID and transmits it to the selected API gateway in the `x-install-id` header. The implementation first attempts to store the identifier at `~/.scrumball_install_id`, outside the Skill directory. The source comment states that this location is intentionally used so the identifier survives reinstallation and can be shared by multiple Skills. A stable identifier may be reasonable for quota enforcement, but its persistence and cross-Skill scope exceed the minimum storage required to perform an individual influencer search. The user-facing documentation describes gateway quota behavior but does not disclose that the Skill creates a durable home-directory identifier, reuses it across installations ...[truncated 1446 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/execute_operation.py:130
Finding

API Credentials and Request Data Can Be Redirected to an Arbitrary or Plaintext 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 ``` The resulting endpoint is used without scheme enforcement or destination validation, while credentials and request data are transmitted to it: ```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")) validate_required(op.get("required_query", []), query, "query parameters") validate_required_any(op.get("required_any_query", []), query, "query parameters") validate_required(op.get("required_path", []), path_params, "path parameters") validate_required(op.get("required_body", []), body, "body fields") url = base_url.rstrip("/") + apply_path_params(op["path"], path_params) if query: q = {k: v for k, v in query.items() if v is not None ...[truncated 3498 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (25)

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The request target is derived from environment-controlled configuration via SCRUMBALL_BASE_URL and then used directly in urllib.request.urlopen. This allows the runtime to send authorization headers, body data, and the persistent x-install-id header to an attacker-controlled endpoint if the environment is manipulated, creating SSRF/data-exfiltration risk. The skill context makes this more concerning because the code is designed to handle API credentials and outbound lead-enrichment data.

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

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
3. Check `references/request-response.md` for required params and response field layout.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
3. Check `references/request-response.md` for required params and response field layout.

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 72)May include surrounding context.

md
## Tooling

Execution commands:
- List operations: `python3 scripts/execute_operation.py --env-file .env list`
- Filter by tag: `python3 scripts/execute_operation.py --env-file .env list --tag search`
- Example search: `python3 scripts/execute_operation.py --env-file .env call --operation search_tiktok_user --body '{"query":"nike","page":1,"page_size":10}'`
- Example enrich: `python3 scripts/execute_operation.py --env-file .env call --operation tiktok_db_user_info --query '{"unique_id":"nike"}'`

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 73)May include surrounding context.

md
## Tooling

Execution commands:
- List operations: `python3 scripts/execute_operation.py --env-file .env list`
- Filter by tag: `python3 scripts/execute_operation.py --env-file .env list --tag search`
- Example search: `python3 scripts/execute_operation.py --env-file .env call --operation search_tiktok_user --body '{"query":"nike","page":1,"page_size":10}'`
- Example enrich: `python3 scripts/execute_operation.py --env-file .env call --operation tiktok_db_user_info --query '{"unique_id":"nike"}'`

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 74)May include surrounding context.

md
## Tooling

Execution commands:
- List operations: `python3 scripts/execute_operation.py --env-file .env list`
- Filter by tag: `python3 scripts/execute_operation.py --env-file .env list --tag search`
- Example search: `python3 scripts/execute_operation.py --env-file .env call --operation search_tiktok_user --body '{"query":"nike","page":1,"page_size":10}'`
- Example enrich: `python3 scripts/execute_operation.py --env-file .env call --operation tiktok_db_user_info --query '{"unique_id":"nike"}'`

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 75)May include surrounding context.

md
## Tooling

Execution commands:
- List operations: `python3 scripts/execute_operation.py --env-file .env list`
- Filter by tag: `python3 scripts/execute_operation.py --env-file .env list --tag search`
- Example search: `python3 scripts/execute_operation.py --env-file .env call --operation search_tiktok_user --body '{"query":"nike","page":1,"page_size":10}'`
- Example enrich: `python3 scripts/execute_operation.py --env-file .env call --operation tiktok_db_user_info --query '{"unique_id":"nike"}'`

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`
- Filter by tag: `python3 scripts/execute_operation.py --env-file .env list --tag search`
- Example search: `python3 scripts/execute_operation.py --env-file .env call --operation search_tiktok_user --body '{"query":"nike","page":1,"page_size":10}'`
- Example enrich: `python3 scripts/execute_operation.py --env-file .env call --operation tiktok_db_user_info --query '{"unique_id":"nike"}'`

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 documents executable tooling that can read local files, load environment variables, and make outbound network requests, but it does not declare an explicit tool scope or permissions boundary. In agent environments, this can cause over-broad capability exposure and makes it harder to enforce least privilege, increasing the risk of unintended file, secret, or network access during execution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The capability matrix presents core user-facing labels in Chinese (for example, capability names across YouTube, TikTok, Instagram, and Cross-platform sections), while the rest of the document is in English. This imposes a language constraint on readers without any opt-in or explanation, which is a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation gives conflicting trust and execution semantics: earlier sections instruct direct execution with .env-loaded credentials, while the quota section claims a zero-config hosted gateway that injects keys server-side. This ambiguity can mislead operators about where secrets are used, whether requests transit third-party infrastructure, and what data leaves the local environment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
72% confidence
Finding

The skill explicitly directs the assistant to send users to an external registration and pricing site and to configure an API key for continued use. While external links are not inherently malicious, this creates an external transmission/trust pivot where users may disclose operational details or follow off-platform credential setup steps, which is more sensitive in a skill that already uses env-loaded secrets and network execution.

Content

Scanner excerpt · SKILL.md (reported line 111)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.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This JSON manifest contains natural-language summaries such as "用户信息" and similar Chinese-only labels for many operations. Because the file provides no indication that the skill is region-specific or that users can opt into this locale, it appears to impose a specific language in violation of the language/locale policy.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest describes finding influencers by keyword, expanding similar creators, enriching profiles, and building lead lists. Endpoints such as /user/brands and media/video listing with is_paid filters indicate brand-collaboration intelligence and sponsored-content analysis, which is a materially broader capability than simple discovery/enrichment.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Endpoints like /instagram/user/hashtag/engagement return top hashtag performance metrics, including engagement medians, totals, and grading. This is analytics functionality that exceeds the manifest's stated scope of search, similar-creator expansion, profile enrichment, and lead-list building.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documentation shows TikTok and YouTube endpoints for /user/brands and /user/hashtag/engagement, mirroring the broader analytics and sponsorship-analysis behavior across all supported platforms. This repeated capability indicates the skill is not limited to influencer search and enrichment as described in the manifest.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code generates a UUID and persists it across runs in the user's home directory or skill directory specifically for stable statistics/quotas, then reuses it indefinitely. This creates cross-session tracking unrelated to the stated influencer discovery functionality and increases privacy risk by enabling long-term correlation of user activity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file both stores a durable install identifier on disk and later transmits it in network headers, but there is no user-facing disclosure or consent mechanism in this code path. Hidden persistent identifiers undermine user expectations and create avoidable privacy and compliance risk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Every API request includes the x-install-id header populated from a persistent identifier, enabling backend correlation of all requests from the same installation. This extends beyond ordinary API functionality for influencer discovery and compounds the privacy impact, especially when combined with configurable outbound destinations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file contains multiple endpoint summaries in Chinese, while the document heading and table structure are in English. Because the file does not state that the skill is region-specific or provide a user language choice, it appears to impose a specific language/locale without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This file is a markdown document, so natural-language policy checks apply. The summaries and field descriptions switch between Chinese and English across endpoints, but the document does not state that the skill is Chinese-only or offer a user language choice, which can violate a language/locale policy requiring user opt-in or explicit justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The docstring/comments for the install ID behavior are written only in Chinese, which imposes a specific language in user- or maintainer-facing natural language with no opt-in or alternative. Under the language/locale policy, forcing a single language without choice can be a policy violation unless clearly justified.

Content

No source excerpt is available for this finding.