Back to skill

Security audit

aws-wechat-article-publish

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its WeChat publishing purpose, but it can send WeChat credentials and unpublished article content to an arbitrary configured API endpoint, so it needs review before installation.

Install only if you trust the repository and its configuration. Keep aws.env out of version control, prefer the default official WeChat API endpoint, avoid custom API_BASE/proxy values unless you fully trust the endpoint, and use draft mode plus an explicit account/article confirmation before any public publish.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish.py:862
Finding

Custom API Base Can Receive WeChat Credentials, Access Tokens, and Unpublished Content

Content
View full analysis
str: """获取 access_token(有效期 2 小时)。网络类失败会自动重试 1 次。""" url = ( f"{API_BASE}{API_PATH}/token?" f"grant_type=client_credential&appid={appid}&secret={appsecret}" ) data = _api_get(url) ``` ```python def _resolve_api_base(cfg: dict, slot: dict) -> str: """槽位 WECHAT_N_API_BASE 优先;为空时回退 config.yaml.wechat_api_base。""" slot_base = (slot.get("api_base") or "").strip() if slot_base: return _normalize_api_base(slot_base) cfg_base = str(cfg.get("wechat_api_base") or "").strip() if cfg_base: return _normalize_api_base(cfg_base) return "" def _init_api_base(): """优先用槽位 WECHAT_N_API_BASE;为空则回退 config.yaml.wechat_api_base。""" global API_BASE API_BASE = DEFAULT_API_BASE cfg = load_repo_config() env = _load_env_map() if not env: return slot_i = _slot_for_api_base(cfg, env) if slot_i is None: return slot = _active_slot_dict(cfg, env, slot_i) api_base = _resolve_api_base(cfg, slot) if not api_base: return API_BASE = api_base _info(f"API 端点: {API_BASE}{API_PATH}") def _get_token() -> str: _init_api_base() appid, appsecret = _get_credentials(_cli_account) return get_access_token(appid, appsecret) ``` The environment-check path also sends credentials to the configured endpoint: ```python api_base = _resolve_api_base(cfg, s) if api_base: API_BASE = api_base try: url = ( f"{API_BASE}{API_PATH}/token?" f"grant_type=client_credential&appid={s['appid']}&secret={s['appsecret']}" ) data = _api_get(url) ``` From `scrip ...[truncated 4192 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description centers on公众号发布 automation through WeChat APIs, including draft/publish actions and publish-time checks. The code chunk instead only manipulates local filesystem content: creating/updating article.yaml, reading local example/config YAML files, and optionally writing closing.md. This is a materially different primary purpose and lacks the core declared behaviors. While metadata preparation could support a larger publishing workflow, this chunk by itself is not a publishing tool and does not implement the advertised WeChat-facing capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description presents a tool whose main purpose is publishing WeChat Official Account content: sending to draft box or directly mass-publishing, uploading cover assets, checking before release, and toggling draft/published modes. The code chunk instead implements a standalone reader/query utility (getdraft.py). It loads config and credentials, obtains an access token, and calls WeChat read-oriented endpoints: draft/batchget, draft/get, freepublish/batchget, freepublish/get, and freepublish/getarticle. These support listing and inspecting drafts/published content and checking publication status, but there is no code for creating drafts, uploading materials, initiating publish/group send, scheduling, or validating content before publication. While the code is related to the same WeChat domain, its primary purpose is materially different from the declared publishing tool, so this is a mismatch.

Content

No source excerpt is available for this finding.

Tainted flow: 'req' from pathlib.Path.read_bytes (line 588, file read) → urllib.request.urlopen (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · scripts/publish.py (reported line 534)May include surrounding context.

python
for attempt in range(2):
        try:
            req = urllib.request.Request(url)
            with urllib.request.urlopen(req, timeout=t_req) as resp:
                return json.loads(resp.read())
        except Exception as e:
            last = e

Tainted flow: 'req' from pathlib.Path.read_bytes (line 588, file read) → urllib.request.urlopen (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · scripts/publish.py (reported line 555)May include surrounding context.

python
for attempt in range(2):
        try:
            req = urllib.request.Request(url)
            with urllib.request.urlopen(req, timeout=t_req) as resp:
                return json.loads(resp.read())
        except Exception as e:
            last = e

Tainted flow: 'req' from pathlib.Path.read_bytes (line 588, file read) → urllib.request.urlopen (network output)

High
Category
Data Flow
Confidence
83% confidence
Finding

The upload helper reads arbitrary local files and sends their bytes to a remote endpoint derived from WECHAT_N_API_BASE or config.yaml wechat_api_base. If an attacker can influence that endpoint or the file path arguments/content references, the tool can be abused to exfiltrate local article assets or other chosen files to a non-WeChat server; the skill context makes this more relevant because publishing workflows routinely handle local media and network egress.

Content

Scanner excerpt · scripts/publish.py (reported line 593)May include surrounding context.

python
data=body,
                headers={"Content-Type": f"multipart/form-data; boundary={boundary}"},
            )
            with urllib.request.urlopen(req, timeout=t_up) as resp:
                return json.loads(resp.read())
        except Exception as e:
            last = e

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/publish.py (reported line 950)May include surrounding context.

python
p_full.add_argument("--publish", action="store_true", help="创建草稿后立即发布")

    sub.add_parser("accounts", help="列出 config.yaml 中的微信槽位与名称")
    sub.add_parser("check", help="检查发布环境(.env 微信槽位等)")
    sub.add_parser(
        "check-wechat-env",
        help="按 config.yaml 槽位检查 aws.env 的 WECHAT_N_APPID/APPSECRET 是否已填写",

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/publish.py (reported line 1155)May include surrounding context.

python
else:
                print(f"[ERROR] 微信接口返回: {data}")
                issues.append(
                    f"槽位 {probe_i} 凭证或白名单有误(见 errcode/errmsg),请检查 .env"
                )
        except Exception as e:
            # 报错必须带上实际请求的 API 基址,且分清「端点配错了」和「网络抖动」。

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill explicitly describes file reads, writes to article metadata, and outbound network requests to WeChat APIs, but it declares no explicit tool scope or permissions boundary. That creates an authorization ambiguity: an agent runtime may grant broader-than-necessary file and network access, increasing the chance of unintended data exposure or unsafe execution against attacker-controlled paths or API bases.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases include very generic terms like “发布”, “提交”, “推送”, and similar everyday expressions, which can cause the skill to activate in contexts where the user did not intend to invoke external publishing. In this skill's context, accidental activation is more dangerous because execution can upload content and media to a third-party platform and may submit content for publication.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The guidance treats a bare user message like “发布” as sufficient to begin a workflow that enumerates drafts, selects content, inspects metadata, and proceeds toward publication. That broad activation condition can cause unintended access to repository content and increase the risk of accidental publication or disclosure, especially in multi-article or multi-account environments.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api-reference.md (reported line 14)May include surrounding context.

md
| 发布草稿 | POST | `/freepublish/submit` | 发布草稿(异步) |
| 查询发布状态 | POST | `/freepublish/get` | 查询发布结果 |

所有接口基础 URL:`https://api.weixin.qq.com/cgi-bin`

## 获取 access_token

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document instructs users to place WeChat AppID/AppSecret values in a repository-root aws.env file and only briefly says not to commit real secrets. That is insufficient secret-handling guidance because it normalizes storing long-lived credentials in a local file without stronger controls such as .gitignore, secret managers, rotation guidance, and least-privilege handling, increasing the risk of accidental disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The guide explicitly documents an immediate publish path (full ... --publish) without any warning that mass-send/publication is externally visible and may be difficult or impossible to fully undo once sent. In a skill specifically designed for WeChat public-account automation, this increases the likelihood of accidental public distribution, reputational damage, and unintended release of unreviewed or sensitive content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file documents use of WeChat credentials from aws.env and commands that create drafts or submit publication, which implies sending user content and authentication data to external network APIs. Under the markdown-specific warning rule, documentation should clearly disclose privacy or system-impacting behavior, but no warning is provided here about external transmission or publication effects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script reads WECHAT app credentials from aws.env and sends them in an HTTP request to obtain an access token, but there is no user-facing warning that sensitive credentials will be used and transmitted. Although the script logs the API endpoint, it does not disclose this credential-bearing network action in prompts or comments near the operation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The description is written only in Chinese and specifically targets WeChat public-account publishing, which implies a fixed language/locale context without any stated user opt-in or alternative. Under the policy for natural-language violations, forcing a specific language or locale should be documented as optional or justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file’s user-facing instructions are entirely in Chinese and do not indicate that language selection is optional or configurable. Under the policy rule for language or locale constraints, this can be considered a natural-language policy issue because it implicitly forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file's natural-language documentation and user-facing messages are entirely in Chinese, which effectively imposes a specific language on users without opt-in or explanation. The file does not state that the skill is region-specific or provide any language choice.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill is described as a WeChat article publishing tool, with broader write/review/layout/image-generation workflows explicitly delegated to a different skill. However, _run_checks() reads and reports on writing_model, image_model, WRITING_MODEL_API_KEY, and IMAGE_MODEL_API_KEY, which are capabilities for content generation rather than publishing. This goes beyond what is justified for a publish-only skill, even though it is framed as optional diagnostics.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.