Back to skill

Security audit

Google Analytics Insights

Security checks for vulnerabilities and agentic risk

Overview

This GA4 assistant has a real privacy and trust-boundary concern because setup asks users to grant ongoing read access to a fixed external service account while under-disclosing what that means.

Review carefully before installing. Do not connect sensitive or client GA4 properties unless you trust the publisher with ongoing read access. If already connected, consider removing ga-insights@plucky-engine-488015-d4.iam.gserviceaccount.com from GA4 Property Access Management and deleting local ~/.openclaw/ga-insights config/cache files. A safer design would use OAuth or a service account created and controlled by the user, with clear privacy, retention, and revocation documentation.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
ga_insights.py:37
Finding

Setup Grants GA4 Viewer Access to a Shared Third-Party Service Account

Content
View full analysis
'" ], "note": "The service account only has read access — your data stays private." } def complete_setup(property_id: str) -> dict: pid = property_id.strip().lstrip("properties/") config = load_config() config.update({"property_id": pid, "credentials_path": DEFAULT_CREDENTIALS, "connected": True}) ``` `SKILL.md:42-50`: ```markdown ## Quick Setup (2 Steps) 1. **Add our service account to your GA4:** - Go to Analytics → Admin → Property Access Management - Add: `ga-insights@plucky-engine-488015-d4.iam.gserviceaccount.com` - Role: Viewer 2. **Tell us your Property ID:** ``` `QUICKSTART.md:3-17`: ```markdown ## Step 1: Connect Your GA4 1. Go to [Google Analytics](https://analytics.google.com/) 2. Click **Admin** (gear icon, bot ...[truncated 3329 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
ga_insights.py:47
Finding

Sensitive Analytics Cache Is Written Without Explicitly Restrictive File Permissions

Content
View full analysis
dict: try: if CACHE_FILE.exists(): with open(CACHE_FILE) as f: return json.load(f) except Exception: pass return {} def _save_cache(cache: dict): try: CONFIG_DIR.mkdir(parents=True, exist_ok=True) with open(CACHE_FILE, 'w') as f: json.dump(cache, f) except Exception: pass ``` The cache path is defined at `ga_insights.py:35-36`: ```python CONFIG_DIR = Path.home() / ".openclaw" / "ga-insights" CONFIG_FILE = CONFIG_DIR / "config.json" CACHE_FILE = CONFIG_DIR / "cache.json" ``` Realtime results written through this mechanism include country, device category, and active-user counts: ```python result = { "active_users": total, "breakdown": breakdown[:10], "status": "live", "insight": (f"🟢 {total} user{'s' if total != 1 else ''} on your site right now." if total else "No active users at this moment.") } cache_set("realtime", result) ``` ### Technical Analysis `_save_cache()` creates the cache directory and file without setting explicit security modes. The resulting permissions depend on the process umask and surrounding filesystem configuration. On a system with a permissive umask, other local users or processes may be able to read `cache.json`. The cache stores GA4-derived data in plaintext. Realtime results are JSON-serializable and can include current user counts, countries, and device categories. Other report functions also attempt to cache analytics results, although their inclusion of SDK response objects may cause JSON serialization to fail. Because every exception is silently suppressed, operators receive no warning when cache writes fail, are partial, or encounter permis ...[truncated 1308 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The quickstart instructs users to grant an external service account direct Viewer access to their GA4 property, which exposes potentially sensitive analytics data to a third party without any disclosure of privacy, data handling, retention, or trust boundaries. Even read-only GA4 access can reveal business-sensitive traffic, campaign, conversion, audience, and behavioral data, so asking users to share it through a setup guide is a real security and privacy risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill advertises behavior that likely relies on sensitive capabilities while omitting any explicit tool-scope or permissions declaration. That makes the execution boundary unclear to users and reviewers, increasing the risk of unintended environment access or file writes if the skill implementation or wrapper code uses those capabilities implicitly.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill invites broad natural-language requests such as general analytics questions, which can cause over-triggering in normal conversation and accidental invocation on unrelated user prompts. In a data-access skill tied to GA4, overly broad activation increases the chance of unintended disclosure or processing of analytics data without clear user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The setup instructs users to grant an external service account Viewer access to their GA4 property but does not prominently warn that this gives a third party ongoing access to potentially sensitive business analytics. Users may not understand the trust, privacy, retention, and revocation implications, which is especially risky for agency or multi-client properties.

Content

No source excerpt is available for this finding.

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · SKILL.md (reported line 70)May include surrounding context.

md
## Pricing

- **Free tier**: 50 queries/month, 1 property
- **Pro ($9/mo)**: Unlimited queries, 5 properties, anomaly alerts
- **Business ($49/mo)**: Unlimited properties, API access

## Requirements

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation states 'in-memory caching (5-10 min TTL)' but the implementation writes cached analytics data to a JSON file on disk. This mismatch is security-relevant because users may make trust decisions based on a false assumption that no local persistence occurs beyond process memory.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Google Analytics query results are serialized and written to a local cache file without user disclosure or consent. GA4 data can contain sensitive business intelligence such as traffic patterns, campaign performance, geography, and conversion behavior, so undisclosed persistence broadens the attack surface even in a local-only design.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · QUICKSTART.md (reported line 5)May include surrounding context.

md
"status": "setup_needed",
        "service_account_email": SERVICE_ACCOUNT_EMAIL,
        "steps": [
            "1. Go to https://analytics.google.com/",
            "2. Admin (⚙) → Property Access Management",
            "3. Click + → Add users",
            f"4. Enter: {SERVICE_ACCOUNT_EMAIL}",

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · ga_insights.py (reported line 132)May include surrounding context.

python
"status": "setup_needed",
        "service_account_email": SERVICE_ACCOUNT_EMAIL,
        "steps": [
            "1. Go to https://analytics.google.com/",
            "2. Admin (⚙) → Property Access Management",
            "3. Click + → Add users",
            f"4. Enter: {SERVICE_ACCOUNT_EMAIL}",

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill enables a catch-all natural-language entry point that forwards arbitrary user input directly to python ga_insights.py query "{input}" without any visible scope restriction, intent allowlist, or confirmation boundary. In an analytics-focused skill, broad NL activation increases the chance of unintended invocation, prompt/command bridging in downstream logic, or abuse of privileged data access through ambiguous queries.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill handles potentially sensitive GA4 analytics data but persists query results to a local disk cache in ~/.openclaw/ga-insights/cache.json, which contradicts the user-facing expectation of a transient analytics assistant. Even if the data is not transmitted to a third party, local persistence increases exposure to other local users, backups, forensic recovery, or unrelated processes that can read the file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The skill stores connection settings, including property ID and credentials path, in a local config file without disclosure. While this is less sensitive than storing raw credentials, it still exposes metadata about the user's analytics environment and may reveal file locations or linked properties to local attackers or other software.

Content

No source excerpt is available for this finding.