T08 · Insecure Dependencies
- Location
SKILL.md:14- Finding
Unpinned Third-Party Python Dependencies
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a disclosed X/Twitter search helper that sends user-requested searches to xAI and can optionally save or schedule results, with manageable setup and privacy risks but no artifact-backed malicious behavior.
Install only if you are comfortable sending your X search prompts and xAI API key to xAI. Use a virtual environment, consider pinning `requests` and `pyyaml`, choose `--output` paths carefully because existing same-day files can be overwritten, and review any cron announcements before sending results to Telegram, Slack, or Discord.
SKILL.md:14Unpinned Third-Party Python Dependencies
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
resp = None
for attempt in range(3):
try:
resp = requests.post(API_URL, headers=headers, json=payload, timeout=120)
if resp.ok:
break
print(f"API error {resp.status_code} (attempt {attempt+1}/3): {resp.text}", file=sys.stderr)
The skill explicitly supports writing to arbitrary user-provided paths and overwriting same-day files, creating a real file-modification primitive. In an agent context, combining broad triggers, shell execution, and path-based output can lead to destructive overwrites of user content or persistence in unintended locations if the path is influenced by ambiguous prompts or unsafe automation.
`--output` saves the result to a Markdown file (stdout is preserved):
- Pass a **directory** → auto-named file: `karpathy-2026-03-22.md`, `trends-AI-2026-03-22.md`, etc.
- Pass a **full path** → saved directly to that path
- Same-day runs overwrite the existing file (no duplicate accumulation)
`--progress-only` suppresses full Markdown on stdout — prints one summary line instead. Use with `--output` in automated pipelines (watchlist, cron) to avoid injecting large outputs into the agent context.
The documentation reveals and encourages direct use of the agent's configuration/skills directory under ~/.claude, exposing internal layout and normalizing access to sensitive agent-local paths. In agent environments, this can expand the blast radius of path-based misuse, accidental disclosure, or chaining with other skills that can read or modify files in the same area.
Find the script at ~/.claude/skills/x-search/x_search.py (or the symlinked path).
# Account mode — by time range
Referenced artifact was not completely inspected
> **Note:** all accounts share the same execution parameters. For per-account customization, call `x_search.py` directly.
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.
parser.add_argument(
"--output", "-o", default=None, metavar="PATH",
help="Save output to file. Pass a directory for auto-naming, or a full path. "
"Same-day runs overwrite the existing file.",
)
parser.add_argument(
"--progress-only", action="store_true",
The file repeatedly uses Asia/Shanghai in scheduling examples and includes a --lang zh example, presenting a specific locale/language as the default pattern without offering choice or clarifying that these are merely sample values. This can violate language/locale policy when users are not given an explicit opt-in or alternative.
The examples use --announce --channel telegram --to ... and later document Slack and Discord delivery, which sends search results or notifications to third-party messaging platforms. The markdown does not warn users that scheduled output may be transmitted off-system to external services.
The skill advertises and instructs use of environment variables, shell execution, network access, and file writing, but it does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, this increases the chance the skill is invoked with broader capabilities than necessary, making unintended file writes, external requests, or command execution harder to constrain and audit.
The trigger language is broad and open-ended, so the skill may be auto-selected for loosely related requests involving X/Twitter accounts or searches. Over-broad invocation increases the chance an agent will perform network access, shell execution, and optional file writes when the user did not clearly request those side effects.
The documentation states that '--lang' defaults to 'zh', which imposes a specific language choice unless the user overrides it. This is a locale/language policy concern because the skill does not indicate that the user is asked to choose or consent to that default.
Persisting search results to disk creates session-to-session state that may contain sensitive queries, monitored accounts, or externally sourced content. In scheduled or automated use, this can accumulate durable artifacts that are later consumed by other tools or exposed to other users/processes, increasing privacy and integrity risks.
`--output` saves the result to a Markdown file (stdout is preserved):
- Pass a **directory** → auto-named file: `karpathy-2026-03-22.md`, `trends-AI-2026-03-22.md`, etc.
- Pass a **full path** → saved directly to that path
- Same-day runs overwrite the existing file (no duplicate accumulation)
`--progress-only` suppresses full Markdown on stdout — prints one summary line instead. Use with `--output` in automated pipelines (watchlist, cron) to avoid injecting large outputs into the agent context.
Referencing ~/.claude/skills/x-search leaks the existence and structure of the installed skills directory, which aids skill enumeration and environment fingerprinting. On its own this is moderate, but in a multi-skill or partially compromised environment it can help an attacker discover adjacent components to target.
Find the script at ~/.claude/skills/x-search/x_search.py (or the symlinked path).
# Account mode — by time range
The prescribed post-result question is written only in Chinese and is presented as the required follow-up, which can force a language choice on users who did not opt into Chinese. This conflicts with language/locale neutrality expectations unless the skill is explicitly scoped to Chinese users.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def run(cmd: list[str]) -> None:
print(f"\n→ {' '.join(cmd)}", file=sys.stderr)
result = subprocess.run(cmd)
if result.returncode != 0:
print(f" ✗ exited with code {result.returncode}", file=sys.stderr)
The CLI sets --lang to zh by default, which imposes a specific language choice when the user does not explicitly request one. This is a natural-language locale policy concern because the skill does not present a neutral default or require user opt-in for the forced language.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
print("Error: 'requests' not installed. Run: pip install requests", file=sys.stderr)
sys.exit(1)
API_URL = "https://api.x.ai/v1/responses"
# Default model. Override with XAI_MODEL env var to pin a specific version, e.g.:
# export XAI_MODEL=grok-4
MODEL = os.environ.get("XAI_MODEL", "grok-4-1-fast-reasoning")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
resp = None
for attempt in range(3):
try:
resp = requests.post(API_URL, headers=headers, json=payload, timeout=120)
if resp.ok:
break
print(f"API error {resp.status_code} (attempt {attempt+1}/3): {resp.text}", file=sys.stderr)
The account-search function defaults the output language to "zh", which imposes a specific language choice unless the user explicitly overrides it. This is a natural-language policy concern because the skill sets a locale preference by default rather than prompting for or preserving user choice.
The command-line interface sets --lang default to zh, meaning generated summaries/translations will be in Chinese unless the user notices and changes the flag. This forces a specific language by default and does not provide an opt-in language selection flow.
The skill description repeatedly instructs users to save results to ~/obsidian/X/, which affects local user data by creating or updating files. The markdown does not include any warning or disclosure that scheduled runs will write to that directory automatically over time.
The manifest description frames the skill as a search tool that outputs Obsidian-ready Markdown, but the documented behavior includes persistent file writing via --output and batch/scheduled watchlist execution. Those behaviors go beyond a simple search-and-display description, even though they are documented elsewhere in the file.
The comment shows a direct invocation example with --lang en, which prescribes English as the language setting. Because no alternative language choice, opt-in, or justification is provided in the file, this may violate the language/locale policy for natural-language instructions.
No suspicious patterns detected.