Back to skill

Security audit

wacai-index-official-website-demand-change

Security checks for vulnerabilities and agentic risk

Overview

This skill openly automates code changes, git push, and WeCom notification, but it uses a hardcoded external webhook and can send repository metadata or arbitrary summary-file contents without a clear per-run consent boundary.

Install only if you trust the publisher and are willing for repository metadata and summaries to be sent to the embedded WeCom webhook. Before use, remove the hardcoded webhook, require your own webhook from a secret source, add explicit confirmation before git push and notification, restrict demand and summary files to the target repository, and review staged changes before committing.

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

Error
Location
scripts/push_wecom_push_notice.py:13
Finding
Hardcoded WeCom Webhook Secret Enables Uncontrolled Sensitive Data Transmission<![CDATA[ ## Vulnerability Details **File Location**: `scripts/push_wecom_push_notice.py:13`, `scripts/push_wecom_push_notice.py:42-48`, `scripts/push_wecom_push_notice.py:114-137`, `scripts/push_wecom_push_notice.py:146-168`; automatic invocation at `scripts/git_commit_and_push.sh:32-36` **Vulnerability Type**: Hardcoded secret and unrestricted outbound transmission **Risk Level**: High ### Vulnerable Code ```python DEFAULT_WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=0e41994e-9e62-4713-ad69-fddeaaba8e9a" ``` ```python def read_summary(args) -> str: if args.summary: return args.summary.strip() if args.summary_file: return Path(args.summary_file).read_text(encoding="utf-8").strip() if args.stdin: return sys.stdin.read().strip() return "" ``` ```python def build_content(project_dir: Path, branch: str, commit_ref: str, summary: str) -> str: commit_hash = run_git(project_dir, "rev-parse", "--short", commit_ref) commit_subject = run_git(project_dir, "show", "-s", "--format=%s", commit_ref) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") summary = summary.strip() if summary.strip() else summarize_from_diff(project_dir, commit_ref) return "\n".join([ f"时间:{timestamp}", f"项目:{project_dir}", f"分支:{branch}", f"提交:{commit_hash} {commit_subject}", "代码变动点:", summary, ]) def post_json(url: str, payload: dict) -> str: data = json.dumps(payload, ensure_ascii=False).encode("utf-8") req = urllib.request.Request( url, data=data, headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=20) as resp: return resp.read().decode("utf-8", errors="replace") ``` ```python parser.add_argument( "--webhook-url", default=os.environ.get("WECOM_WEBHOOK_URL", DEFAULT_WEBHOOK_URL), help="Override webhook URL" ) ``` ```python response ...[truncated 3024 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Immediately revoke and rotate the exposed WeCom webhook key. 2. Remove `DEFAULT_WEBHOOK_URL` and all webhook credentials from source control and repository history. 3. Require `WECOM_WEBHOOK_URL` to be supplied through an approved secret manager or protected runtime environment. Fail closed if it is absent. 4. Make outbound notification opt-in and show the destination and payload to the user before transmission. 5. Remove arbitrary `--summary-file` support where possible. Prefer a summary generated from validated Git metadata. 6. If summary files remain supported: - Resolve the path before reading it. - Require it to be a regular file. - Require it to remain within the target repository or a dedicated summary directory. - Reject symlinks, absolute external paths, and traversal outside the permitted directory. - Enforce a strict maximum size. 7. Redact secrets and omit absolute project paths, local usernames, and unnecessary internal filenames. 8. Send only the minimum information necessary, such as a short commit identifier and a user-approved summary. 9. Document the external destination, transmitted fields, retention implications, and failure behavior. 10. Add automated secret scanning and tests verifying that arbitrary local files cannot be included in notifications. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/save_product_demand.py:29
Finding
Unrestricted Demand Filename Allows Writes Outside the Target Project<![CDATA[ ## Vulnerability Details **File Location**: `scripts/save_product_demand.py:29-45`; related broad Git staging at `scripts/git_commit_and_push.sh:28-30` **Vulnerability Type**: Path traversal, arbitrary file overwrite, and unintended backup disclosure **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument('--project-dir', required=True, help='Target project directory') parser.add_argument('--demand-file-name', default='productdemand.md', help='Demand file name inside project dir') parser.add_argument('--stdin', action='store_true', help='Read demand content from stdin') parser.add_argument('--file', help='Read demand content from a file') args = parser.parse_args() project_dir = Path(args.project_dir).expanduser().resolve() demand_file = project_dir / args.demand_file_name content = read_content(args) if not content or not content.strip(): print('Demand content is empty.', file=sys.stderr) return 2 project_dir.mkdir(parents=True, exist_ok=True) backup = backup_if_exists(demand_file) normalized = content.rstrip() + '\n' demand_file.write_text(normalized, encoding='utf-8') ``` ```python def backup_if_exists(target: Path) -> Path | None: if not target.exists(): return None stamp = datetime.now().strftime('%Y-%m-%d-%H') backup = target.with_name(f'productdemand.backup.{stamp}.md') shutil.copy2(target, backup) return backup ``` ```bash git add -A git commit -m "$COMMIT_MSG" git push origin "$TARGET_BRANCH" ``` ### Technical Analysis The `--demand-file-name` argument is described as a filename inside the project directory, but the implementation does not enforce that boundary. With `pathlib`, joining `project_dir` to an absolute second path discards `project_dir`. A relative value containing `..` can also traverse outside the project. In addition, `write_text()` follows an existing symbolic link, allowing a destination that appears to be in the repository to resolve to an external file. The scr ...[truncated 2159 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the configurable demand filename if the workflow only requires `productdemand.md`. 2. If configurability is required, restrict the value to a simple basename: - Reject absolute paths. - Reject `.` and `..` path components. - Reject directory separators. - Permit only an explicit filename pattern or allowlist. 3. Resolve the destination and verify containment before writing: ```python project_dir = Path(args.project_dir).expanduser().resolve(strict=True) candidate = (project_dir / args.demand_file_name).resolve(strict=False) candidate.relative_to(project_dir) ``` Handle `ValueError` by refusing the operation. 4. Reject existing symlinks and verify that the final parent directory is inside the project. 5. Open files using safe no-follow semantics where supported, and write through a securely created temporary file followed by an atomic replacement. 6. Store backups outside the Git working tree in a permission-restricted directory, or explicitly exclude them from version control. 7. Replace `git add -A` with an explicit allowlist of intended changed files. Review the staged diff before committing. 8. Add tests covering absolute paths, traversal sequences, nested paths, symlink destinations, nonexistent project directories, and accidental backup staging. 9. Warn users that demand documents and backups may contain sensitive business information and require explicit approval before committing them. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
This variant of the mismatch is security-relevant because it notes undeclared outbound webhook behavior and support for reading git history/diffs beyond the narrow success-notification scenario. Hidden or underdisclosed network egress and repository metadata disclosure can leak sensitive project information, especially when users believe the skill only performs local requirement-change automation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This variant of the mismatch is security-relevant because it notes undeclared outbound webhook behavior and support for reading git history/diffs beyond the narrow success-notification scenario. Hidden or underdisclosed network egress and repository metadata disclosure can leak sensitive project information, especially when users believe the skill only performs local requirement-change automation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
This variant of the mismatch is security-relevant because it notes undeclared outbound webhook behavior and support for reading git history/diffs beyond the narrow success-notification scenario. Hidden or underdisclosed network egress and repository metadata disclosure can leak sensitive project information, especially when users believe the skill only performs local requirement-change automation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This variant of the mismatch is security-relevant because it notes undeclared outbound webhook behavior and support for reading git history/diffs beyond the narrow success-notification scenario. Hidden or underdisclosed network egress and repository metadata disclosure can leak sensitive project information, especially when users believe the skill only performs local requirement-change automation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This variant of the mismatch is security-relevant because it notes undeclared outbound webhook behavior and support for reading git history/diffs beyond the narrow success-notification scenario. Hidden or underdisclosed network egress and repository metadata disclosure can leak sensitive project information, especially when users believe the skill only performs local requirement-change automation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This variant of the mismatch is security-relevant because it notes undeclared outbound webhook behavior and support for reading git history/diffs beyond the narrow success-notification scenario. Hidden or underdisclosed network egress and repository metadata disclosure can leak sensitive project information, especially when users believe the skill only performs local requirement-change automation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill advertises and instructs execution of high-risk capabilities including shell access, file reads/writes, network egress, and environment use, but declares no explicit tool scope or permission boundaries. That makes it easier for an agent runtime to overgrant access and perform destructive repository changes or exfiltration-related actions without clear user-visible constraints.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill explicitly instructs automatic `git push` and outbound WeCom webhook notification, both of which are remote side effects, but it does not provide a strong user warning or require an explicit confirmation gate immediately before those actions. In this context, the skill targets arbitrary externally supplied project paths, making unintended code publication and metadata leakage materially more dangerous.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script performs `git push origin "$TARGET_BRANCH"` automatically after committing, with no interactive confirmation, dry-run, or explicit safeguard. In the context of a one-click automation skill that modifies code from pasted requirements, this can unintentionally publish incorrect, sensitive, or unsafe changes to a remote repository, increasing the risk of accidental data exposure or unauthorized deployment flow changes.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
After the push, the script forwards repository metadata such as project path, branch, commit reference, and optionally a summary file to an external notification script that triggers a WeCom webhook. In this skill's context, that creates an external data egress path without per-run disclosure or consent, and summary content may contain sensitive implementation details, internal paths, or change descriptions that should not be sent outside the local environment.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The script embeds a live WeCom webhook URL, creating a fixed outbound exfiltration path to an external service. In this skill's context, the tool automatically summarizes commit metadata, branch names, project paths, and file-change hints after code changes, so the hardcoded endpoint can leak internal development information without per-run trust decisions.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The combination of a hardcoded default webhook and optional environment-supplied credentialed endpoint means the script is designed to send data to external destinations without robust secret-handling or disclosure controls. Because the skill is intended for one-click project changes and push notifications, operators may trigger external data transfer implicitly, making this more dangerous than a simple standalone notifier.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run_git(project_dir: Path, *args: str) -> str:
    result = subprocess.run(
        ["git", *args],
        cwd=str(project_dir),
        check=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script automatically posts commit hashes, commit subjects, branch names, project directory paths, and inferred change summaries to an external WeCom webhook with no interactive warning or confirmation. In an automation skill that performs repository modification and push operations, this increases the danger because sensitive internal codebase details can be transmitted off-host as part of normal execution.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The script constructs commit messages using a fixed Chinese phrase, which imposes a specific language regardless of user preference or repository conventions. This is a natural-language policy concern because there is no opt-in, configuration, or explanation that the skill is intended only for a Chinese-language workflow.

Static analysis

No suspicious patterns detected.