Back to skill

Security audit

Qq

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent QQ development guide with purpose-aligned API examples, but users should harden the sample credential handling and logging before production use.

Install only if you are building QQ integrations and treat the snippets as skeleton examples. Before production use, redact logs, avoid full event-payload printing, protect AppSecret and access tokens, prefer least-privilege intents, and follow the current official QQ documentation for required OAuth parameter handling.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:353
Finding
Sensitive credentials and OAuth tokens exposed in URL query strings<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 353–400 **Vulnerability Type**: Sensitive data exposure through URL query parameters **Risk Level**: Medium ### Complete Code Snippet ```python # Backend: exchange code for session def qq_miniapp_login(code): url = ( 'https://api.q.qq.com/sns/jscode2session' f'?appid={QQ_APPID}&secret={QQ_SECRET}&js_code={code}' '&grant_type=authorization_code' ) resp = requests.get(url).json() return resp # {"openid": "...", "session_key": "..."} ``` ```python # Exchange authorization code for access token def get_qq_access_token(code: str) -> dict: url = ( "https://graph.qq.com/oauth2.0/token" f"?grant_type=authorization_code&client_id={APP_ID}" f"&client_secret={APP_SECRET}&code={code}&redirect_uri={REDIRECT_URI}" "&fmt=json" ) return requests.get(url).json() # {"access_token": "...", "expires_in": 7776000, "refresh_token": "..."} # Obtain openid def get_openid(access_token: str) -> str: url = f"https://graph.qq.com/oauth2.0/me?access_token={access_token}&fmt=json" data = requests.get(url).json() return data["openid"] # Obtain user information def get_user_info(access_token: str, openid: str) -> dict: url = ( "https://graph.qq.com/user/get_user_info" f"?access_token={access_token}&oauth_consumer_key={APP_ID}&openid={openid}" ) return requests.get(url).json() ``` ### Technical Analysis The examples place an application secret, OAuth authorization code, and access tokens directly in URL query strings. Although the destinations are legitimate QQ HTTPS endpoints and these requests support the Skill's declared authentication functionality, query parameters are commonly recorded as part of the complete URL. Sensitive values may consequently appear in: - Application and reverse-proxy access logs - HTTP client debug logs - APM and distributed-tracing systems - Exception messag ...[truncated 1608 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use an HTTP authorization header or POST request body for secrets and tokens whenever the QQ endpoint supports those mechanisms. 2. If an endpoint requires query parameters, configure all application, proxy, APM, and HTTP client logging to redact: - `secret` - `client_secret` - `code` - `access_token` - `session_key` 3. Avoid manually interpolating credentials into URL strings. Use the HTTP client's parameter handling and a centralized redaction layer. 4. Prevent complete request URLs from being included in exceptions, tracing spans, analytics, or user-facing errors. 5. Restrict access to operational logs, minimize their retention period, and encrypt them at rest. 6. Store application secrets in a managed secret store or protected environment variable rather than source code or client-side configuration. 7. Rotate any credential known or suspected to have appeared in logs. 8. Add an explicit warning to the Skill explaining that these provider-defined query parameters are sensitive and must never be logged. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:134
Finding
Unredacted QQ event payloads written to application logs<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, line 134 **Vulnerability Type**: Sensitive information exposure through excessive logging **Risk Level**: Medium ### Complete Code Snippet ```python async def dispatch(self, event_type: str, data: dict): print(f"收到事件: {event_type}, 数据: {data}") ``` ### Technical Analysis The WebSocket dispatcher prints the complete event payload without filtering or redaction. Based on the documented intents, event data may include message content, private or C2C communications, user identifiers, group identifiers, channel metadata, membership events, and other personal information. Logging the entire payload is not necessary for routine event dispatch and exceeds the minimum data exposure required by the Skill's functionality. Standard output is frequently collected by container platforms, process supervisors, CI systems, or centralized log services, turning transient QQ event data into persistent records. ### Attack Path 1. The bot subscribes to QQ message, private-message, group, or membership events. 2. A user sends the bot a message containing private, personal, or otherwise sensitive content. 3. QQ delivers the content within the WebSocket event payload. 4. The `dispatch` method prints the entire payload to standard output. 5. Infrastructure collects and retains that output in local or centralized logs. 6. A user with log access, or an attacker who compromises the logging system, reads the message content and associated identifiers. ### Impact Assessment The issue may disclose private conversations, user and group identifiers, profile-related metadata, or operational event details. Exposure is limited to data received through the bot's enabled intents, but it may affect every user interacting with the bot while unrestricted logging is enabled. The vulnerability does not directly provide system-level privileges or code execution. However, leaked content may facilitate privacy violations, social ...[truncated 74 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove full-payload logging from production code. 2. Log only an allowlisted set of operational fields, such as the event type and a redacted correlation identifier. 3. Mask or omit message bodies, access credentials, user identifiers, group identifiers, and private-channel metadata. 4. Use structured logging with a centralized sanitization function instead of interpolating the complete dictionary. 5. Make detailed payload logging an explicit, temporary development-only option that is disabled by default. 6. Apply access controls, encryption, retention limits, and audit monitoring to all collected logs. 7. Document the privacy implications of enabling intents that receive private, C2C, group, or membership events. A safer pattern would be: ```python async def dispatch(self, event_type: str, data: dict): event_id = data.get("id") safe_event_id = event_id[-6:] if isinstance(event_id, str) else None logger.info("QQ event received", extra={ "event_type": event_type, "event_id_suffix": safe_event_id, }) ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (7)

External Transmission

Medium
Category
Data Exfiltration
Content
"appId": app_id,
        "clientSecret": app_secret
    }
    resp = requests.post(url, json=payload)
    data = resp.json()
    # access_token 有效期通常为 7200 秒
    return data["access_token"]
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
async def send_channel_message(channel_id: str, content: str, token: str,
                                msg_id: str = None, image: str = None):
    """向频道子频道发送消息"""
    url = f"https://api.sgroup.qq.com/channels/{channel_id}/messages"
    headers = {
        "Authorization": f"QQBot {token}",
        "Content-Type": "application/json"
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
async def send_channel_message(channel_id: str, content: str, token: str,
                                msg_id: str = None, image: str = None):
    """向频道子频道发送消息"""
    url = f"https://api.sgroup.qq.com/channels/{channel_id}/messages"
    headers = {
        "Authorization": f"QQBot {token}",
        "Content-Type": "application/json"
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
async def send_channel_message(channel_id: str, content: str, token: str,
                                msg_id: str = None, image: str = None):
    """向频道子频道发送消息"""
    url = f"https://api.sgroup.qq.com/channels/{channel_id}/messages"
    headers = {
        "Authorization": f"QQBot {token}",
        "Content-Type": "application/json"
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
async def send_channel_message(channel_id: str, content: str, token: str,
                                msg_id: str = None, image: str = None):
    """向频道子频道发送消息"""
    url = f"https://api.sgroup.qq.com/channels/{channel_id}/messages"
    headers = {
        "Authorization": f"QQBot {token}",
        "Content-Type": "application/json"
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
async def send_channel_message(channel_id: str, content: str, token: str,
                                msg_id: str = None, image: str = None):
    """向频道子频道发送消息"""
    url = f"https://api.sgroup.qq.com/channels/{channel_id}/messages"
    headers = {
        "Authorization": f"QQBot {token}",
        "Content-Type": "application/json"
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# 后端:code 换取 session
def qq_miniapp_login(code):
    url = (
        'https://api.q.qq.com/sns/jscode2session'
        f'?appid={QQ_APPID}&secret={QQ_SECRET}&js_code={code}'
        '&grant_type=authorization_code'
    )
Confidence
50% 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.