T09 · Insecure Skill Coding Practices
- Location
metacognition.py:37- Finding
Unrestricted outbound transmission of extracted insight text
- Content
View full analysis
Vulnerability Details
File Location:
metacognition.py:37-86
Vulnerability Type: Unvalidated outbound network destination and sensitive-data disclosure
Risk Level: HighVulnerable Code
python EMBEDDINGS_URL = os.environ.get("EMBEDDINGS_URL", "http://localhost:11434/v1/embeddings") _embeddings_available = None # tri-state cache: None=untested, True, False def _test_embeddings() -> bool: """Check if the local embeddings endpoint is reachable.""" global _embeddings_available if _embeddings_available is not None: return _embeddings_available try: result = subprocess.run( ["curl", "-s", "-m", "2", "-X", "POST", EMBEDDINGS_URL, "-H", "Content-Type: application/json", "-d", json.dumps({"input": "test"})], capture_output=True, text=True, timeout=5, ) if result.returncode == 0 and result.stdout.strip(): resp = json.loads(result.stdout) if "data" in resp and resp["data"]: _embeddings_available = True return True except Exception: pass _embeddings_available = False return False def get_embedding(text: str) -> "list": """Get embedding vector from local endpoint. Returns None on failure.""" if not _test_embeddings(): return None try: result = subprocess.run( ["curl", "-s", "-m", "10", "-X", "POST", EMBEDDINGS_URL, "-H", "Content-Type: application/json", "-d", json.dumps({"input": text[:2000]})], capture_output=True, text=True, timeout=15, ) if result.returncode == 0: resp = json.loads(result.stdout) return resp["data"][0]["embedding"] except Exception: pass return NoneTechnical Analysis
EMBEDDINGS_URLis taken directly from the process environment and passed tocurlwithout validating its scheme, hostname, resolved address, or ...[truncated 1918 chars]- Remediation
View remediation
Remediation Suggestions
- Parse the endpoint using
urllib.parse.urlparse()and require an explicitly supported scheme. - Resolve the hostname and verify that every resulting address is loopback, including
127.0.0.0/8and::1. - Reject credentials, fragments, unexpected ports, malformed hosts, and non-loopback IP literals.
- Disable redirects or validate the destination again after every redirect.
- Replace
curlandsubprocesswith a bounded standard-library HTTP client, as promised by the documentation. - Apply strict request and response size limits and validate the complete response schema.
- Require explicit user consent before transmitting transcript-derived or note-derived content, even to a local service.
- Remove or correct inaccurate security claims in
README.mdandSKILL.md. - Add automated tests proving that remote hosts, DNS rebinding scenarios, and redirects to remote addresses are rejected.
- Parse the endpoint using
