Back to skill

Security audit

Search Intelligence Skill

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed security/OSINT search skill, but it should go through Review because it automatically generates sensitive reconnaissance queries and feeds untrusted web results into agent context without strong guardrails.

Install only for authorized security research or public-data OSINT, preferably with a trusted HTTPS SearXNG endpoint. Avoid sending confidential targets, personal data, credentials, or internal investigation terms unless the user has explicitly approved it, and treat returned snippets as untrusted web content before allowing an agent to take further actions.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T01 · Skill Instruction Hijacking

Warning
Location
search_dorks_skill/models.py:88
Finding

Untrusted Search Results Are Inserted Directly into LLM Context

Content
View full analysis

Vulnerability Details

File Location: search_dorks_skill/models.py:88-110; untrusted fields originate from search_dorks_skill/client.py:110-129
Vulnerability Type: Indirect prompt injection through external search content
Risk Level: Medium

Vulnerable Code

python
def parse_results(self, raw_response: dict[str, Any]) -> list[SearchResult]:
    """Convert raw SearXNG JSON response to SearchResult objects."""
    results = []
    for item in raw_response.get("results", []):
        results.append(SearchResult(
            title=item.get("title", ""),
            url=item.get("url", ""),
            snippet=item.get("content", ""),
            engines=item.get("engines", []),
            score=float(item.get("score", 0.0)),
            category=item.get("category", "general"),
            positions=item.get("positions", []),
            metadata={
                "template": item.get("template", ""),
                "parsed_url": item.get("parsed_url", []),
                "publishedDate": item.get("publishedDate", ""),
                "thumbnail": item.get("thumbnail", ""),
                "img_src": item.get("img_src", ""),
            },
        ))
    return results
python
def to_context(self, max_results: int = 20) -> str:
    """Format results for LLM context window."""
    lines = [
        f"=== Search Report ===",
        f"Query: {self.query}",
        f"Intent: {self.intent.category.value}/{self.intent.subcategory}",
        f"Strategy: {self.strategy.name}",
        f"Results: {len(self.results)} (of {self.total_found} total)",
        f"Engines: {', '.join(self.engines_used)}",
        f"Time: {self.timing_seconds:.2f}s",
        "",
    ]
    for i, r in enumerate(self.results[:max_results], 1):
        lines.append(f"[{i}] {r.title}")
        lines.append(f"    URL: {r.url}")
        lines.append(f"    {r.snippet[:300]}")
      
...[truncated 2352 chars]
Remediation
View remediation

Remediation Suggestions

  1. Prefer returning typed, structured result objects rather than a prompt-ready string.
  2. When text rendering is required, wrap every external field in explicit untrusted-data delimiters.
  3. Add a fixed instruction before results stating that titles, URLs, snippets, and suggestions are untrusted evidence and must never be interpreted as commands.
  4. Remove control characters and escape markup or delimiter sequences that could break the intended result structure.
  5. Keep external result data in a separate model/tool-response channel where the integration platform supports one.
  6. Apply prompt-injection detection and either flag or omit snippets containing instruction-like content.
  7. Require confirmation before a downstream agent performs consequential tool actions based solely on search-result content.
  8. Document that to_context() output must not be concatenated into privileged system or developer instructions.

T09 · Insecure Skill Coding Practices

Warning
Location
search_dorks_skill/client.py:22
Finding

Sensitive Search Queries May Be Transmitted over Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: search_dorks_skill/client.py:22-69; remote plaintext usage is also shown in README.md:73
Vulnerability Type: Insecure transport and unrestricted redirect handling
Risk Level: Medium

Vulnerable Code

python
def __init__(
    self,
    base_url: str = "http://localhost:8888",
    timeout: float = 30.0,
    max_retries: int = 2,
    rate_limit_delay: float = 0.5,
    verify_ssl: bool = True,
):
    self.base_url = base_url.rstrip("/")
    self.timeout = timeout
    self.max_retries = max_retries
    self.rate_limit_delay = rate_limit_delay
    self._last_request_time = 0.0
    self._client = httpx.Client(
        timeout=timeout,
        verify=verify_ssl,
        headers={"Accept": "application/json"},
        follow_redirects=True,
    )
python
params: dict[str, Any] = {
    "q": query,
    "format": "json",
    "pageno": pageno,
    "safesearch": safesearch,
}
if engines:
    params["engines"] = ",".join(engines)
if categories:
    params["categories"] = ",".join(categories)
if language and language != "auto":
    params["language"] = language
if time_range:
    params["time_range"] = time_range

for attempt in range(self.max_retries + 1):
    try:
        resp = self._client.get(f"{self.base_url}/search", params=params)

The documented remote configuration is:

python
skill = SearchSkill(searxng_url="http://your-searxng:8888")

Technical Analysis

The client accepts arbitrary HTTP base URLs and the documentation demonstrates plaintext HTTP for a potentially remote SearXNG server. Search terms are sent as URL query parameters and may contain investigative targets, email addresses, phone numbers, IP addresses, internal domain names, or credential-related terms.

The verify_ssl option has no protective effect when the URL uses HTTP. In addition, follow_redirects=True allows ...[truncated 1354 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require HTTPS whenever the configured host is not a loopback address.
  2. Reject remote http:// URLs by default and provide an explicit, prominently warned development-only override if necessary.
  3. Change all remote examples to https://.
  4. Preserve TLS certificate verification by default and clearly document the risks of disabling it.
  5. Disable automatic redirects or validate every redirect destination, scheme, host, and port before following it.
  6. Consider limiting the configured endpoint to an administrator-approved allowlist.
  7. Avoid recording full sensitive queries in production logs; use redaction or stable request identifiers.
  8. Use POST requests where supported to reduce query exposure in URL-oriented logs, while recognizing that POST still requires HTTPS.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Dependency Resolution Is Not Reproducibly Constrained

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1; matching declaration at setup.py:9
Vulnerability Type: Unbounded dependency version and missing integrity lock
Risk Level: Low

Vulnerable Code

text
httpx>=0.27.0
python
setup(
    name="search-intelligence-skill",
    version="1.0.0",
    description="Advanced AI search skill with SearXNG backend, dork generation, and intelligent strategies",
    packages=find_packages(),
    python_requires=">=3.9",
    install_requires=["httpx>=0.27.0"],
    author="Your Name",
    license="MIT",
)

Technical Analysis

The project permits any future httpx release at or above version 0.27.0 and does not include a deployment lock file or package hashes. The reviewed dependency name and package source are not suspicious, and no malicious dependency was identified. The issue is that future installations are mutable and may resolve code that was never tested or reviewed with this project.

Because Python dependency installation also resolves transitive packages, different installation times can produce different dependency sets and security behavior.

Attack Path

  1. An operator runs the documented pip install -e . command.
  2. The package index resolves the newest available version satisfying httpx>=0.27.0, together with its transitive dependencies.
  3. A compromised, malicious, or unexpectedly incompatible future release is installed without review by this project.
  4. Dependency code executes during installation, import, or normal HTTP client operation within the Skill's process.

This is a supply-chain exposure rather than evidence that the currently named dependency is malicious.

Impact Assessment

The theoretical impact is bounded by the privileges of the user or service installing and running the package. A compromised dependency could access process data, network resources, and files available to that ac ...[truncated 110 chars]

Remediation
View remediation

Remediation Suggestions

  1. Define and test a compatible upper bound for httpx.
  2. Maintain a lock file for deployed applications so direct and transitive versions are reproducible.
  3. Use hash-verified dependency installation where operationally feasible.
  4. Install only from approved package indexes over authenticated HTTPS.
  5. Add automated dependency vulnerability and provenance scanning.
  6. Review and test dependency upgrades before updating the lock file.
  7. Keep the broad package metadata constraint only if library compatibility requires it, while using stricter locked constraints in deployment environments.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (17)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

This configuration explicitly includes security dork templates for locating exposed environment files, credentials, private keys, admin panels, API docs, and VCS metadata. Even though it is only configuration data, it materially enables reconnaissance and discovery of sensitive assets, which goes beyond a neutral search helper and can facilitate unauthorized targeting if exposed to untrusted users or automated agents.

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 · search_dorks_skill/config.py (reported line 185)May include surrounding context.

python
# Subcategory detection patterns
SUBCATEGORY_PATTERNS: dict[str, dict[str, list[str]]] = {
    "security": {
        "exposed_files": ["env file", ".env", "exposed file", "config file", "backup file", "log file"],
        "directory_listing": ["directory listing", "index of", "open directory"],
        "admin_panels": ["admin panel", "admin page", "login page", "dashboard", "wp-admin", "phpmyadmin"],
        "sensitive_data": ["password", "credential", "private key", "api key", "secret key", "aws key"],

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 · search_dorks_skill/intent.py (reported line 52)May include surrounding context.

python
# Subcategory detection patterns
SUBCATEGORY_PATTERNS: dict[str, dict[str, list[str]]] = {
    "security": {
        "exposed_files": ["env file", ".env", "exposed file", "config file", "backup file", "log file"],
        "directory_listing": ["directory listing", "index of", "open directory"],
        "admin_panels": ["admin panel", "admin page", "login page", "dashboard", "wp-admin", "phpmyadmin"],
        "sensitive_data": ["password", "credential", "private key", "api key", "secret key", "aws key"],

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 · search_dorks_skill/skill.py (reported line 38)May include surrounding context.

python
Usage:
        skill = SearchSkill(searxng_url="http://localhost:8888")
        report = skill.search("find exposed .env files on example.com")
        print(report.to_context())
    """

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The example initializes the skill against an external SearXNG endpoint and later submits user-provided queries without any notice that search terms will be transmitted over the network. In a security-research context, queries may contain sensitive targets, investigation topics, or internal terms, so silent transmission can leak confidential intent or data to the configured service and its upstream engines.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

No manifest is available, so the skill's stated purpose is unknown. In that context, this usage example demonstrates targeted reconnaissance features such as direct dork queries, finding public API documentation on a target domain, building domain-scoped searches for 'confidential' PDFs, and competitor SEO analysis, which are materially more sensitive than generic search examples and are not justified by any declared purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

In the OSINT branch, the analyzer explicitly boosts results containing terms like "email", "phone", "linkedin", "profile", and "bio", which signals handling or prioritization of potentially sensitive personal data. This code provides no user-facing warning, confirmation, or explanatory disclosure in the file about privacy implications of surfacing personal-data-oriented results.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The client defaults to http://localhost:8888, so search queries are sent unencrypted unless the caller overrides the URL. Even on localhost, this can expose sensitive search terms through local proxies, container/network misconfiguration, SSH port forwards, or deployment changes where the host is no longer truly local, and there is no user-facing warning about that disclosure risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file contains extensive security and OSINT-oriented search logic but no visible warning, consent flow, policy text, or restriction mechanism for sensitive searches. That omission makes misuse more likely because high-risk query generation is presented as ordinary functionality without user-facing friction or safety boundaries.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The OSINT templates support reconnaissance of companies, domains, employees, IPs, and contact information, including tracking-oriented lookups across LinkedIn, Shodan, Censys, and breach-related terms. In a generic skill with no built-in authorization, minimization, or purpose limitation, this increases the risk of privacy-invasive profiling and target development.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code logs parsed intent, subcategory, confidence, and extracted entities derived from the user's query. In a security-search skill, those entities may contain domains, filenames, credentials-related terms, internal targets, or investigation subjects, which can be exposed through logs to operators or other systems that aggregate logging data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill sends arbitrary user queries directly to a configurable SearXNG endpoint, and the intended use includes potentially sensitive security-search terms such as exposed secrets or target-specific reconnaissance. If the SearXNG instance is remote, untrusted, or misconfigured, those queries can disclose user intent, target names, or sensitive investigation data to third parties without any explicit consent or warning at this interface layer.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified as httpx>=0.27.0, which permits any newer release to be installed. This makes builds non-reproducible and can unexpectedly introduce vulnerable or incompatible versions through future upstream changes or supply-chain compromise. In this context, the file is only a dependency manifest, so the issue is real but lower severity than an actively exploitable code flaw.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
httpx>=0.27.0

Unverifiable Dependency: httpx has 2 known advisory(ies) (CVE-2021-41945 (Improper Input Validation in httpx); CVE-2021-41945 (Encode OSS httpx <=1.0.0.beta0 is affected by improper input validation in `http)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding

The manifest references httpx without pinning to a specific reviewed version, and known advisories exist for some httpx releases. Because the version range is open-ended, it is impossible to verify from this file alone whether deployments will avoid affected versions, creating supply-chain uncertainty and potentially allowing installation of a vulnerable release in some environments.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The inline comment claims a behavior framed around preferring results with contact or personal-data indicators, which reads as though the analyzer is performing a stronger OSINT-specific capability. In reality, the code merely checks for a few keywords in already-supplied title/snippet text and adds a small score bonus; the comment overstates the operational behavior of the code.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
70% confidence
Finding

The configuration contains a dedicated "language" category and engine/operator support entries such as Bing and Yandex language selectors, but there is no natural-language indication that language or locale selection is optional or user-controlled. This can create a policy concern if the skill implicitly steers queries toward specific language settings without explicit user choice or documented regional justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The code explicitly maps natural-language phrases like "in english", "in spanish", and others to forced language codes. While it reacts to user phrasing rather than unconditionally forcing one locale, this is still the only natural-language locale behavior present and there is no accompanying comment or policy text clarifying user choice or broader locale handling.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.