T09 · Insecure Skill Coding Practices
- Location
scripts/tinkclaw.py:42- Finding
Unvalidated API Base URL Can Expose Bearer Credentials and User Prompts
- Content
View full analysis
Vulnerability Details
File Location:
scripts/tinkclaw.py:20,scripts/tinkclaw.py:42-59, andscripts/tinkclaw.py:112-120
Vulnerability Type: Unvalidated destination for sensitive network requests
Risk Level: HighVulnerable Code
python API_BASE = os.getenv("TINKCLAW_API_URL", "https://tinkclaw.com")python def _request(path: str, method: str = "GET", body: dict | None = None, auth_key: str = "") -> dict: """Make an authenticated request to TinkClaw API.""" url = f"{API_BASE}{path}" headers = {"Content-Type": "application/json"} key = auth_key or API_KEY if key: headers["Authorization"] = f"Bearer {key}" data = json.dumps(body).encode() if body else None req = urllib.request.Request(url, data=data, headers=headers, method=method) try: with urllib.request.urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode())python def cmd_ask(question: str): """Ask the Brain API a natural language question.""" if not API_KEY: print("ERROR: Brain API requires an API key. Get one at https://tinkclaw.com/docs") sys.exit(1) data = _request("/v1/chat/completions", method="POST", body={ "model": "tinkclaw-1", "messages": [{"role": "user", "content": question}], "stream": False, })Technical Analysis
The destination of every API request is derived from the unrestricted
TINKCLAW_API_URLenvironment variable. The code does not validate the URL scheme, hostname, port, or resolved destination before sending the request._requestautomatically addsTINKCLAW_API_KEYas a bearer credential whenever that key is present. Consequently, changingTINKCLAW_API_URLredirects authenticated requests to an arbitrary destination. A plain HTTP URL is also accepted, allowing credentials and request bodies to travel without transport enc ...[truncated 2465 chars]- Remediation
View remediation
Remediation Suggestions
-
Pin the production API origin. Use a constant trusted origin such as
https://tinkclaw.comrather than accepting an unrestricted environment-provided URL. -
Strictly validate any required development override. Parse the URL and require:
- The
httpsscheme. - A hostname from an explicit allowlist.
- No embedded username or password.
- An approved port, normally
443. - No fragments or unexpected base paths.
- The
-
Make non-production overrides explicit. Gate custom endpoints behind a separate development-only option that is disabled by default, and never transmit production credentials when an override is active.
-
Apply endpoint-specific authentication. Add the bearer header only for endpoints that require authentication. Public Signal Market endpoints should be called without
TINKCLAW_API_KEY. -
Separate credential scopes. Ensure SmartChart and Signal Market requests use only their respective keys. Avoid fallback logic that silently applies the primary key to every request.
-
Protect free-form user content. Clearly notify users that
asktransmits their question to an external service, and advise them not to include secrets, account credentials, personal information, or confidential trading data. -
Prevent plaintext transmission. Reject all non-HTTPS destinations before constructing or sending a request.
-
Fail closed. If origin validation fails, terminate without sending the authorization header or request body, and return an error that does not reveal credential values.
-
