Back to skill

Security audit

sn-search-social-en

Security checks for vulnerabilities and agentic risk

Overview

This is a real social-search skill, but it needs review because its credential handling can expose API keys in command lines or error output.

Review before installing. Use a virtual environment, prefer environment variables over command-line API keys, restrict provider keys to the minimum APIs and quotas, avoid logging stdout from failed runs until errors are sanitized, and pin dependencies before production use.

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

Warning
Location
scripts/youtube_search.py:18
Finding

YouTube API key disclosure through HTTP error output

Content
View full analysis

Vulnerability Details

File Location: scripts/youtube_search.py, lines 18–29 and 58–63
Vulnerability Type: Sensitive credential exposure through exception serialization
Risk Level: Medium

Vulnerable Code

python
params = {
    "part": "snippet",
    "q": query,
    "type": "video",
    "maxResults": min(limit, 50),
    "order": order,
    "key": api_key,
}

with get_client() as client:
    resp = client.get(API_URL, params=params)
    resp.raise_for_status()
    data = resp.json()
python
try:
    items = search(args.query, args.limit, api_key, args.order)
    print_json(make_result(True, args.query, "youtube", items))
except Exception as e:
    print_json(make_result(False, args.query, "youtube", [], str(e)))
    sys.exit(1)

Technical Analysis

The YouTube API key is placed in the request query string as key. When raise_for_status() raises an httpx.HTTPStatusError, its string representation can contain the complete request URL. The broad exception handler then serializes str(e) directly into the program's JSON output.

Consequently, an HTTP failure may place the API key in standard output. Although sending the key to Google's documented HTTPS API is required for the declared search functionality, reproducing that key in application output is not required and exceeds minimum credential exposure.

Attack Path

  1. A user supplies a valid YouTube API key through YOUTUBE_API_KEY or --api-key.
  2. The script sends a search request with the key in the URL query string.
  3. Google or an intermediary returns an HTTP error, such as a quota, authorization, or malformed-request response.
  4. resp.raise_for_status() raises an exception associated with the complete request URL.
  5. The broad exception handler converts the exception to a string without redaction.
  6. The resulting JSON error is written to stdout and may be retained by agent transcripts, ...[truncated 460 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not return raw exception strings to users or agent output.
  • Catch httpx.HTTPStatusError separately and emit only a sanitized status code and generic message.
  • Remove or redact sensitive query parameters before logging request URLs.
  • Use a centralized error-sanitization function that replaces values for parameters such as key, token, and authorization.
  • Restrict the Google API key to the YouTube Data API, enforce applicable source restrictions, and configure quota alerts.
  • Rotate any key that may already have appeared in logs.

Example:

python
except httpx.HTTPStatusError as exc:
    error = f"YouTube API request failed with HTTP {exc.response.status_code}"
    print_json(make_result(False, args.query, "youtube", [], error))
    sys.exit(1)
except Exception:
    print_json(make_result(False, args.query, "youtube", [], "YouTube search failed"))
    sys.exit(1)

T09 · Insecure Skill Coding Practices

Note
Location
scripts/twitter_search.py:67
Finding

API credentials accepted through command-line arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/twitter_search.py, lines 67–70; scripts/youtube_search.py, lines 51–57; SKILL.md, lines 63–67 and 80
Vulnerability Type: Exposure of secrets through process arguments and shell history
Risk Level: Low

Vulnerable Code

python
parser = build_parser("搜索 Twitter/X 推文")
parser.add_argument("--token", help="TikHub Token(也可通过 TIKHUB_TOKEN 环境变量设置)")
args = parser.parse_args()

token = get_key("TIKHUB_TOKEN", args.token)
python
parser = build_parser("搜索 YouTube 视频")
parser.add_argument("--api-key", help="YouTube API Key(也可通过 YOUTUBE_API_KEY 环境变量设置)")
parser.add_argument("--order", default="relevance",
                    choices=["relevance", "date", "viewCount", "rating"],
                    help="排序方式(默认 relevance)")
args = parser.parse_args()

api_key = get_key("YOUTUBE_API_KEY", args.api_key)

The documentation also demonstrates supplying a TikHub token directly:

bash
python3 scripts/twitter_search.py "LLM" --token your_tikhub_token --limit 5

Technical Analysis

Command-line arguments are not an appropriate default transport for long-lived credentials. Depending on the operating system and execution environment, process arguments may be visible through process-inspection interfaces, monitoring agents, job metadata, audit logs, terminal history, or wrapper-script diagnostics.

The shared get_key() function gives command-line values precedence over environment variables, and the documentation explicitly advertises the CLI credential path. Reading only the dedicated environment variable would provide the required functionality with less incidental exposure.

Attack Path

  1. A user follows the documented command format and supplies a real token or API key with --token or --api-key.
  2. The shell may retain the complete command in its history.
  3. While the request is running, the complete argument vector m ...[truncated 771 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove or deprecate --token and --api-key.
  • Read credentials only from TIKHUB_TOKEN and YOUTUBE_API_KEY, or from a credential file with restrictive filesystem permissions.
  • Update the documentation so no example places a real secret in a command line.
  • If interactive entry is required, use getpass.getpass() so the credential is not echoed or stored in shell history.
  • Ensure wrapper systems do not print credential-bearing environment variables.
  • Rotate credentials that were previously used in command lines retained by shared logs or history files.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unbounded and non-hash-verified third-party dependency

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, line 1
Vulnerability Type: Non-reproducible dependency resolution and insufficient supply-chain integrity controls
Risk Level: Low

Vulnerable Code

text
httpx>=0.27

Technical Analysis

The dependency declaration permits any future httpx release at or above version 0.27 and does not specify an artifact hash. A fresh installation can therefore resolve to code that was not present when the Skill was reviewed.

This is not evidence that the current httpx package is malicious. The weakness is that dependency behavior and integrity are not reproducible: a compromised upstream release, account takeover, malicious distribution artifact, or incompatible future version could be selected automatically.

Attack Path

  1. A user follows the documented instruction to run python3 -m pip install -r requirements.txt.
  2. The package resolver queries the configured package index.
  3. It selects any available httpx release satisfying >=0.27, including future releases that were not audited with this Skill.
  4. If the selected package or its transitive dependencies are compromised, their installation or imported runtime code executes in the user's Python environment.
  5. That code obtains the same operating-system permissions as the user running the Skill.

Impact Assessment

Successful exploitation depends on an upstream package, package-index account, artifact, configured mirror, or dependency being compromised. If that occurs, malicious dependency code could execute with the invoking user's privileges and potentially access files, environment variables, network resources, and API credentials available to that process. No current dependency compromise was established during this audit.

Remediation
View remediation

Remediation Suggestions

  • Pin httpx to an exact version that has been tested and reviewed.
  • Generate a lock file that also fixes all transitive dependency versions.
  • Use hash verification, such as pip's --require-hashes, with trusted artifact hashes.
  • Apply dependency updates through a controlled review and testing process.
  • Use a trusted package index and monitor dependencies for published security advisories.
  • Install the Skill in an isolated virtual environment with only the permissions required for social-platform search.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

根据提供的代码片段,实际行为是一个单一平台的 Reddit 搜索脚本,不包含任何针对 Twitter/X 或 YouTube 的请求、API 调用、解析逻辑或结果构造。因此,声明中的“搜索英文社交平台,包括 Reddit、Twitter/X 和 YouTube”与该代码片段的实际功能范围不一致。虽然代码确实符合其中的 Reddit 部分,但就该片段而言,声明描述了更广的平台能力,属于描述与实际行为不匹配。未发现额外的未声明高风险能力;问题在于声明范围明显大于代码实际实现范围。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

声明描述的是一个覆盖多个英文社交平台的搜索技能,包含 Reddit、Twitter/X 和 YouTube。但提供的代码块仅调用 TikHub 的 Twitter/X 搜索时间线接口,解析推文内容并输出 Twitter 结果,没有任何 Reddit 或 YouTube 相关逻辑、端点或结果处理。因此,代码行为与声明的整体能力范围不一致。虽然已实现的 Twitter/X 部分与声明部分重合,但从该代码块本身看,声明明显比实际行为更宽,属于描述与实际功能不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

代码的主要功能是 YouTube 视频搜索,这与声明中“搜索英文社交平台,包括 Reddit、Twitter/X 和 YouTube”不一致。当前代码没有任何 Reddit 或 Twitter/X 的 API 调用、解析逻辑或结果处理,因此实际能力明显比声明更窄。虽然 YouTube 部分与声明的一部分相符,但就该代码块本身而言,描述夸大了支持的平台范围,属于描述与行为不匹配。

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
95% confidence
Finding

The description repeatedly states that the skill is for searching English social platforms, including in the skill name and usage text. This is a natural-language locale restriction, but the document does not offer user opt-in or explain why English-only behavior is required.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This file contains natural-language docstrings and dependency error text exclusively in Chinese, which imposes a specific language on users without opt-in. The policy explicitly disallows forcing a language or locale unless the skill offers a choice or documents a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code performs an HTTP request to a third-party API and transmits the user's search query in request parameters while authenticating with a TikHub bearer token. Although the function names and comments indicate search behavior, there is no user-facing print/log message, confirmation, or warning in this file that the query and token are being sent to an external service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring presents the skill description only in Chinese, which can violate language/locale policy when no user opt-in or justification is provided. Similar Chinese-only user-facing strings appear throughout the CLI, indicating the skill forces a specific language experience rather than offering a choice.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified as httpx>=0.27, which allows any future version to be installed and makes builds non-reproducible. This can introduce unexpected vulnerable or breaking releases through normal dependency resolution, especially for a network-facing library used to access external social platforms.

Content

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

text
httpx>=0.27

Unverifiable Dependency: httpx has 2 known advisory(ies) (CVE-2021-41945 (Improper Input Validation in httpx); CVE-2021-41945 (Encode OSS httpx <=1.0.0.beta0 is affected by improper input validation in `http)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding

Because the manifest does not pin the httpx version, it is not possible to verify whether the installed release is affected by known advisories. In a skill that performs outbound HTTP requests to third-party social services, using an unverified version of a core HTTP client increases supply-chain and runtime risk if dependency resolution selects an affected release.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The header explicitly sets Accept-Language to en-US,en;q=0.9, which imposes a language/locale preference regardless of user preference. Under the policy, forcing a specific language without opt-in is a natural-language policy violation unless clearly justified or user-selectable.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code performs an external HTTP request to Reddit and includes the user-provided search query in request parameters. Although network access is the core purpose of a search skill, this file contains no visible confirmation prompt, print/log disclosure, or warning that user input will be transmitted to a third-party service.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The manifest describes a skill for searching English social platforms, but this helper library includes generic credential-loading behavior from command-line arguments and environment variables. While this may support some providers, credential access is not justified by the stated purpose in this file itself and expands capability beyond plain search/result formatting utilities.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The file's natural-language descriptions are written entirely in Chinese, including the top-level module docstring, without indicating that language is optional or that the skill is region-specific. Under the policy, forcing a specific language without user opt-in can be a locale/language policy issue.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.