Back to skill

Security audit

meta_ad

Security checks for vulnerabilities and agentic risk

Overview

This skill appears purpose-aligned for Meta ad automation, but it handles high-impact ad-account credentials in an unsafe plaintext way that users should review before installing.

Install only if you are comfortable giving this skill a Meta access token capable of managing ads. Use a least-privilege token, avoid entering credentials while screen sharing or recording, do not provide the optional App Secret unless truly needed, and delete or protect ~/.workbuddy/meta_ads_config.json after use. Review all generated campaigns in Meta Ads Manager before activating them.

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

Warning
Location
scripts/config_manager.py:11
Finding
Plaintext Storage and Visible Entry of Meta Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/config_manager.py:11-36` and `scripts/config_manager.py:69-81` **Vulnerability Type**: Plaintext sensitive-data storage and insecure secret input **Risk Level**: Medium ### Vulnerable Code ```python CONFIG_FILE = Path.home() / ".workbuddy" / "meta_ads_config.json" def get_config(): """读取配置""" if CONFIG_FILE.exists(): with open(CONFIG_FILE, 'r') as f: return json.load(f) return {} def save_config(config): """保存配置""" CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True) with open(CONFIG_FILE, 'w') as f: json.dump(config, f, indent=2) def init_config(access_token, ad_account_id, app_id=None, app_secret=None): """初始化配置""" config = { "access_token": access_token, "ad_account_id": ad_account_id, "app_id": app_id, "app_secret": app_secret, "api_version": "v18.0" } save_config(config) print(f"✅ 配置已保存到: {CONFIG_FILE}") return config ``` ```python if __name__ == "__main__": # 命令行交互式配置 print("=== Meta Ads API 配置 ===") print("請提供以下信息(這些信息將保存在本地配置文件中):\n") access_token = input("Access Token: ").strip() ad_account_id = input("廣告賬戶 ID (如: act_123456789): ").strip() app_id = input("App ID (可選): ").strip() or None app_secret = input("App Secret (可選): ").strip() or None if not access_token or not ad_account_id: print("❌ Access Token 和廣告賬戶 ID 是必填項") exit(1) init_config(access_token, ad_account_id, app_id, app_secret) ``` ### Technical Analysis The configuration manager serializes the Meta access token and optional App Secret directly into an unencrypted JSON file at a predictable location under the user's home directory. It does not explicitly enforce restrictive permissions on either the configuration file or its parent directory. Their effective permissions therefore depend on the process umask and any pre-existing directory ...[truncated 2773 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Stop collecting the unused App Secret** - Remove the `app_secret` prompt, function parameter, and configuration field unless a concrete implemented operation requires it. - Apply data minimization by retaining only the access token, ad-account ID, and API version needed by the current workflow. 2. **Use protected secret input** - Replace `input()` with `getpass.getpass()` for the access token and any future secret values. - Avoid printing, logging, or including credentials in exception messages. 3. **Use a dedicated credential store** - Prefer the operating system's credential manager, such as macOS Keychain, Windows Credential Manager, or a Linux Secret Service implementation. - For automated environments, use a managed secrets service or protected environment-variable injection rather than a repository or general-purpose JSON file. 4. **Enforce restrictive permissions if file storage is unavoidable** - Ensure the parent directory has mode `0700`. - Create the credential file atomically with mode `0600`. - Reject or repair an existing configuration file whose ownership or permissions are unsafe. - Avoid relying solely on the process umask. 5. **Minimize token privileges** - Request only the Meta permissions needed for the requested advertising operations. - Use separate development and production tokens. - Rotate tokens regularly and immediately revoke any token suspected of exposure. 6. **Document credential handling** - Clearly disclose where credentials are stored, how they are protected, and how users can delete or rotate them. - Warn users not to enter secrets during screen sharing or in recorded terminal sessions. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The description claims a streamlined workflow that handles campaign setup, audience targeting, media upload, and ad creation. This code chunk only supports creating an ad from a provided adset_id and creative object, plus helper logic for assembling creative payloads and listing CTA options. It assumes prerequisites already exist, such as an ad set, page, and uploaded image/video identifiers. There is no logic for creating campaigns, defining audiences/targeting, or uploading media assets. Therefore, the declared description overstates the implemented capabilities of this code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description promises a streamlined workflow for creating Meta ads programmatically, including campaign setup, targeting, media upload, and ad creation. However, the supplied code only defines generic GET/POST request helpers and concrete functions for reading ad account information and listing campaigns, plus token validation. Although a generic POST helper exists, there is no implemented logic for creating campaigns, ad sets, creatives, uploads, or ads. Therefore the actual code materially underdelivers relative to the declared primary purpose, making this a description/behavior mismatch.

Credential Access

High
Category
Privilege Escalation
Content
```

需要的信息:
- **Access Token**: Meta API 访问令牌
- **Ad Account ID**: 广告账户 ID (格式: act_123456789)
- **App ID** (可选): 应用 ID
- **App Secret** (可选): 应用密钥
Confidence
84% confidence
Finding
This section explicitly lists sensitive items to provide to the skill, including Access Token and App Secret, without any safeguards or warnings about secure input and storage. In the context of an ad-automation skill with network access, exposed credentials could enable unauthorized campaign management, data access, and financial abuse of the linked ad account.

Credential Access

High
Category
Privilege Escalation
Content
## 认证

所有请求需要 Access Token:

```
Authorization: Bearer {ACCESS_TOKEN}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""
Meta Ads Creator - 配置管理模块
管理 Access Token、广告账户 ID 等配置
"""

import json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""
Meta Ads Creator - 配置管理模块
管理 Access Token、广告账户 ID 等配置
"""

import json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""
Meta Ads Creator - 配置管理模块
管理 Access Token、广告账户 ID 等配置
"""

import json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""
Meta Ads Creator - 配置管理模块
管理 Access Token、广告账户 ID 等配置
"""

import json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""
Meta Ads Creator - 配置管理模块
管理 Access Token、广告账户 ID 等配置
"""

import json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""
Meta Ads Creator - 配置管理模块
管理 Access Token、广告账户 ID 等配置
"""

import json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tainted flow: 'files' from open (line 75, file read) → requests.post (network output)

High
Category
Data Flow
Content
if name:
        data['name'] = name
    
    response = requests.post(url, files=files, data=data)
    response.raise_for_status()
    result = response.json()
Confidence
80% confidence
Finding
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Tainted flow: 'files' from open (line 75, file read) → requests.post (network output)

High
Category
Data Flow
Content
if name:
        data['name'] = name
    
    response = requests.post(url, files=files, data=data)
    response.raise_for_status()
    result = response.json()
Confidence
80% confidence
Finding
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Lp3

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding
The skill documents and invokes scripts that read local files, write configuration, and make network calls to the Meta Marketing API, but it does not declare any explicit tool scope such as allowed-tools or permissions. This increases the risk of overbroad execution in environments that rely on manifest scoping, because users and platforms cannot easily tell what capabilities the skill expects before running it.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The documentation instructs users to handle highly sensitive credentials including Meta access tokens and app secrets, but it does not warn against exposing them in logs, examples, shared config files, or source control. In a skill centered on API automation, missing credential-handling guidance materially raises the chance of accidental token leakage and subsequent account or ad-spend abuse.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The documentation explicitly recommends passing the access token as a URL query parameter without any warning. Tokens in URLs are commonly exposed via logs, browser history, reverse proxies, analytics systems, and referrer leakage, which can lead to unauthorized access to the Meta ad account and campaign management APIs.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
User-facing docstrings, prompts, and status messages are written in Chinese throughout the file, which imposes a specific language experience. There is no indication that language is configurable or that the skill is intentionally limited to a Chinese-speaking context.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code writes highly sensitive secrets including the Meta access token and optional app secret to a local JSON file in plaintext under the user's home directory. Any other local user, process, backup system, or malware with access to that file can recover those credentials and use them to access or abuse the advertising account.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module docstrings, CLI usage text, and user-facing output are entirely in Chinese, which imposes a specific language on users. The file does not indicate that this is a region-specific tool or provide any opt-in or alternative language support.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
SQP-3 applies to all file types and covers language or locale policy violations. This file forces a specific language for docstrings and user-facing CLI output without offering an alternative or documenting that the tool is intentionally region/language-specific.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This file’s user-facing natural language, including the module description, argument help, usage output, and status messages, is exclusively Chinese. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified, which is not present here.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code file contains natural-language strings, docstrings, and CLI usage text that force a specific language experience. Under the policy, language constraints should be optional or explicitly justified; here there is no opt-in, fallback, or explanation that the skill is intended only for Chinese-speaking users.

Missing User Warnings

Medium
Confidence
82% confidence
Finding
The module accesses a sensitive credential via get_access_token() and injects it into an Authorization header, but there is no warning, comment, or documentation in this file explaining that credentials are being consumed and sent to an external API. Under the rule, sensitive environment variables or credentials should have some form of disclosure unless already clearly documented elsewhere.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This code performs outbound requests to the Meta Graph API using account identifiers, access tokens, and request parameters, but the general GET/POST helpers provide no user-facing disclosure, confirmation, or explanatory comment about transmitting data to an external service. The later print statements only appear in the test harness and do not warn callers using these functions as a library.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code reads a local file and sends it, along with an access token, to a remote Meta API endpoint. While the module docstrings describe uploading, the upload functions themselves provide no user-facing warning, confirmation, or logging that local media and credentials are being transmitted over the network.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The video upload path sends a local video file and access token to the Meta API, but unlike the batch image path it has no user-facing print, prompt, or warning around this network action. This is a safety-relevant operation involving user data transmission and credential use.

Static analysis

No suspicious patterns detected.