Back to skill

Security audit

巨量广告自动化投放技能 - LemClaw Skills

Security checks for vulnerabilities and agentic risk

Overview

This is a legitimate-looking Ocean Engine ad automation skill, but it can affect live ad accounts and credentials without clear enough user controls.

Install only if you are comfortable giving this skill access to an Ocean Engine account that can create or modify ads. Use a test account first, avoid production tokens until you have added confirmation and dry-run controls, keep budgets capped, do not call save_config() unless credential storage is fixed, and install dependencies in an isolated environment.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (3)

T01 · Skill Instruction Hijacking

Error
Location
optimizer.py:362
Finding
Unconditional Commercial Content Injection into Generated Reports## Vulnerability Details **File Location**: `optimizer.py:362-369` **Vulnerability Type**: Forced output modification and commercial traffic diversion **Risk Level**: High ### Vulnerable Code ```python # 免责声明 report += """ --- **报告由 LemClaw 智能优化引擎自动生成** 建议仅供参考,请结合实际情况调整 按月付费使用请联系:business@lemclaw.com """ return report ``` ### Technical Analysis `OceanEngineOptimizer.generate_optimization_report()` unconditionally appends LemClaw branding and a commercial contact address to every generated optimization report. The caller cannot disable this behavior. The appended content is not required to calculate or communicate campaign performance. It modifies task output for advertising and traffic-diversion purposes. `main.py:141-149` subsequently prints this modified report and writes it to a local report file, allowing the injected promotion to propagate into stored reports and downstream systems. Promotional footers in the Markdown documentation are static content and do not independently instruct an Agent to repeat them. The executable mutation in `optimizer.py`, however, directly and consistently changes generated user-facing output. ### Attack Path 1. A user or integrated Agent requests an advertising optimization report. 2. The request reaches `OceanEngineOptimizer.generate_optimization_report()`. 3. The method retrieves advertising data and constructs the requested analysis. 4. Before returning, it unconditionally appends LemClaw branding and `business@lemclaw.com`. 5. `OceanEngineMain.optimize()` prints and saves the modified report. 6. If the report is redistributed or consumed by another system, the unrelated commercial content is redistributed as if it were part of the requested analysis. ### Impact Assessment This issue compromises output integrity rather than granting operating-system privileges. It can: - Insert unsolicited commercial material into every opti ...[truncated 473 chars]
Remediation
## Remediation Suggestions 1. Remove the commercial footer from `generate_optimization_report()`. 2. Keep support contacts and payment information in documentation rather than task-generated analytical output. 3. If attribution is contractually required, expose an explicit option such as: ```python def generate_optimization_report( self, account_id: str, period: str = "last_7d", include_attribution: bool = False ) -> str: ``` 4. Default attribution and commercial content to disabled. 5. Clearly separate optional metadata from the analytical report body. 6. Add tests verifying that generated reports do not contain undeclared links, email addresses, promotions, or fixed third-party content unless explicitly requested.

T09 · Insecure Skill Coding Practices

Warning
Location
auth.py:189
Finding
OAuth Tokens and Application Secrets Stored in a Plaintext Configuration File## Vulnerability Details **File Location**: `auth.py:189-205` **Vulnerability Type**: Plaintext sensitive-data storage **Risk Level**: Medium ### Vulnerable Code ```python def save_config(self) -> None: """保存配置到文件""" config_data = { "access_token": self.config.access_token, "refresh_token": self.config.refresh_token, "app_id": self.config.app_id, "app_secret": self.config.app_secret, "account_id": self.config.account_id, "test_mode": self.config.test_mode, "expires_at": self.config.expires_at.isoformat() if self.config.expires_at else None } with open("config.json", "w", encoding="utf-8") as f: json.dump(config_data, f, indent=2, ensure_ascii=False) ``` ### Technical Analysis The public `save_config()` method copies the OAuth access token, refresh token, application secret, application identifier, and account identifier into a predictable plaintext file named `config.json` in the current working directory. The file is created using default process permissions. Its actual mode therefore depends on the runtime umask and may permit access by other local users or processes. The implementation does not use an operating-system credential store, encryption, explicit restrictive permissions, atomic replacement, or a dedicated user-private configuration directory. The sensitive network transmissions in `auth.py:63-69` and `auth.py:103-109` are made over HTTPS to the configured Ocean Engine production or test endpoints and are necessary for the declared OAuth functionality. The security issue is the unnecessary plaintext persistence of those credentials, not their transmission to the declared service. ### Attack Path 1. OAuth credentials are loaded from environment variables into `OceanEngineAuth.config`. 2. An application, extension, or user invokes the public `save_confi ...[truncated 1272 chars]
Remediation
## Remediation Suggestions 1. Do not persist access tokens, refresh tokens, or application secrets by default. 2. Store credentials in an operating-system keyring, managed secret service, or platform-provided credential vault. 3. If file storage is unavoidable: - Use a user-specific private configuration directory. - Create the file with mode `0600`. - Write through a temporary private file and replace the destination atomically. - Avoid storing the application secret unless strictly necessary. - Encrypt stored values using a key that is not kept beside the configuration file. 4. Add `config.json` and equivalent secret files to version-control ignore rules. 5. Display an explicit warning and obtain user consent before persisting credentials. 6. Document token revocation and rotation procedures. 7. Add automated tests that verify restrictive permissions and ensure secrets are not emitted to logs or ordinary report files.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:2
Finding
Unpinned and Excessive Third-Party Dependency Installation## Vulnerability Details **File Location**: `requirements.txt:2-16` **Vulnerability Type**: Non-reproducible dependency resolution and excessive supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```text requests>=2.31.0 python-dotenv>=1.0.0 pydantic>=2.5.0 python-dateutil>=2.8.0 openpyxl>=3.1.0 pandas>=2.0.0 numpy>=1.24.0 asyncio-mqtt>=0.13.0 aiohttp>=3.8.0 schedule>=1.2.0 loguru>=0.7.0 rich>=13.6.0 click>=8.1.0 fastapi>=0.104.0 uvicorn>=0.24.0 ``` The installation instructions execute this dependency set directly: ```bash pip install -r requirements.txt ``` ### Technical Analysis All third-party packages are specified only with lower version bounds. As a result, installation can select future versions that were not reviewed with this Skill. No lock file, package hashes, upper bounds, or reproducible build mechanism is provided. The reviewed runtime directly uses only a subset of the declared dependencies. Packages such as FastAPI, Uvicorn, MQTT support, spreadsheet handling, CLI formatting libraries, and scheduling components are not required by the inspected execution paths. Installing unnecessary packages increases the number of upstream projects whose installation and runtime security affect the Skill. No typosquatted package name, custom package index, direct URL dependency, or currently confirmed malicious package was identified. The risk arises from unconstrained future resolution and unnecessary dependency breadth. ### Attack Path 1. A user follows the documented command `pip install -r requirements.txt`. 2. pip resolves the newest available releases satisfying the lower-bound constraints. 3. A future compromised, malicious, or incompatible release is selected without requiring any change to this Skill. 4. Package installation or import behavior executes with the privileges of the user installing or running the Skill. 5. The affected dependency may access local ...[truncated 763 chars]
Remediation
## Remediation Suggestions 1. Remove every dependency not required by an implemented runtime feature. 2. Pin reviewed versions exactly rather than using unrestricted lower bounds. 3. Generate a lock file with cryptographic hashes and require hash verification during installation. 4. Separate optional feature dependencies into explicit extras. 5. Install the Skill inside an isolated virtual environment with minimal operating-system privileges. 6. Use automated dependency auditing and update review before changing locked versions. 7. Document the approved Python version and supported dependency set. 8. Avoid installing server, scheduler, MQTT, spreadsheet, or presentation libraries unless the corresponding functionality is actually implemented and enabled.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (58)

Missing User Warnings

High
Confidence
95% confidence
Finding
Batch launch reads campaign IDs from a file and immediately launches all of them with launch_immediately=True, without any confirmation or preview. Because this operates on multiple campaigns at once, accidental or maliciously prepared input can cause large-scale unauthorized ad activation and rapid financial loss.

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding
Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The changelog describes '一键启动自动投放' and ROI-based budget reallocation as core features, but the surrounding documentation does not provide a prominent user-facing warning that these actions can directly spend money, modify live campaigns, or affect account state. In an ad-tech skill, automation that can launch campaigns or redistribute budget without explicit guardrails materially increases the risk of unintended spend and operational impact.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The report presents commands for creating ads and starting automated launches as a simple 'quick start' workflow, but it does not prominently warn that these actions can modify live advertising resources and trigger real spend. In an ad-automation skill, this omission is risky because users may run examples assuming they are informational or test-only, especially since the document also claims the project is production-ready and emphasizes ease of use.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The guide instructs users to export sensitive API credentials and immediately run code that uses them, but it does not include any warning about secure token storage, shell history exposure, least-privilege scoping, or the privacy/financial impact of misuse. In an advertising automation skill, leaked tokens could allow unauthorized access to ad accounts, campaign data, and budget-affecting actions, making this more dangerous than a generic API example.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README advertises autonomous ad launching, budget reallocation, bid optimization, and destructive actions such as deleting campaigns, but it does not prominently warn users that these features can directly spend money, alter live delivery, or remove production assets. In an ad-tech skill, unclear disclosure around financial and operational side effects increases the chance of accidental misuse, especially when examples encourage direct execution against production accounts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill advertises capabilities that imply access to environment variables, local files, and networked API calls, but it declares no explicit tool scope or permission boundaries. In an agent setting, this can cause overbroad authority to be granted implicitly, increasing the risk of accidental secret exposure, unintended file access, or unauthorized outbound requests.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill presents automated campaign launch, budget optimization, and bid adjustment workflows as straightforward actions without a prominent warning that they may affect live ad accounts and spend real money. In this context, the danger is elevated because the entire skill is designed to automate financially impactful operations, so a user or agent could trigger costly changes under the assumption they are only running a harmless demo.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This code performs outbound HTTP requests using authenticated headers and request bodies that can contain advertiser, campaign, ad group, creative, and reporting data, but the only disclosure is internal logging after the fact. There is no confirmation prompt or explicit user-facing warning in this file that the skill will send potentially sensitive account and advertising data to an external API.

External Transmission

Medium
Category
Data Exfiltration
Content
if method.upper() == "GET":
                response = requests.get(url, headers=headers, timeout=self.timeout)
            elif method.upper() == "POST":
                response = requests.post(url, headers=headers, json=data, timeout=self.timeout)
            elif method.upper() == "PUT":
                response = requests.put(url, headers=headers, json=data, timeout=self.timeout)
            elif method.upper() == "DELETE":
Confidence
80% 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
elif method.upper() == "POST":
                response = requests.post(url, headers=headers, json=data, timeout=self.timeout)
            elif method.upper() == "PUT":
                response = requests.put(url, headers=headers, json=data, timeout=self.timeout)
            elif method.upper() == "DELETE":
                response = requests.delete(url, headers=headers, json=data, timeout=self.timeout)
            else:
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The module exposes direct state-changing operations such as campaign, ad group, and creative creation or updates without any built-in guardrails, dry-run mode, or confirmation hooks. In an agent-skill context, this can enable unintended or unauthorized spend, campaign changes, or publication of creatives if higher-level caller controls are weak or bypassed.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The module serializes OAuth secrets including access tokens, refresh tokens, and the client secret into a local config.json file in plaintext. This expands the credential exposure surface beyond runtime memory and can lead to account compromise if the file is read by other local users, accidentally committed, included in logs/backups, or packaged with the skill.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The code writes sensitive credentials to config.json without any warning, prompt, or disclosure to the user. In a reusable agent skill, hidden credential persistence is risky because operators may not realize long-lived tokens and secrets are being stored on disk, increasing the chance of unintended disclosure through source control, artifacts, or shared environments.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code performs external state-changing ad operations—creating ad groups, creatives, and launching ads—immediately after a single method call, without any confirmation gate, dry-run mode, cost estimate, or explicit acknowledgement of financial impact. In an automation skill connected to a real ad account, this increases the risk of unintended spend, accidental campaign activation, or abuse if the method is triggered with unreviewed input.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The targeting configuration fixes location values to CN, which imposes a specific locale/region behavior on all runs. There is no user opt-in, configuration field, or documented justification indicating this is intentionally limited to China-specific campaigns.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The method is documented as "批量启动多个广告计划" and logs a batch launch, but the implementation defines a single async function and then passes a generator expression directly to asyncio.run, which does not execute the launches as described. This is an active mismatch between the documented intent and the actual code behavior.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The auto-launch path enables immediate ad campaign activation with no secondary confirmation, dry-run mode, or safety interlock. In an automation context tied to real ad accounts, a mistaken invocation can trigger unintended spend and operational impact immediately.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The function signature and logging suggest the caller can control the reporting period, but the implementation hardcodes start and end dates for the last 7 days. This actively diverges from the documented interface and user-facing intent conveyed by the parameter and CLI option.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module title and user-facing descriptions are written entirely in Chinese, and later report-generation strings are also hard-coded in Chinese, indicating the skill is designed to operate in a single language. There is no visible opt-in, locale selection, or justification that this is a region-specific language constraint.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The creative-suggestion branch checks campaign["metrics"].get("issues", []), but issues are stored at the top level of each campaign analysis object, not inside metrics. As a result, this condition is effectively always false and the optimizer silently skips campaigns with multiple detected issues, undermining optimization decisions and potentially causing continued wasted ad spend or missed remediation.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This code file contains user-facing natural-language text entirely in Chinese, beginning with the module description. The file does not indicate that the skill is region-specific or that users can opt into this locale, which can violate language/locale policy for skills expected to support user choice.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The test runner prints status messages such as test headings and results exclusively in Chinese. Because these are user-visible outputs and there is no language selection mechanism or justification for a Chinese-only locale, this is a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
文档内容完全以中文编写,未向用户提供可选语言版本,也没有说明该技能仅面向特定中文使用场景。根据该规则,强制单一语言而无用户选择或合理限定,属于自然语言层面的语言/locale策略风险。

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
Top-level and method/class docstrings are presented in Chinese only, which imposes a specific language choice in the skill's user-facing/documentation text. The file does not offer a language choice or indicate that the locale restriction is intentional and justified.

Static analysis

No suspicious patterns detected.