T09 · Insecure Skill Coding Practices
- Location
SKILL.md:303- Finding
Raw AI and MCP telemetry may disclose sensitive data to an external analytics service
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:309-310, 335-336, 361-362, 493-494, 505-506;references/api-reference.md:54-76, 204-229, 243-268;references/python-sdk.md:260-267, 306-320, 381-388;references/typescript-sdk.md:334-341, 350-358, 427-434, 570-578
Vulnerability Type: Sensitive data exposure through excessive telemetry collection
Risk Level: MediumThe Skill intentionally sends analytics data to
https://api.agnost.ai. Although network communication is necessary for its declared hosted analytics functionality, the recommended configurations enable collection of raw inputs and outputs. Examples also transmit user identifiers, email addresses, prompts, model responses, tool arguments, tool results, metadata, and exception strings.Representative vulnerable configuration from
SKILL.md:303-311:python track(mcp, "your-org-id", config( endpoint="https://api.agnost.ai", disable_input=False, # Track input arguments disable_output=False # Track output results ))Equivalent TypeScript configuration from
SKILL.md:331-337:typescript trackMCP(server, "your-org-id", { endpoint: "https://api.agnost.ai", disableInput: false, disableOutput: false });Direct transmission example from
references/api-reference.md:204-229:python import requests import json BASE_URL = "https://api.agnost.ai/api/v1" ORG_ID = "your-org-id" headers = { "Content-Type": "application/json", "X-Org-Id": ORG_ID } requests.post( f"{BASE_URL}/capture-session", headers=headers, json={ "session_id": "sess_123", "client_config": "my-app", "user_data": {"user_id": "user_456"} } ) response = requests.post( f"{BASE_URL}/capture-event", headers=headers, json={ "session_id": "sess_123", "primitive_type": "tool", "primitive_name": "search", "l ...[truncated 3735 chars]- Remediation
View remediation
Remediation Suggestions
-
Make content collection privacy-preserving by default:
- Set
disableInputanddisableOutputtotrue. - Set Python equivalents
disable_inputanddisable_outputtoTrue. - Require explicit, documented opt-in before collecting raw content.
- Set
-
Use a strict telemetry allowlist:
- Prefer primitive name, latency, success status, coarse token counts, and non-identifying application version.
- Reject arbitrary metadata dictionaries unless keys and value types have been reviewed.
- Do not collect authorization headers, cookies, environment variables, request bodies, or database results.
-
Add a mandatory redaction layer before telemetry is queued:
- Detect API keys, bearer tokens, private keys, passwords, email addresses, and regulated identifiers.
- Replace stable user identifiers with scoped pseudonymous identifiers.
- Truncate oversized values and reject unsupported structured content.
-
Do not send raw exceptions. Emit a stable error category or sanitized error code instead.
-
Require user and organizational consent where applicable. Document data ownership, retention, deletion, regional processing, subprocessors, and access controls.
-
Separate development and production configurations. Keep raw-content diagnostics disabled in production and ensure debug logging cannot reproduce event contents.
-
Update all examples to demonstrate privacy-preserving settings first, with raw capture shown only as an explicitly risky optional mode.
-
