Back to skill

Security audit

ip-lookup

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward IP and hostname lookup tool, though users should know it sends lookup targets to public services and one geolocation request uses unencrypted HTTP.

Install only if you are comfortable sending queried IPs or hostnames to public lookup providers. Avoid using it for confidential internal hosts or sensitive customer investigations unless that disclosure is acceptable, and prefer changing the geolocation provider to HTTPS before relying on results for security decisions.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ip_lookup.py:98
Finding
Geolocation Target and Results Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ip_lookup.py`, lines 98-106 **Vulnerability Type**: Plaintext transmission and unauthenticated network response **Risk Level**: Medium **Classification**: T09: Insecure Skill Coding Practices ### Vulnerable Code ```python def fetch_geo(ip: str) -> dict: """ip-api.com geolocation + ASN. Falls back to ipwho.is.""" fields = ("status,message,country,countryCode,regionName,city,zip," "lat,lon,timezone,isp,org,as,asname,mobile,proxy,hosting,query") data = fetch(f"http://ip-api.com/json/{ip}", params={"fields": fields}) if data and data.get("status") == "success": return {"_source": "ip-api.com", **data} data2 = fetch(f"https://ipwho.is/{ip}") ``` ### Technical Analysis The primary geolocation request uses `http://ip-api.com` rather than an HTTPS endpoint. Consequently, neither the confidentiality of the requested IP address nor the authenticity and integrity of the returned geolocation data is protected by TLS. A passive network observer can identify which IP addresses the user is investigating. An active on-path attacker—such as an operator of a malicious wireless access point, compromised gateway, or hostile network intermediary—can intercept the request and return attacker-controlled JSON. The generic `fetch()` function accepts and parses any syntactically valid JSON response. `fetch_geo()` only verifies that the response contains `"status": "success"` before treating all remaining fields as trusted geolocation intelligence. An attacker can therefore forge fields such as country, organization, ASN, ISP, proxy status, and hosting status. The HTTPS fallback does not mitigate this issue when an attacker supplies a valid-looking successful response to the initial HTTP request, because the fallback is only used when the first response fails or reports an unsuccessful status. ### Attack Path 1. A user invokes the Skill to investigate an IP address or hostn ...[truncated 1316 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the plaintext endpoint with a geolocation provider that supports HTTPS: ```python data = fetch(f"https://<trusted-geolocation-provider>/{ip}", params={"fields": fields}) ``` 2. If the selected provider does not offer HTTPS under the applicable service tier, do not silently use its HTTP endpoint. Use the existing HTTPS `ipwho.is` service as the primary provider or select another HTTPS-capable service. 3. If plaintext access must be retained for compatibility, disable it by default and require an explicit, clearly documented command-line opt-in that warns users about target disclosure and response manipulation. 4. Enforce HTTPS centrally in `fetch()` so future callers cannot accidentally introduce plaintext requests: ```python def fetch(url: str, params: dict | None = None, headers: dict | None = None, timeout: int = 8) -> dict | None: parsed = urllib.parse.urlparse(url) if parsed.scheme != "https": raise ValueError("Refusing non-HTTPS network request") # Continue constructing and sending the request. ``` 5. Retain strict request timeouts and add response-size limits and schema/type validation. Schema validation will reduce malformed-data risks, although it cannot replace TLS for server authentication and response integrity. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger list and description are broad enough to match generic requests like 'look up IP' or 'check if IP is malicious' without clearly constraining when this skill should activate. That can cause the agent to invoke the skill unexpectedly and send user-supplied indicators to external services, increasing privacy and data-handling risk beyond the user’s likely intent.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill documentation describes multiple live lookups against third-party services but does not clearly warn that queried IPs and hostnames will be transmitted to external providers. This is dangerous because users may submit sensitive internal hostnames, customer infrastructure details, or investigative targets without realizing those indicators are disclosed to outside services and potentially logged.

External Transmission

Medium
Category
Data Exfiltration
Content
def fetch_abuse(ip: str, api_key: str) -> dict:
    """AbuseIPDB reputation check (90-day window)."""
    data = fetch(
        "https://api.abuseipdb.com/api/v2/check",
        params={"ipAddress": ip, "maxAgeInDays": "90"},
        headers={"Key": api_key, "Accept": "application/json"},
    )
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.