Back to skill

Security audit

Last30days

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real recent-research tool, but it needs review because local project configuration can steer some network behavior and untrusted search snippets can influence planning.

Install only if you are comfortable sending research topics and retrieved snippets to AISA and the selected external services. Avoid running it from untrusted repositories that may contain .claude/last30days.env, set credentials in trusted process environment variables instead, and do not enable Xiaohongshu or custom endpoints unless you control and trust the endpoint.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib/env.py:248
Finding

Repository-Controlled Xiaohongshu Endpoint Enables SSRF and Research Topic Disclosure

Content
View full analysis
Path | None: """Find per-project .env by walking up from cwd. Searches for .claude/last30days.env in each parent directory, stopping at the user's home directory or filesystem root. """ cwd = Path.cwd() for parent in [cwd, *cwd.parents]: candidate = parent / '.claude' / 'last30days.env' if candidate.exists(): return candidate # Stop at filesystem root or home if parent == Path.home() or parent == parent.parent: break return None ``` `scripts/lib/env.py:92-102` gives this project configuration precedence over the default configuration: ```python # Load from per-project config (overrides global) project_env_path = _find_project_env() project_env = load_env_file(project_env_path) if project_env_path else {} # Merge: project overrides global merged_env = {**file_env, **project_env} # Build config: process.env > project .env > global .env config = { 'AISA_API_KEY': os.environ.get('AISA_API_KEY') or merged_env.get('AISA_API_KEY'), 'AISA_BASE_URL': os.environ.get('AISA_BASE_URL') or merged_env.get('AISA_BASE_URL', 'https://api.aisa.one'), ``` `scripts/lib/env.py:248-251` accepts the configured URL without validating its scheme, hostname, or resolved address: ```python def get_xiaohongshu_api_base(config: dict[str, Any]) -> str: """Get Xiaohongshu HTTP API base URL. Defaults to host.docker.internal so OpenClaw Docker can reach host service. """ return (config.get('XIAO ...[truncated 4319 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
scripts/lib/planner.py:97
Finding

Untrusted Web Search Content Is Inserted into the LLM Planner Prompt Without a Trust Boundary

Content
View full analysis
tuple[str, list[dict]]: items, _artifact = grounding.web_search(query, date_range, config) return label, items with ThreadPoolExecutor(max_workers=3) as executor: futures = { executor.submit(_search, label, q): label for label, q in queries.items() } for future in as_completed(futures): label = futures[future] try: _label, items = future.result() results[label] = items searches_run += 1 except Exception as exc: _log(f"Search failed for {label}: {exc}") results[label] = [] subreddits = _extract_subreddits(results.get("subreddit", [])) x_handle = _extract_x_handle(results.get("x_handle", [])) github_user = _extract_github_user(results.get("github", [])) github_repos = _extract_github_repos(results.get("github", [])) context = _build_context_summary(results.get("news", [])) ``` `scripts/lib/planner.py:97-100` appends that context directly to the instruction prompt: ```python prompt = _build_prompt(topic, available_sources, requested_sources, depth) if context: prompt += f"\n\nCurrent context (from web search): {context}" if provider and model: try: ``` By comparison, the reranker includes an explicit untrusted-content boundary in `scripts/lib/rerank.py:43-48`: ```pyt ...[truncated 3174 chars]
Remediation
View remediation
\n" f"{context}\n" "" ) ``` 2. Serialize search context as JSON with fixed fields such as `title`, `snippet`, `url`, and `source_domain`, rather than appending free-form prose. 3. Keep operational instructions and untrusted content in separate model message roles if the provider supports system and user messages. 4. Add deterministic semantic validation after planning: - Require meaningful token overlap between each generated query and the original topic. - Reject queries that introduce unrelated domains or entities without evidence. - Fall back to deterministic planning when validation fails. - Limit query length and the number of newly introduced proper nouns. 5. Strip or flag common instruction-oriented phrases in search snippets before including them in planner context. This should supplement, not replace, prompt isolation. 6. Prefer deterministic extraction for subreddits, handles, and repositories instead of feeding raw search snippets back into the planning model. 7. Add adversarial tests where titles and snippets contain instructions such as “ignore previous instructions,” forged JSON, fake prompt delimiters, and requests to search unrelated topics. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (78)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Yes, this is a mismatch. The declared description describes a substantive research capability over Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, GitHub, and web search. The actual code chunk does none of that; it only checks for an installed Python 3.12+ executable and prints its path. While environment setup can be a supporting implementation detail, this chunk by itself does not reflect the declared functionality and instead has a different immediate purpose: selecting a Python runtime. Therefore the supplied code does not accurately represent the declared behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Yes, this is a mismatch based on the provided code chunk. The declared description promises a substantial research capability spanning multiple external platforms and analytical output generation. However, the actual code shown is only an __init__.py file containing a version string. That behavior is purely metadata/supporting infrastructure and does not substantiate the declared primary purpose. While this may be only a partial code sample, evaluating the supplied chunk alone, the implemented behavior does not match the declared functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description promises broad multi-platform research across nine sources plus grounded web search and a synthesized ranked/clustered brief. The supplied code chunk only implements AIsa wrappers for chat completions, Twitter/X search, YouTube search, Tavily web/news search, and Polymarket market search, along with response parsers and relevance/date normalization helpers. There is no code here for Reddit, TikTok, Instagram, Hacker News, or GitHub retrieval. Also, while the parsers attach URLs and relevance fields, this chunk does not generate the described final clustered brief with citations; it only fetches and structures source results. Additionally, it includes a general chat_completion helper, which is not part of the declared description. Therefore the declared description materially overstates and partly misrepresents the actual behavior of this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a broad social/web research skill that gathers recent information from many external platforms and produces ranked, clustered, cited research briefs. The actual code chunk does none of that directly. It is a local text deduplication utility operating on SourceItem objects, using normalization plus n-gram/token Jaccard similarity to filter near-duplicates. While deduplication could be a supporting internal component of a research pipeline, this code by itself does not implement or expose the declared primary purpose. Therefore, the description does not accurately represent what this supplied code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents a broad multi-source recent-research skill, but this code chunk is a narrow GitHub integration module. Its primary behavior is querying the GitHub Search API plus related repo endpoints, enriching results with comments, releases, README snippets, issue summaries, and star counts. That is materially narrower than the declared cross-platform research purpose, and it also includes profile/project analysis capabilities not mentioned in the description. Additionally, the code depends on GitHub tokens, which is inconsistent with declaring no permissions. While GitHub is one of the listed sources, this chunk alone does not match the broader declared functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

There is a material description-to-code mismatch. The declared purpose describes a comprehensive multi-platform recency research skill spanning numerous social and web sources and producing synthesized ranked/clustered output. The actual code chunk is narrowly scoped to grounded web search through a single proxy service (AIsa Tavily), plus helper functions for date normalization/range checks and URL domain extraction. No evidence in this chunk supports the claimed retrieval from the named social platforms or the higher-level synthesis behavior. This is not merely an implementation detail omission; the described primary capability is substantially broader than the observed behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose describes a broad cross-platform recent-research capability over several named sources, with output as a ranked, clustered brief with citations. The actual code chunk is narrowly focused on Pinterest discovery through an AISA web proxy (site:pinterest.com), parsing/normalizing Pinterest items and engagement metadata. This is a material description-behavior mismatch because the code accesses an undeclared source (Pinterest) and lacks the stated synthesis behavior. While this may be one module within a larger system, evaluating this supplied chunk alone, its behavior is not accurately represented by the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

Most of the core description matches the code well: the pipeline computes a date range (default 30 days), plans subqueries, searches across Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, GitHub, and grounded web search, then normalizes, deduplicates, reranks, clusters, and returns a structured report. That said, the code materially exceeds the declared source set and capabilities. It conditionally exposes additional sources (Threads, Pinterest, Xiaohongshu) and includes supplemental searches driven by extracted entities/handles from prior results, especially extra X lookups. It also has special GitHub person/project search modes and candidate star enrichment not mentioned in the description. Because the declared description presents a fairly specific set of supported sources and behavior, these extra capabilities are meaningful undeclared behavior, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The declared description is about a research skill that gathers recent information across many external platforms and produces a ranked, clustered brief with citations. The supplied code chunk instead contains infrastructure code for provider selection and model interaction: it resolves configuration variables, chooses an AISA/local reasoning runtime, checks API keys, extracts text/JSON from model outputs, and parses streaming response chunks. This is materially different from the declared end-user behavior. While this code could support a larger research system, this chunk itself does not implement the described research capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description is for a multi-source recent-research skill that gathers evidence from numerous platforms and produces a synthesized brief. The supplied code does not conduct any retrieval, clustering, ranking, citation generation, or cross-platform analysis. Instead, it evaluates whether certain sources were active, computes a percentage score, and builds user-facing guidance about missing sources and credentials. This is a materially different primary purpose, so the description does not accurately represent the code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full multi-platform recent-research skill. However, this code chunk is a narrow helper library for cleaning search queries and identifying compound terms. While such preprocessing could support a larger research system, the behavior shown here is materially different from the declared end-user capability and does not itself implement the claimed research, aggregation, ranking, clustering, or citation functions. Therefore this chunk does not accurately represent the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This code chunk materially underdelivers relative to the declared description. The declared purpose describes a broad multi-source research skill spanning numerous social and web platforms and producing a synthesized ranked/clustered brief with citations. In contrast, the supplied code is narrowly scoped to Reddit: helper logic for Reddit query expansion, subreddit discovery, public Reddit search delegation, comment fetching, and enrichment. It does not access or orchestrate any of the other named platforms, nor does it build the final analytical brief described. While this module could be one component of a larger system, judged on this supplied chunk alone, the actual behavior is Reddit-only and therefore does not accurately represent the declared overall capability.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The supplied code chunk is narrowly focused on Reddit thread enrichment. It validates Reddit URLs, fetches Reddit JSON, parses submission/comment data, derives engagement metrics, selects top comments, and extracts short heuristic comment insights. A legacy Reddit-specific API path is also present. There is no evidence here of searching across X, YouTube, TikTok, Instagram, Hacker News, Polymarket, GitHub, or grounded web search, nor of producing a ranked/clustered cross-platform brief with citations. This is a materially narrower behavior than the declared purpose, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description presents a broad last-30-days research skill spanning many platforms and producing a clustered brief with citations. The supplied code chunk only performs Reddit public search and optional Reddit comment enrichment. It does not access or analyze the other listed platforms, does not perform grounded web search, and does not generate a final ranked/clustered brief. While the Reddit portion is consistent with part of the description, the actual behavior of this chunk is substantially narrower than the declared purpose, so this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description claims a research skill spanning Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, GitHub, and grounded web search, producing a ranked and clustered brief with citations. The supplied code is a narrower internal reranking/scoring module. It accepts preexisting candidates and a query plan, asks an LLM to judge relevance, applies fallback scoring, and sorts candidates. That reranking behavior is plausibly supportive of the declared pipeline, so by itself it is not a problem. However, the code also implements a separate 'score_fun' path whose stated purpose is to score content for humor, cleverness, wit, and shareability, with heuristics favoring punchy, meme-like, viral content. That is a materially different and undeclared capability from recent research briefing. Additionally, this chunk does not itself carry out the declared multi-source search or brief/citation generation, so the observed behavior is only a partial match to the declaration.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a comprehensive cross-platform recent-research skill. The supplied code chunk is much narrower: it issues four web searches ('subreddit', 'news', 'x_handle', 'github') and extracts identifiers from search results using regexes, plus a short context snippet. That is a materially different primary purpose from producing a full ranked, clustered research brief with citations across many sources. While the code does use grounded web search over a 30-day date range and touches Reddit/X/GitHub/news indirectly, it lacks most of the declared platform coverage and output behavior, so this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a broad last-30-days cross-platform research capability spanning numerous social, web, prediction, and code platforms, plus synthesis into a ranked clustered brief with citations. The supplied code does something materially narrower: it searches only Threads content through aisa.search_tavily with a site:threads.net query, filters by date, and formats result items. While this may be a supporting subcomponent of a larger system, evaluating this chunk alone shows a clear scope mismatch between the broad declared functionality and the actual implemented behavior. There is no evidence here of Reddit/X/YouTube/TikTok/Instagram/Hacker News/Polymarket/GitHub coverage, grounded web search aggregation, clustering, briefing, or citation generation.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

This code chunk does not match the declared description well. The declared purpose describes a broad cross-platform recent-research capability spanning multiple named services plus grounded web search, culminating in a ranked and clustered brief with citations. In contrast, this code only interfaces with Xiaohongshu via specific REST endpoints, checks whether that service is logged in, performs a feed search there, and converts results into a standardized item format with engagement metadata. Xiaohongshu is an undeclared resource, and the implemented behavior is a narrow source adapter rather than the described end-to-end multi-source research and summarization capability. While it is plausibly a supporting component of a larger research system, taken on its own it materially differs from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The description presents a broad cross-platform 'last 30 days' research skill that synthesizes evidence into a clustered brief with citations. The supplied code, however, is narrowly scoped to YouTube. It searches YouTube through AISA, optionally fetches captions/transcripts directly from YouTube pages, extracts transcript highlights, and returns item lists. There is no implementation in this chunk for the other declared platforms, no web search, and no final clustered brief/citation generation. While this may be a component of a larger system, this specific code chunk does not accurately represent the declared end-to-end capability, so it is a mismatch.

Content

No source excerpt is available for this finding.

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/lib/env.py (reported line 20)May include surrounding context.

python
CONFIG_FILE = None
elif _config_override:
    CONFIG_DIR = Path(_config_override)
    CONFIG_FILE = CONFIG_DIR / ".env"
else:
    CONFIG_DIR = Path.cwd() / ".claude-skill-data" / "last30days"
    CONFIG_FILE = CONFIG_DIR / ".env"

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/lib/env.py (reported line 23)May include surrounding context.

python
CONFIG_FILE = None
elif _config_override:
    CONFIG_DIR = Path(_config_override)
    CONFIG_FILE = CONFIG_DIR / ".env"
else:
    CONFIG_DIR = Path.cwd() / ".claude-skill-data" / "last30days"
    CONFIG_FILE = CONFIG_DIR / ".env"

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

The function walks up from the current working directory and automatically loads the first matching '.claude/last30days.env' found in any parent directory. In untrusted or shared workspaces, this can cause the skill to ingest attacker-controlled configuration, potentially redirecting API traffic via AISA_BASE_URL or altering runtime behavior without the user realizing it.

Content

Scanner excerpt · scripts/lib/env.py (reported line 65)May include surrounding context.

python
return env

def _find_project_env() -> Path | None:
    """Find per-project .env by walking up from cwd.

    Searches for .claude/last30days.env in each parent directory,
    stopping at the user's home directory or filesystem root.

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The documented and implemented precedence gives project-local '.claude/last30days.env' higher priority than global config, enabling repository-controlled settings to override trusted user configuration. In the context of a research skill that makes outbound API requests, a malicious repository could influence endpoints or tokens used at runtime and steer requests to attacker-controlled services.

Content

Scanner excerpt · scripts/lib/env.py (reported line 87)May include surrounding context.

python
Priority (highest wins):
      1. Environment variables (os.environ)
      2. .claude/last30days.env (per-project config)
      3. ~/.config/last30days/.env (global config)
    """
    # Load from global config file
    file_env = load_env_file(CONFIG_FILE) if CONFIG_FILE else {}

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

The merged configuration allows values such as 'AISA_BASE_URL' and authentication tokens to be sourced from project-local files and then used throughout the skill. In this skill context, which performs networked research across multiple services, attacker-controlled config can redirect outbound requests and cause credential disclosure to malicious infrastructure or unauthorized data flows.

Content

Scanner excerpt · scripts/lib/env.py (reported line 99)May include surrounding context.

python
# Merge: project overrides global
    merged_env = {**file_env, **project_env}

    # Build config: process.env > project .env > global .env
    config = {
        'AISA_API_KEY': os.environ.get('AISA_API_KEY') or merged_env.get('AISA_API_KEY'),
        'AISA_BASE_URL': os.environ.get('AISA_BASE_URL') or merged_env.get('AISA_BASE_URL', 'https://api.aisa.one'),

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/lib/ui.py (reported line 207)May include surrounding context.

python
{Colors.YELLOW}Legacy X authentication failed.{Colors.RESET}

Recommended fix:
1. Add AISA_API_KEY to ./.claude-skill-data/last30days/.env or .claude/last30days.env
2. Re-run to use the hosted AISA Twitter proxy
"""