Back to skill

Security audit

Easy Search

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed command-line web search skill with expected network access and local caching, with privacy and dependency caveats users should understand.

Install only in a normal user environment, preferably a virtual environment, and avoid searching for secrets or sensitive internal terms because queries are sent to third-party search services and may be cached locally in plaintext. Use --no-cache for sensitive searches and --clear-cache to remove saved results.

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

T08 · Insecure Dependencies

Warning
Location
SKILL.md:24
Finding

Unpinned Third-Party Dependencies Create a Supply-Chain Risk

Content
View full analysis
Remediation
View remediation
requests== ``` 2. Generate and publish cryptographic hashes for every permitted distribution, then require hash verification: ```bash python -m pip install --require-hashes -r requirements.txt ``` 3. Use a lock-file workflow such as `pip-tools`, Poetry, or an equivalent reproducible dependency manager. 4. Pin transitive dependencies as well as direct dependencies. 5. Review and update dependencies through a controlled process with vulnerability and provenance checks. 6. Advise users not to install the Skill with `sudo` or into a privileged global Python environment. 7. Consider isolating dependencies in a dedicated virtual environment. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/search.py:624
Finding

Sensitive Search Queries and Results Are Cached in Plaintext

Content
View full analysis
str: key = f"{query}:{engine}:{time_filter or 'all'}" return hashlib.md5(key.encode()).hexdigest() def get_cached_result(query: str, engine: str, time_filter: Optional[str] = None) -> Optional[Dict]: try: cache_file = CACHE_DIR / f"{get_cache_key(query, engine, time_filter)}.json" if cache_file.exists(): if time.time() - cache_file.stat().st_mtime < CACHE_TTL: return json.loads(cache_file.read_text()) except: pass return None def save_to_cache(query: str, engine: str, result: Dict, time_filter: Optional[str] = None): try: CACHE_DIR.mkdir(parents=True, exist_ok=True) cache_file = CACHE_DIR / f"{get_cache_key(query, engine, time_filter)}.json" cache_file.write_text(json.dumps(result, ensure_ascii=False)) except: pass ``` The cached result explicitly contains the original query: ```python result = { "query": query, "engine": engine, "method": method, "results": results[:max_results], "total": len(results[:max_results]) } ``` ### Technical Analysis The cache filename is derived from an MD5 digest, but the cache file’s JSON contents include the original search query, result URLs, titles, and snippets in plaintext. Hashing the filename therefore does not protect the sensitive content. The cache directory is created without an explicit mode, and files are written without explicitly enforcing owner-only permissions. Their effective permissions depend on the process umask and pre-ex ...[truncated 2050 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises and documents network use, proxy support, caching, and likely file/environment access, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates a capability/expectation gap: a user or hosting agent may not realize the skill can access environment variables, write cache files, or perform outbound requests, increasing the chance of overbroad execution and unintended data exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This skill sends user-supplied search queries to third-party search engines and may route them through configured proxies, but the description does not warn users that their input leaves the local environment. If users submit secrets, internal project names, or sensitive research topics, that data could be disclosed to search providers, proxy operators, or network logs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Search queries and returned results are persisted under the user's home directory for an hour without an explicit privacy warning or opt-in. In an agent setting, queries may contain sensitive prompts, internal project names, credentials, incident terms, or URLs, and local cache files can later be read by other local processes, users, backups, or forensic tooling.

Content

No source excerpt is available for this finding.

Tainted flow: 'url' from requests.get (line 532, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/search.py (reported line 1148)May include surrounding context.

python
for name, url in test_urls:
            try:
                if HAS_REQUESTS:
                    resp = requests.get(url, timeout=5, headers={"User-Agent": USER_AGENTS[0]})
                    status = f"OK ({resp.status_code})"
                else:
                    import urllib.request

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The --diagnose mode performs additional outbound requests to several third-party sites outside the tool's core search path. In an agent/skill context, that broadens network side effects, can leak environment/network metadata such as proxy behavior and egress reachability, and may violate least-privilege expectations if invoked unexpectedly.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.