T09 · Insecure Skill Coding Practices
- Location
scripts/xhs_search.py:10- Finding
OS Command Injection in Xiaohongshu Search
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill needs review because it asks users to store raw social-media login cookies and includes search scripts where crafted search text can run local commands.
Install only after reviewing the scripts and removing or fixing the shell=True command construction. Do not place real platform cookies in references/platform_cookies.json unless you fully trust the package and accept the account-session risk; prefer anonymous search or official scoped authentication. The bundled cookie file currently contains empty placeholders, but following the setup instructions would create sensitive local secrets.
scripts/xhs_search.py:10OS Command Injection in Xiaohongshu Search
scripts/youtube_search.py:10OS Command Injection in YouTube Search
scripts/douyin_search.py:10Reusable Platform Session Cookies Stored in a Plaintext Project File
The declared description presents a broad, personalized multi-platform recommendation skill, but the supplied code implements a narrow Bilibili-only search utility. It accesses only Bilibili APIs and a local cookie file, with no code for 小红书、抖音、YouTube, no preference learning, and no recommendation engine or push behavior. Reading cookies from a file is materially different from 'automatically obtaining user cookies.' While Bilibili is one of the mentioned platforms and searching for videos/bloggers is related, the actual functionality is substantially narrower and lacks several core declared behaviors.
The declared description presents a broader recommendation system that works across several platforms, learns the user's tastes, automatically acquires cookies, and pushes personalized content. The supplied code chunk is much narrower: it simply loads preexisting Douyin cookies from a file and calls a Douyin search API for a provided keyword, returning a list of video results. While this partially aligns with the Douyin-search portion of the description, the primary behavior here is only a single-platform keyword search, and several prominent declared capabilities are absent.
The declared description presents a broader recommendation system with cross-platform coverage, automatic cookie retrieval, user preference learning, and personalized content pushing. The supplied code chunk only implements a straightforward Xiaohongshu search wrapper via xhs search, then formats a limited subset of note metadata. There is no evidence of support for Douyin, YouTube, or Bilibili; no cookie access logic; no user profiling or learning; and no personalization or push mechanism. Therefore the code materially under-implements and differs from the declared behavior.
The declared description promises a multi-platform personalized recommendation skill spanning Xiaohongshu, Douyin, YouTube, and Bilibili, including automatic cookie acquisition and preference learning. The supplied code only performs a generic YouTube search via yt-dlp and returns top results sorted by view count. It does not access cookies, track user preferences, personalize recommendations, or interact with the other declared platforms. While YouTube search is one subset of the stated goal, the implemented behavior is materially narrower and lacks several prominent declared capabilities, so this is a description-behavior mismatch.
The skill explicitly instructs collection, storage, and reuse of platform authentication cookies and user preference data. Authentication cookies are credential-equivalent for many services; storing them in local files creates a high-value secret exposure path that can enable account takeover, session hijacking, privacy loss, and unauthorized tracking.
The workflow tells users to open browser developer tools, extract named session cookies, and hand them to the skill. This is a classic credential-harvesting pattern: the requested values (for example sessionid, SESSDATA, web_session) are often sufficient to impersonate the user, making the context especially dangerous because the skill is framed as entertainment rather than a legitimate account-integration flow.
This is a classic tool-parameter abuse issue: user input flows into a shell command without safe argument separation. In the context of an agent skill that may process natural-language requests, attackers can craft a search term that escapes the quoted context and executes arbitrary commands, potentially exposing local files, credentials, or cookies.
def search_xhs(keyword, num=10):
"""使用 xhs-cli 搜索"""
cmd = f'source ~/.agent-reach-venv/bin/activate && xhs search "{keyword}" --sort popular --json'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
try:
data = json.loads(result.stdout)
This is a classic tool-parameter abuse issue: untrusted input is fed into a powerful system tool via a shell command, allowing the tool invocation to be repurposed into arbitrary command execution. In the context of an agent skill that may operate on behalf of users and potentially access cookies/preferences, the blast radius is larger because compromise could extend beyond this single search action.
def search_youtube(keyword, num=5):
"""搜索 YouTube 视频"""
cmd = f'yt-dlp --dump-json "ytsearch{num}:{keyword}"'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
results = []
for line in result.stdout.strip().split('\n'):
The skill declares shell, file-read, and network-capable behavior but does not define any tool scope or permission boundaries. In a skill that instructs reading/storing cookies and opening links, missing explicit tool restrictions increases the chance the agent can access local data or execute commands beyond the intended search workflow.
The usage scenarios are ambiguous and broad, so the skill may activate on ordinary conversation without strong user intent. Because the skill handles sensitive preference data and asks for platform cookies, ambiguous activation materially raises privacy and credential-handling risk.
The trigger phrases are broad common-language terms such as requests to find attractive creators, making accidental or overly eager activation likely. In this skill, accidental activation is more dangerous because the workflow then steers users toward credential extraction, local data storage, and shell/network actions.
The skill specifies persistent storage of preference history and platform cookies in predictable local reference files. Persisting both behavioral profiling data and live session secrets expands the blast radius of any local compromise, accidental disclosure, backup leak, or misuse by other tools/skills.
The script loads persisted Bilibili cookies from a local file and silently attaches them to search and profile requests, even though these endpoints can generally be queried without user authentication for basic discovery. In the broader skill context, which explicitly mentions automatically obtaining cookies and learning user preferences, this creates a privacy and account-abuse risk because the skill can act with the user's authenticated session without clear necessity or consent.
The code performs outbound requests using stored cookies with no user-facing notice, prompt, or audit trail. Given the skill description's emphasis on automatic cookie collection and personalized recommendation, the hidden use of authenticated session data is especially dangerous because it can expose browsing identity, influence server-side personalization, and normalize covert data use.
The script transmits user-supplied search terms and attached cookies to Bilibili over the network. External transmission alone is not inherently unsafe, but in this case it becomes security-relevant because the request includes persisted authentication material for a feature that appears to only need public search, increasing privacy exposure and session linkage risk.
'Referer': f'https://search.bilibili.com/all?keyword={urllib.parse.quote(keyword)}',
}
api_url = 'https://api.bilibili.com/x/web-interface/search/type'
params = {
'search_type': 'video',
'keyword': keyword,
The profile-video lookup sends the target user ID and the caller's persisted cookies to an external Bilibili endpoint. In the skill's context of collecting cookies and inferring user preferences, this expands the privacy surface by allowing silent authenticated lookups that can reveal or couple user identity and behavioral profiling with remote requests.
'Referer': f'https://space.bilibili.com/{mid}',
}
api_url = 'https://api.bilibili.com/x/space/arc/search'
params = {
'mid': str(mid),
'ps': str(num),
The script silently loads Douyin cookies from a local file and sends them to Douyin in authenticated requests without any user notice, consent, or scoping controls. In the context of this skill, which explicitly advertises automatic cookie collection and preference learning, this behavior can facilitate unauthorized use of a user's authenticated session and privacy-invasive profiling.
A content-search skill does not need shell execution, yet this implementation launches a shell to perform the search. That unnecessarily expands the attack surface and, in this file, combines with user-controlled input to create a direct command-injection path.
The script builds a shell command and executes it via subprocess.run with shell=True, but there is no confirmation prompt, visible disclosure, or explanatory comment warning the user that an external command will be run. In a code file, subprocess execution is a safety-relevant operation that should be explicitly disclosed unless clearly communicated as part of the skill behavior.
The script builds a shell command by interpolating the untrusted keyword directly into a string and executes it with subprocess.run(..., shell=True). An attacker can supply shell metacharacters or quote-breaking input to achieve arbitrary command execution under the agent's privileges, which is especially dangerous given the broader skill context mentions automatic cookie access and multi-platform scraping.
def search_xhs(keyword, num=10):
"""使用 xhs-cli 搜索"""
cmd = f'source ~/.agent-reach-venv/bin/activate && xhs search "{keyword}" --sort popular --json'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
try:
data = json.loads(result.stdout)
User-provided search terms are passed into shell execution without validation, escaping, or any confirmation boundary. In this file that is not merely a UX issue; combined with shell=True it directly enables command injection and abuse of the host environment.
The script builds a shell command by interpolating the user-controlled keyword directly into a string and then executes it with shell=True. This creates a command injection path: an attacker can supply shell metacharacters or crafted input to execute arbitrary OS commands under the agent's privileges.
def search_youtube(keyword, num=5):
"""搜索 YouTube 视频"""
cmd = f'yt-dlp --dump-json "ytsearch{num}:{keyword}"'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
results = []
for line in result.stdout.strip().split('\n'):
The default keyword is hard-coded as "beautiful girl", which imposes a specific content and language choice when the user provides no input. This is a natural-language policy concern because the skill does not offer a neutral default or ask the user to choose the query explicitly.
The skill is written to operate entirely in Chinese-language platform and query contexts, and the trigger phrases are fixed to that locale without stating that this is optional or region-specific by design. Under the policy, locale constraints should either offer user choice or be explicitly justified.
Natural-language strings in the script, including the default search keyword and user-facing descriptions, are fixed in Chinese with no indication of locale choice or opt-in. This can violate language/locale policy when a skill implicitly forces one language rather than allowing the user to choose.