Back to skill

Security audit

jike-data-service

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its marketing-data purpose, but it needs review because it can expose API keys and can change remote keyword monitoring without confirmation.

Install only if you trust the API endpoint and the account whose API key you will use. Prefer RY_DATA_SECRET_KEY over storing secrets in config.json, avoid changing RY_DATA_BASE_URL unless it is a trusted HTTPS origin, do not run the check command where transcripts or logs may expose key fragments, and require explicit user approval before using keywords add or keywords delete.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ry-data.py:62
Finding

API Key Can Be Transmitted to an Arbitrary Configured Endpoint

Content
View full analysis
str: url = os.environ.get("RY_DATA_BASE_URL", "").strip() if not url: cfg = load_config() url = (cfg.get("base_url") or "").strip() return url or DEFAULT_BASE_URL ``` ```python def api_request(method: str, path: str, body=None, query: dict | None = None) -> dict: """Send HTTP request to API. Returns parsed JSON response.""" base = get_base_url() url = f"{base}{path}" if query: url += "?" + urllib.parse.urlencode({k: v for k, v in query.items() if v is not None}) headers = { "Content-Type": "application/json", "Accept": "application/json", } secret_key = get_secret_key() if secret_key: headers["X-API-Key"] = secret_key data = json.dumps(body).encode("utf-8") if body else None req = urllib.request.Request(url, data=data, headers=headers, method=method) try: with urllib.request.urlopen(req, timeout=30) as resp: result = json.loads(resp.read().decode("utf-8")) ``` ### Technical Analysis The API base URL can be overridden through either the `RY_DATA_BASE_URL` environment variable or the `base_url` field in `scripts/config.json`. The value is used without validating its scheme, hostname, port, or ownership. Every API request then automatically attaches the credential from `RY_DATA_SECRET_KEY` or `config.json` as the `X-API-Key` header. Consequently, the credential is not restricted to the declared service at `https://ry-api.dso100.com`. It can be sent to any HTTP or HTTPS server selected through configuration. Allowing a configurable service endpoint can be legitimate, but forwarding the production credential to an unrestricted destination exceeds the minimum privileges required for the declared functionality. Plain H ...[truncated 1216 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ry-data.py:152
Finding

The Check Command Exposes API-Key Material in Console Output

Content
View full analysis
12 else f"Key: {key}") else: print(f"Key: 未配置 (set secret_key in config.json or RY_DATA_SECRET_KEY env)") ``` ### Technical Analysis The `check` command prints credential material to standard output. Keys of 12 characters or fewer are printed in full. Longer keys reveal the first eight and final four characters. Secrets should not be included in normal diagnostic output. Such output may be captured by Agent transcripts, CI/CD logs, terminal recording, support bundles, shell wrappers, or centralized logging systems. Partial secret disclosure is unnecessary and can assist credential identification or reduce the unknown search space; full disclosure of short keys directly compromises the credential. ### Attack Path 1. A valid key is configured through `RY_DATA_SECRET_KEY` or `scripts/config.json`. 2. A user, Agent, diagnostic process, or CI job invokes `python3 scripts/ry-data.py check`. 3. The script writes all or part of the key to standard output. 4. The output is retained in a transcript, build log, terminal capture, or monitoring system. 5. A person with access to that output recovers a short key completely or obtains identifying fragments of a longer key. 6. A fully recovered key can be reused against the API. ### Impact Assessment For keys of 12 characters or fewer, the impact is complete credential disclosure and unauthorized use of all remote API permissions assigned to that key. For longer keys, the immediate disclosure is partial, but the exposed prefix and suffix may still aid secret correlation, validation, social engineer ...[truncated 208 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/ry-data.py:79
Finding

Documented Maximum Page Size Is Not Enforced

Content
View full analysis
int: cfg = load_config() return cfg.get("page_size", 20) ``` Representative use in list commands: ```python body["page_size"] = args.page_size or get_page_size() ``` The same unvalidated assignment is used by account, video, keyword, keyword-video, hot-video, and hashtag searches. ### Technical Analysis The configuration defines `max_page_size` as 100, and the documentation states that list requests have a maximum size of 100. The implementation never reads or enforces `max_page_size`. The `--page-size` argument accepts any integer, including negative values and extremely large values, and the configured default is likewise not validated. This permits the client to submit requests outside the declared operational limit. Whether an oversized query causes substantial resource consumption depends on server-side validation, which is not visible in this repository. Nevertheless, client-side enforcement is important because the Skill explicitly states that Elasticsearch cannot tolerate very large one-time queries. ### Attack Path 1. A user or Agent invokes a list command with an excessive value, for example: ```bash python3 scripts/ry-data.py videos search --page-size 100000000 ``` 2. `argparse` accepts the value because only integer conversion is applied. 3. The command places the value into the JSON request body without clamping or rejection. 4. The API receives the oversized request. 5. If server-side validation is absent or incomplete, the request may trigger excessive query processing, memory consumption, large responses, timeouts, or service degradatio ...[truncated 589 chars]
Remediation
View remediation
int: cfg = load_config() maximum = int(cfg.get("max_page_size", 100)) selected = int(value if value is not None else cfg.get("page_size", 20)) if selected < 1 or selected > maximum: raise ValueError(f"page_size must be between 1 and {maximum}") return selected ``` 2. Replace every `args.page_size or get_page_size()` assignment with the validated helper. 3. Validate that `max_page_size` itself is positive and does not exceed the service's hard limit of 100. 4. Validate page numbers and other resource-sensitive parameters such as hashtag `size` and trend `days`. 5. Retain server-side limits as the authoritative defense; client-side checks should supplement rather than replace API validation. 6. Add boundary tests for zero, negative, 100, 101, and extremely large values. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

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

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The request target is derived from RY_DATA_BASE_URL/config and is sent directly to urllib without any allowlist or scheme/host validation. This enables SSRF-like behavior and credential disclosure because the script also attaches the X-API-Key header to whatever host is configured, so a malicious or tampered environment/config can exfiltrate the API key and cause requests to arbitrary internal or external services.

Content

Scanner excerpt · scripts/ry-data.py (reported line 109)May include surrounding context.

python
req = urllib.request.Request(url, data=data, headers=headers, method=method)

    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            result = json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        err_body = e.read().decode("utf-8", errors="replace")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes a local Python script, reads configuration files, consumes environment secrets, and calls a remote API, but it does not declare any explicit tool scope such as allowed-tools or permissions. This creates an authorization gap: a host agent may grant broader file, environment, or network access than reviewers and users expect, increasing the risk of unintended secret exposure or overprivileged execution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instruction '说中文' requires all replies to be in Chinese as a fixed policy. This is a natural-language locale restriction, and the file does not provide any user opt-in or alternative language choice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file documents a delete action for keywords, which can remove configured monitoring data, but it provides no warning that the action is destructive or potentially irreversible. Under the markdown criteria for missing user warnings, descriptions should disclose behaviors that may affect user data or system state.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The entire workflow guide is written in Chinese and does not indicate that users may choose another language or locale. Under the policy, forcing a specific language without opt-in is a natural-language policy concern unless the regional constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill metadata describes analytical/search capabilities, but the script also exposes keyword add/delete operations that modify remote state. In an agent setting, this is a scope-expansion risk: users or orchestrators may invoke the skill assuming read-only behavior, leading to unintended data changes on the backend.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The delete command performs a destructive remote DELETE immediately once --word is supplied, with no confirmation, dry-run, or undo guidance. In interactive or agent-driven use, this increases the chance of accidental or prompt-induced deletion of managed keywords, especially since the skill otherwise appears primarily informational.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The entire skill reference forces a single language presentation in Chinese, and the file does not indicate that this is a region-specific tool or provide any user language choice. Per the policy rule, fixed language constraints should either be justified or presented as an opt-in choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

User-facing docstrings, help descriptions, status messages, and CLI text are consistently presented in Chinese, and the file does not indicate that language selection is optional or region-specific. This can violate a language/locale policy when a skill forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.