Back to skill

Security audit

NanoGPT Web Search

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent NanoGPT web-search skill that sends user search requests to a disclosed external API, with ordinary integration risks but no evidence of hidden or malicious behavior.

Install only if you are comfortable sending search terms, domain filters, and your NanoGPT API key to NanoGPT's web API. Avoid putting secrets or confidential internal project names in queries, install dependencies in a virtual environment, and prefer a pinned requirements file if you harden this for production use.

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

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 22-25
Vulnerability Type: Supply-chain exposure through an unpinned dependency
Risk Level: Medium

Vulnerable Code

bash
Install the requests package:

```bash
pip install requests
text

### Technical Analysis

The installation instructions retrieve and install the latest version of `requests` available from pip's configured package index. No reviewed version, lock file, package hash, or trusted index is specified.

This does not demonstrate that the current `requests` package is malicious. However, it makes installation behavior dependent on mutable upstream package metadata and the user's pip configuration. A compromised upstream release, maliciously configured package index, or future package version could introduce unwanted code. Python package installation may execute package-controlled build logic under the privileges of the user running pip.

### Attack Path

1. An attacker compromises an upstream release or a package index used by the victim.
2. The victim follows the documented `pip install requests` instruction.
3. pip resolves a mutable, unreviewed package version from the configured index.
4. Package-controlled installation or build logic executes.
5. Malicious code gains the permissions of the account or environment running pip.

This path depends on an upstream or package-index compromise; the audited project does not itself supply a malicious dependency.

### Impact Assessment

Successful exploitation could execute arbitrary code with the privileges of the user performing installation. Depending on the environment, this may permit access to that user's files, environment variables, API credentials, virtual environment, and application data. If installation is performed by a privileged account, the impact could extend to system-level modification.
Remediation
View remediation

Remediation Suggestions

  • Pin requests to a reviewed version in a requirements or lock file.

  • Record and verify package hashes using pip install --require-hashes.

  • Install only from an explicitly trusted package index.

  • Prefer installation inside an isolated virtual environment under an unprivileged account.

  • Use automated dependency scanning and controlled update procedures to review future version changes.

  • Example hardened command:

    bash
    python3 -m pip install --require-hashes -r requirements.txt
    

T09 · Insecure Skill Coding Practices

Note
Location
format_output.py:12
Finding

Unsanitized Remote Content Written to Interactive Terminals

Content
View full analysis

Vulnerability Details

File Location: format_output.py, lines 12-38
Vulnerability Type: Terminal control-sequence injection
Risk Level: Low

Vulnerable Code

python
metadata = data.get("metadata", {})
print(f"\n🔍 Query: {metadata.get('query', 'N/A')}")
print(f"📡 Provider: {metadata.get('provider', 'N/A')} ({metadata.get('depth', 'standard')})")
print(f"💰 Cost: ${metadata.get('cost', 0)}")
print("-" * 60)

output_type = metadata.get("outputType", "searchResults")

if output_type == "searchResults":
    results = data.get("data", [])
    for i, r in enumerate(results, 1):
        if r.get("type") == "text":
            print(f"\n{i}. {r.get('title', 'No title')}")
            print(f"   🔗 {r.get('url', '')}")
            snippet = r.get("snippet", "")
            if snippet:
                print(f"   📝 {snippet[:200]}{'...' if len(snippet) > 200 else ''}")
        elif r.get("type") == "image":
            print(f"\n{i}. 🖼️ {r.get('title', 'Image')}")
            print(f"   🔗 {r.get('imageUrl', r.get('url', ''))}")

elif output_type == "sourcedAnswer":
    answer_data = data.get("data", {})
    print(f"\n{answer_data.get('answer', 'No answer')}\n")
    sources = answer_data.get("sources", [])
    if sources:
        print("📚 Sources:")
        for s in sources:
            print(f"   • {s.get('name', 'Unknown')}: {s.get('url', '')}")

Technical Analysis

Search metadata, titles, URLs, snippets, sourced answers, and source names originate from a remote API or indexed web content. These values are printed directly without filtering terminal control characters.

If an attacker can cause crafted content to appear in a result or influence an API response, ANSI, C0/C1, or OSC sequences may be interpreted by a compatible terminal rather than displayed as ordinary text. Truncating snippets to 200 characters does not neutralize these sequences.

Attack Path

...[truncated 1029 chars]

Remediation
View remediation

Remediation Suggestions

  • Sanitize every remote string before writing it to an interactive terminal.
  • Remove or visibly escape C0/C1 controls, ANSI CSI sequences, and OSC sequences.
  • Preserve only expected printable Unicode characters and safe whitespace such as spaces and line breaks.
  • Apply sanitization to metadata, titles, URLs, snippets, answers, image URLs, and source names.
  • Consider a plain or JSON output mode for automated consumers, while documenting that raw JSON must not be printed to a terminal without safe rendering.
  • Add tests containing escape characters such as ESC, BEL, CSI, and OSC to verify that they cannot affect terminal state.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · search.sh (reported line 112)May include surrounding context.

sh
${MAX_RESULTS:+--max-results "$MAX_RESULTS"})

# Make request
RESPONSE=$(curl -s -X POST "$API_URL" \
    -H "Content-Type: application/json" \
    -H "x-api-key: $NANOGPT_API_KEY" \
    -d "$JSON_PAYLOAD")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares capabilities that imply shell execution, network access, and environment-variable use, but it does not define an explicit tool scope such as permissions or allowed-tools. That makes the skill's effective authority less transparent to users and host systems, increasing the chance of unintended command execution or external access beyond what a caller expects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill performs web search through NanoGPT and third-party providers, which means user queries are transmitted to external services, yet the description does not clearly warn about that data flow. Users may unknowingly send sensitive prompts, internal project names, or confidential research topics off-platform, creating a privacy and data-handling risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · search.py (reported line 87)May include surrounding context.

python
"x-api-key": self.api_key,
        }
        
        response = requests.post(self.API_URL, headers=headers, json=payload)
        response.raise_for_status()
        
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

This curl call sends the full JSON payload and API key to an external service, creating a real data egress path from the local environment to a third party. In the context of a search skill this is expected behavior, but it is still a security-relevant issue because user-supplied queries may contain confidential information and the transmission happens silently.

Content

Scanner excerpt · search.sh (reported line 112)May include surrounding context.

sh
${MAX_RESULTS:+--max-results "$MAX_RESULTS"})

# Make request
RESPONSE=$(curl -s -X POST "$API_URL" \
    -H "Content-Type: application/json" \
    -H "x-api-key: $NANOGPT_API_KEY" \
    -d "$JSON_PAYLOAD")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script transmits the user's query, filters, and any included domain constraints to a third-party remote API, but provides no explicit runtime disclosure or consent prompt before sending that data. This is dangerous because users may assume a local search helper while unintentionally sending potentially sensitive research terms or internal domain names off-host.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.