T09 · Insecure Skill Coding Practices
- Location
config.json:12- Finding
Plaintext WeChat Secret Storage and Exposure in Request URLs
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill does what it says, but it asks users to expose WeChat credentials and automatically uploads local presentation content to WeChat without a clear confirmation step.
Review before installing. Do not paste real WeChat secrets into chat or commit them in config.json; use a secret manager or environment variables and rotate any secret already shared. Only run this on PPT files you are comfortable uploading to WeChat, and add a manual review/confirmation step before network upload or draft creation.
config.json:12Plaintext WeChat Secret Storage and Exposure in Request URLs
The README instructs users to provide WeChat app credentials but gives no warning about secret handling, storage, logging, or safer input channels. This creates a real risk of credential exposure in chat history, agent logs, transcripts, or downstream tooling, especially because the documentation normalizes sharing secrets directly with the skill.
The markdown describes usage only through a free-form example prompt and does not define specific trigger phrases, boundaries, or negative examples. This can make activation ambiguous and increase the chance of unintended invocation from ordinary requests about generating images or publishing content.
The example prompt explicitly tells the user to paste wechat_appid and wechat_appsecret into natural-language input. That is dangerous because conversational interfaces are commonly logged, retained, or exposed to operators and other components, turning the documentation into an inducement for secret disclosure.
The documentation states that users need to provide their WeChat credentials, establishing an unnecessary sensitive data collection pattern without guidance on secure handling. In the context of an agent skill, this increases the chance that secrets are passed through unsafe channels or persisted in configs, prompts, or logs.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
print("正在转换 PPT → PDF")
subprocess.run(cmd, check=True)
pdf_path = output_dir / (ppt_path.stem + ".pdf")
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
print("正在转换 PPT → PDF")
subprocess.run(cmd, check=True)
pdf_path = output_dir / (ppt_path.stem + ".pdf")
The script is capable of automatically uploading local images and creating WeChat drafts, which causes external transmission of local content and use of stored platform credentials. In an agent-skill context with no documented consent, approval, or scope controls, this expands the blast radius because local files can be published to a third-party service without an explicit user checkpoint.
The code sends app credentials and local file contents to WeChat APIs without any user-facing disclosure, consent flow, or runtime warning. In an automation/agent setting, silent exfiltration of presentation-derived images and credential use is risky because users may not realize external transmission is occurring.
This API call sends application credentials to obtain an access token from WeChat. Although normal for the feature, it is security-sensitive in a skill context because it initiates third-party access using stored secrets without any explicit user approval or disclosure in the workflow.
# =============================
def get_access_token(appid, secret):
url = f'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}'
r = requests.get(url).json()
This endpoint uploads a local image file externally as permanent WeChat material, which is a direct data-transfer action. If the working directory contains sensitive presentation content, this can expose local data to a third party, especially dangerous when performed automatically inside an agent workflow.
def upload_permanent_image(access_token, file_path):
url = f'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={access_token}&type=image'
with open(file_path, 'rb') as f:
This API call uploads local images to WeChat to obtain externally hosted URLs, again transmitting presentation-derived content off the machine. The code performs this automatically for all pages after the cover, making unintended disclosure more likely if inputs are confidential or if the skill is triggered unexpectedly.
def upload_image_get_url(access_token, file_path):
url = f'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={access_token}'
with open(file_path, 'rb') as f:
This request transmits article content and metadata to an external WeChat endpoint, potentially publishing derived local data to a third-party platform. In an agent skill, undisclosed outbound transmission is security-relevant because it can move sensitive presentation content off-host without a separate approval boundary.
data = {"articles": [article]}
r = requests.post(
"https://api.weixin.qq.com/cgi-bin/draft/add",
params={"access_token": access_token},
data=json.dumps(data, ensure_ascii=False).encode("utf-8"),
This is the same draft-creation transmission path as the prior finding, identified at the concrete URL line. It sends generated article content to WeChat, which is security-relevant because it externalizes local content in an automated manner without user-facing safeguards.
data = {"articles": [article]}
r = requests.post(
"https://api.weixin.qq.com/cgi-bin/draft/add",
params={"access_token": access_token},
data=json.dumps(data, ensure_ascii=False).encode("utf-8"),
headers={"Content-Type": "application/json"}
This is a manifest-style JSON file, but it provides only operational configuration values and no explicit trigger phrases, activation boundaries, or exclusion conditions. For manifest files, missing specificity around how and when the skill should activate can lead to ambiguous or unintended invocation behavior.
The filename value includes Chinese text, which suggests the skill may be oriented toward a specific language or locale, but this file does not indicate any user opt-in or documented locale constraint. Under the policy rule, forcing or assuming a language without clear user choice can be a natural-language policy concern.
compress_image modifies files in place by reopening and saving them back to the same path, which is a file write that changes generated assets irreversibly. The code does not provide a warning, confirmation, or comment explaining that image quality will be reduced and the original file contents replaced.
The section header '发布微信草稿' indicates publishing a WeChat draft, but the implementation calls the draft creation endpoint '/cgi-bin/draft/add' and never invokes a publish action. This is an active documentation-to-code mismatch about the operation's actual effect.
No suspicious patterns detected.