T09 · Insecure Skill Coding Practices
Warning
- Location
- dingtalk.py:248
- Finding
- Agent-Callable Diagnostic Tool Discloses Part of the DingTalk Access Token## Vulnerability Details **File Location**: `dingtalk.py`, lines 248–263; tool registration at lines 312–315 **Vulnerability Type**: Exposure of authentication-token material through a public tool result **Risk Level**: Medium ### Vulnerable Code ```python async def dingtalk_get_token() -> Dict[str, Any]: """ Get DingTalk access token. Returns: Dictionary with token info """ client = _get_client() if not client: return {"success": False, "error": "DingTalk not configured"} token = client.get_token(force_refresh=True) if token: return {"success": True, "token": token[:20] + "..."} else: return {"success": False, "error": "Failed to get token"} ``` The function is exposed as an Agent-callable tool: ```python { "name": "dingtalk_get_token", "description": "Get DingTalk access token" } ``` ### Technical Analysis Access tokens are bearer credentials and should remain confined to the authentication and API-client layer. This function forces a token refresh and returns the first 20 characters of the resulting token to the calling Agent. The same tool is also declared publicly in `claw.json`. Token retrieval does not need to be exposed for the Skill's messaging or chat-management functionality because `send_message`, `create_chat`, and `list_chats` already acquire tokens internally. Returning a token prefix therefore exceeds the minimum information required by the declared operations. Although the implementation does not return the complete token, a substantial credential fragment can enter model context, tool-call traces, application logs, chat history, or monitoring systems. The fragment may facilitate token correlation or become useful when combined with another disclosure. There is no evidence in the reviewed code that the complete token can be reconstructed from this prefix alone. ### Attack Path 1. The Skill is ...[truncated 1541 chars]
- Remediation
- ## Remediation Suggestions 1. Remove `dingtalk_get_token` from the `TOOLS` list in `dingtalk.py` and from the tool entries in `claw.json`. 2. Keep token acquisition and refresh entirely private to `DingTalkClient`. 3. Never return a complete token or token substring in tool responses, exceptions, logs, traces, or diagnostic output. 4. If an authentication health check is required, expose only non-sensitive status information, such as: ```python async def dingtalk_check_auth() -> Dict[str, Any]: client = _get_client() if not client: return {"success": False, "configured": False} token = client.get_token(force_refresh=True) return { "success": token is not None, "configured": True } ``` 5. Review existing Agent traces, application logs, and conversation records for previously disclosed token prefixes. Restrict access to those records and rotate DingTalk credentials or invalidate active tokens if broader token leakage is suspected. 6. Apply output redaction for common credential fields such as `token`, `access_token`, `appsecret`, and `authorization` as a defense-in-depth measure.
