Back to skill

Security audit

Openclaw Google Ads

Security checks for vulnerabilities and agentic risk

Overview

This Google Ads reporting skill is mostly coherent and read-first, but its authentication script prints a long-lived OAuth refresh token to standard output.

Review before installing. The main issue is the authentication helper: do not run it in an agent, shared terminal, CI job, or logged environment until it is changed to store the refresh token through an approved secret channel without printing it. The reporting scripts otherwise appear read-only and purpose-aligned, but they will use Google Ads credentials from the environment and contact Google's API.

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/authenticate.py:48
Finding

OAuth Refresh Token Exposed in Standard Output

Content
View full analysis

Vulnerability Details

File Location: scripts/authenticate.py, lines 48–52
Vulnerability Type: Plaintext sensitive-token disclosure
Risk Level: High

Vulnerable Code

python
# Store refresh token
refresh_token = credentials.refresh_token

print(f"\n{'='*60}")
print(f"REFRESH TOKEN: {refresh_token}")

Technical Analysis

After the OAuth authorization flow completes, the script prints the complete Google OAuth refresh token to standard output. A refresh token is a long-lived credential that can be exchanged for short-lived access tokens under the granted Google Ads scope:

text
https://www.googleapis.com/auth/adwords

Standard output is not a secure secret-transfer mechanism. In agent, CI/CD, terminal-recording, debugging, or support environments, it may be captured by execution logs, monitoring systems, conversation transcripts, or session recordings. The warning printed after the token does not prevent the token from already being disclosed.

This behavior also conflicts with the security rule in SKILL.md that tokens and credentials must never be exposed in files or chat.

Attack Path

  1. A user or agent follows the documented authentication procedure and runs python3 scripts/authenticate.py.
  2. The user completes Google's OAuth authorization flow.
  3. Google returns a refresh token to the script.
  4. The script writes the complete refresh token to standard output.
  5. The execution environment retains or forwards that output through logs, agent context, terminal recording, monitoring, or support transcripts.
  6. An attacker with access to the captured output obtains the refresh token.
  7. The attacker combines it with the relevant OAuth client credentials and exchanges it at Google's token endpoint for access tokens.
  8. The attacker uses those access tokens to access Google Ads resources available to the authorized identity.

Impact Assessment

A disclosed refresh token can provide durable access because it may cont ...[truncated 633 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove all statements that print the refresh token or other OAuth credentials.
  2. Transfer the token directly to the workspace's approved secret manager instead of standard output, chat, files, or shell history.
  3. If direct secret-manager integration is unavailable, fail safely and provide instructions for completing credential enrollment through a trusted, non-logged channel.
  4. Ensure secret values are redacted from exceptions, debug logs, telemetry, and agent tool results.
  5. Disable verbose HTTP or OAuth debugging in production authentication workflows.
  6. Restrict access to authentication execution logs and configure automatic secret masking as defense in depth.
  7. Revoke and rotate any refresh token previously displayed by this script, then review relevant Google account and Google Ads access logs for unexpected activity.
  8. Add an automated test or static-analysis rule that rejects output statements containing tokens, client secrets, passwords, or similarly sensitive values.

A safer implementation should confirm success without revealing the credential, for example:

python
refresh_token = credentials.refresh_token

if not refresh_token:
    print("Error: No refresh token was returned.")
    sys.exit(1)

# Store refresh_token directly through an approved secret-store integration.
print("Authentication succeeded. The refresh token was stored securely.")
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (7)

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Content

Scanner excerpt · references/optimization.md (reported line 21)May include surrounding context.

md
## Bidding

- Aggressive target CPA can choke volume.
- Maximize Conversions without guardrails can waste budget.
- Manual CPC can be useful early, but often leaves money on the table once conversion volume is real.
- Bid changes should be evaluated against conversion lag, not same-day noise.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · README.md (reported line 22)May include surrounding context.

md
- a Sea Cool-only skill
- a replacement for business-specific campaign strategy docs
- a license to make live account changes without approval
- a place to store credentials

## Structure

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill references local scripts and an authentication flow but does not declare an explicit tool scope or allowed-tools boundary. That creates ambiguity about what runtime capabilities an agent may use, increasing the risk of unintended environment access, secret exposure, or execution beyond the author’s intended read-only workflow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code loads Google Ads credentials from the environment and sends the supplied account ID and GAQL query to the Google Ads API. Although it prints the account and query, it does not disclose that the script will use environment-based credentials and perform an external API call, which is a relevant safety warning for code that transmits user or system data.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency google-auth-oauthlib is specified with a lower-bound range instead of an exact version, which allows future builds to resolve to different releases. In a security-sensitive skill that interacts with Google Ads and authentication flows, this weakens reproducibility and can introduce vulnerable or breaking upstream versions through the supply chain.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
google-ads==24.1.0
google-auth-oauthlib>=0.5.0
google-auth>=2.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency google-auth is also left unpinned with only a minimum version, so installations may pull in any newer release at build time. Because this skill relies on cloud authentication libraries for access to advertising account data, unexpected dependency drift can expose the agent to supply-chain risk, regressions, or newly introduced insecure behavior.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
google-ads==24.1.0
google-auth-oauthlib>=0.5.0
google-auth>=2.0.0

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

This code initializes a Google Ads client from environment configuration and issues a remote API request, which sends account-related data to Google's service. Although the script prints the account being queried, it does not explicitly disclose that it will contact an external network service or use environment-based credentials.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.