Back to skill

Security audit

Search Cluster

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed multi-provider search skill with normal outbound search behavior, but users should understand its subprocess, scraping, caching, and dependency risks before installing.

Install only if you are comfortable sending search terms to the listed external providers, including DuckDuckGo through Scrapling. Use a trusted virtual environment for SCRAPLING_PYTHON_PATH, consider pinning Scrapling dependencies yourself, avoid putting secrets in custom user-agent values or queries, and configure Redis only if caching search results for 24 hours is acceptable.

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:9
Finding

Unpinned Third-Party Dependency Creates a Supply-Chain Risk

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
search-cluster.py:25
Finding

Untrusted Search Content Is Inadequately Protected Against Downstream Prompt Injection

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Tainted flow: 'req' from os.getenv (line 132, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · search-cluster.py (reported line 57)May include surrounding context.

python
ctx = ssl.create_default_context()
    try:
        req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
        with urllib.request.urlopen(req, timeout=10, context=ctx) as response:
            data = json.loads(response.read().decode())
            results = []
            if isinstance(data, list) and len(data) > 3:

Tainted flow: 'req' from os.getenv (line 132, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · search-cluster.py (reported line 80)May include surrounding context.

python
ctx = ssl.create_default_context()
    try:
        req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
        with urllib.request.urlopen(req, timeout=10, context=ctx) as response:
            data = json.loads(response.read().decode())
            results = []
            if isinstance(data, list) and len(data) > 3:

Tainted flow: 'req' from os.getenv (line 132, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · search-cluster.py (reported line 114)May include surrounding context.

python
ctx = ssl.create_default_context()
    try:
        req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
        with urllib.request.urlopen(req, timeout=10, context=ctx) as response:
            data = json.loads(response.read().decode())
            results = []
            if isinstance(data, list) and len(data) > 3:

Tainted flow: 'req' from os.getenv (line 132, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · search-cluster.py (reported line 133)May include surrounding context.

python
ctx = ssl.create_default_context()
    try:
        req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
        with urllib.request.urlopen(req, timeout=10, context=ctx) as response:
            data = json.loads(response.read().decode())
            results = []
            if isinstance(data, list) and len(data) > 3:

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared behavior says the skill aggregates results from specific providers, but the implementation reportedly uses DuckDuckGo scraping and a stealth-fetching mechanism that is not transparently disclosed. This mismatch is dangerous because it can conceal unexpected network destinations and collection methods, undermining user consent, security review, and policy enforcement; the use of 'stealth' scraping makes the discrepancy more suspicious in this context.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises executable components and requires environment variables, network access, and shell/subprocess behavior, but it does not declare an explicit tool scope such as permissions or allowed-tools. This creates a governance gap where reviewers and runtime policy engines cannot easily constrain what the skill is allowed to access, increasing the risk of unintended command execution, secret exposure, or outbound requests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

User search terms are sent to third-party services, which can expose potentially sensitive queries to external providers without any explicit disclosure or consent mechanism in the code path. In a search aggregation skill, this is contextually significant because the core function fans the same query out to multiple services, increasing privacy exposure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Executing an external helper process is a meaningful security-relevant design choice because it introduces another executable component and trust boundary. In this skill's context, that is more dangerous than a typical search aggregator because compromise of the helper script or interpreter path can alter behavior or execute arbitrary code.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill launches a secondary script for one provider without any user-facing indication, obscuring that additional local code will run as part of a search request. Hidden execution paths reduce transparency and can surprise operators, especially in agent environments where capabilities should be explicit.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
92% confidence
Finding

The skill spawns an external Python interpreter and helper script to fulfill search functionality, which expands the attack surface beyond normal in-process HTTP requests. While subprocess.run is invoked without shell=True, the executable path comes from an environment variable, so a compromised or untrusted environment can redirect execution to an unintended binary.

Content

Scanner excerpt · search-cluster.py (reported line 100)May include surrounding context.

python
if not os.path.exists(SCRAPLING_PYTHON) or not os.path.exists(STEALTH_SCRIPT):
        return []
    try:
        result = subprocess.run([SCRAPLING_PYTHON, STEALTH_SCRIPT, query], capture_output=True, text=True, timeout=30)
        if result.returncode == 0:
            data = json.loads(result.stdout)
            for item in data:

Tainted flow: 'SCRAPLING_PYTHON' from os.getenv (line 20, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
97% confidence
Finding

SCRAPLING_PYTHON is taken from an environment variable and executed directly, creating a trust boundary violation that can lead to arbitrary code execution if the environment is attacker-controlled or misconfigured. The existence check only confirms that a path exists, not that it is the intended interpreter or a safe executable.

Content

Scanner excerpt · search-cluster.py (reported line 100)May include surrounding context.

python
if not os.path.exists(SCRAPLING_PYTHON) or not os.path.exists(STEALTH_SCRIPT):
        return []
    try:
        result = subprocess.run([SCRAPLING_PYTHON, STEALTH_SCRIPT, query], capture_output=True, text=True, timeout=30)
        if result.returncode == 0:
            data = json.loads(result.stdout)
            for item in data:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The Google News RSS query forces hl=en-US, gl=US, and ceid=US:en, which imposes a specific language and region regardless of user preference. This is a natural-language policy issue because the skill does not offer a locale choice or document a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The implementation sends user queries to DuckDuckGo and scrapes its HTML results even though the skill metadata says it aggregates Google CSE, GNews RSS, Wikipedia, Reddit, and Scrapling. This is a real integrity and transparency issue because users and downstream systems may rely on the declared data sources for privacy, compliance, or trust decisions, but the code silently uses an undeclared third-party endpoint instead.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This markdown file documents multiple outbound network endpoints and notes required credentials such as GOOGLE_API_KEY, but it does not include any warning that using these APIs transmits queries or metadata to third parties. Under the markdown variant of SQP-2, descriptions should warn about behaviors that may affect user privacy or external data handling.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
71% confidence
Finding

The file specifies https://en.wikipedia.org/w/api.php, which fixes the skill behavior to the English Wikipedia domain. Because no user choice, opt-in, or documented justification is provided, this appears to impose a specific language/locale in natural-language configuration.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The code transmits the user's search query to an external website without any explicit disclosure, consent flow, or warning. In a search skill this may seem routine, but it still creates a privacy risk because user-supplied queries can contain sensitive terms, and the hidden transmission is more concerning here because the destination is also undeclared in the manifest.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.