Back to skill

Security audit

Google ads for OpenClaw

Security checks for vulnerabilities and agentic risk

Overview

This Google Ads skill is not malicious, but it handles sensitive ad-account credentials and account selection too loosely for a business-impacting integration.

Install only if you are comfortable with an agent reading your local Google Ads credential configuration. Before using it, restrict ~/.google-ads.yaml permissions to owner-only, avoid storing real secrets in shared workspaces, and require explicit confirmation of the target Google Ads customer account before any operation. Treat the advertised budget/status features as incomplete in this artifact.

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/setup_ads.py:4
Finding

Google Ads Credential File Is Created Without Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/setup_ads.py, lines 4–12
Vulnerability Type: Insecure permissions on a sensitive configuration file
Risk Level: Medium

Vulnerable Code

python
def create_config_template(path):
    config = {
        'developer_token': 'INSERT_DEVELOPER_TOKEN_HERE',
        'client_id': 'INSERT_CLIENT_ID_HERE',
        'client_secret': 'INSERT_CLIENT_SECRET_HERE',
        'refresh_token': 'INSERT_REFRESH_TOKEN_HERE',
        'use_proto_plus': True
    }
    with open(path, 'w') as f:
        yaml.dump(config, f, default_flow_style=False)

Technical Analysis

The script creates ~/.google-ads.yaml with Python's standard open(path, 'w') operation and does not explicitly enforce owner-only permissions. The resulting permissions therefore depend on the process umask. For example, a typical umask of 022 can produce a file with mode 0644, making it readable by other local users.

The file initially contains placeholders, but its intended purpose is to store a Google Ads developer token, OAuth client secret, and refresh token. After a user replaces the placeholders with real credentials, permissive file permissions can expose those secrets to other accounts on the same system.

Attack Path

  1. The user runs scripts/setup_ads.py.
  2. The script creates ~/.google-ads.yaml without explicitly setting mode 0600.
  3. The user inserts valid Google Ads credentials into the generated file.
  4. On a multi-user host with a permissive umask, another local account reads the configuration file.
  5. The attacker extracts the developer token, client credentials, and refresh token.
  6. The attacker attempts to reuse those credentials through the Google Ads API.

Exploitation requires local filesystem access under an account permitted to read the resulting file. Actual API access remains constrained by the validity, authorization scope, and account permissions o ...[truncated 622 chars]

Remediation
View remediation

Remediation Suggestions

Create the credential file atomically with owner-only permissions and refuse to overwrite an existing file:

python
import os
import yaml

def create_config_template(path):
    config = {
        'developer_token': 'INSERT_DEVELOPER_TOKEN_HERE',
        'client_id': 'INSERT_CLIENT_ID_HERE',
        'client_secret': 'INSERT_CLIENT_SECRET_HERE',
        'refresh_token': 'INSERT_REFRESH_TOKEN_HERE',
        'use_proto_plus': True,
    }

    flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
    fd = os.open(path, flags, 0o600)
    try:
        with os.fdopen(fd, 'w') as f:
            yaml.safe_dump(config, f, default_flow_style=False)
    except Exception:
        try:
            os.unlink(path)
        except OSError:
            pass
        raise

Additional hardening measures:

  • Verify the final mode with os.stat() and reject or correct group/world-readable permissions.
  • Apply os.chmod(path, 0o600) where appropriate as a defense-in-depth measure.
  • Warn users that the file contains sensitive credentials and must not be committed to source control.
  • Prefer a platform credential store or secrets manager where operationally feasible.
  • Rotate the refresh token, client secret, and developer token if unauthorized file access is suspected.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

If the skill claims to manage Google Ads but in reality only creates a local configuration file containing credential parameters, that is a meaningful security concern. It can mislead the agent or user into handling sensitive secrets locally under the guise of API operations, increasing the risk of accidental credential exposure or improper storage.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

If the skill claims to manage Google Ads but in reality only creates a local configuration file containing credential parameters, that is a meaningful security concern. It can mislead the agent or user into handling sensitive secrets locally under the guise of API operations, increasing the risk of accidental credential exposure or improper storage.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
72% confidence
Finding

The skill instructs the agent to rely on a local configuration file and references a script that can modify campaign state, yet it does not declare any explicit tool scope or permission boundaries. In an agent environment, missing scope declarations can lead to broader-than-intended file access or write operations, especially around credential files like ~/.google-ads.yaml.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language content of the skill, including the manifest description and all usage instructions, is entirely in Russian, which can impose a language choice on users or agents without offering an alternative or opt-in. The file does not document that this skill is intended only for a Russian-speaking or region-specific environment, so this creates a language/locale policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest says the skill can change budgets and enable or disable campaigns through the Google Ads API. Although CLI subcommands for update-status and update-budget are declared, the only implemented behavior in the command handler is the list branch, so no modifying operations actually occur.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The tool silently loads Google Ads credentials from the default local configuration, which can cause it to operate against whichever account is present on the host without explicit user awareness or account selection. In an agent/skill context, this increases the risk of unintended access to sensitive advertising data and actions being performed under the wrong account.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.