Back to skill

Security audit

google-sheets-soha

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent Google Sheets purpose, but its instructions create real review concerns around command execution, unsafe cache paths, and plaintext retention of private sheet data.

Review this skill before installing. Use it only with sheets you are comfortable exposing to the OpenClaw runtime, avoid private sheets unless caching is fixed or disabled, and do not run it on untrusted Sheet IDs or attacker-controlled tab names until command construction and cache path handling are hardened.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:83
Finding

Shell Command Injection Through Unvalidated Sheet and Tab Identifiers

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:150
Finding

Path Traversal Enables Filesystem Writes and Recursive Deletion Outside the Cache Directory

Content
View full analysis
c.get("ttl", TTL): return None # expired — will re-fetch return c def save_cache(sheet_id, tab, headers, rows): path = cache_path(sheet_id, tab) with open(path, "w") as f: json.dump({ "spreadsheetId": sheet_id, "tabName": tab, "fetchedAt": int(time.time()), "ttl": TTL, "headers": headers, "rows": rows }, f, ensure_ascii=False) def clear_cache(sheet_id=None): target = os.path.join(CACHE_DIR, sheet_id) if sheet_id else CACHE_DIR if os.path.exists(target): shutil.rmtree(target) ``` ### Technical Analysis The cache path incorporates `sheet_id` without validation or canonical-path containment checks. The Skill explicitly accepts a Sheet ID directly from a user. Python's `os.path.join` does not enforce confinement beneath `CACHE_DIR`: - A relative ID containing `..` components can escape the cache directory. - An absolute ID can cause the preceding cache directory to be discarded. - Symbolic links in path components can redirect operations outside the intended directory. Although forward slashes are replaced in `tab`, no equivalent confinement is applied to `sheet_id`, and string replacement alone is ...[truncated 1932 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:166
Finding

Private Spreadsheet Contents Are Persisted in Plaintext Without Permission Hardening

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (10)

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger language is extremely broad, including generic words like 'sheet' and casual phrases such as 'check my sheet,' which are likely to overlap with unrelated user requests. Overbroad activation can cause this skill to engage unexpectedly, leading to unnecessary external requests, credential use, or access to spreadsheet-linked data when the user did not intend to invoke it.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

| python3 -c "import sys,json; d=json.load(sys.stdin); [print(s['properties']['title']) for s in d['sheets']]"

Fetch tab data

curl -s "https://sheets.googleapis.com/v4/spreadsheets/{SHEET_ID}/values/{TAB_NAME}!A1:Z1000?key={GOOGLE_API_KEY}"
| python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d.get('values',[])))"

text

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

The README states that the skill remembers the Sheet ID throughout the conversation and describes local caching of sheet data, which creates session persistence of potentially sensitive document references and contents. In a data-access skill, retaining identifiers and cached spreadsheet data beyond the immediate request increases the chance of unintended reuse, stale-context access, or exposure to other local processes/users if permissions are weak.

Content

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

md
### Google API Key (public sheet)
1. Go to [console.cloud.google.com](https://console.cloud.google.com)
2. Create a project → **APIs & Services → Library** → enable **Google Sheets API**
3. **APIs & Services → Credentials → Create Credentials → API Key**
4. Copy the key into your config

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
3. **IAM & Admin → Service Accounts → Create Service Account**
4. Go to the **Keys** tab → **Add Key → JSON** → download the file
5. Copy the file to `~/.openclaw/google-sa.json`
6. Fix permissions: `sudo chown 1000:1000 ~/.openclaw/google-sa.json`
7. Open your Google Sheet → **Share** → paste the `client_email` from the JSON file → Viewer

## Usage

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
3. **IAM & Admin → Service Accounts → Create Service Account**
4. Go to the **Keys** tab → **Add Key → JSON** → download the file
5. Copy the file to `~/.openclaw/google-sa.json`
6. Fix permissions: `sudo chown 1000:1000 ~/.openclaw/google-sa.json`
7. Open your Google Sheet → **Share** → paste the `client_email` from the JSON file → Viewer

## Usage

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation criteria are broad enough to trigger on generic words like 'sheet' or 'spreadsheet' and casual requests such as 'check my sheet,' which can cause the skill to activate in contexts the user did not clearly intend. Because this skill can access Google Sheets data, over-triggering increases the risk of unnecessary data access, privacy exposure, and unintended use of configured credentials.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instruction to run apt-get install -y python3 introduces package-management side effects unrelated to reading spreadsheet data. Allowing a skill to install software broadens its capabilities, can change the execution environment, and may be abused to trigger privileged or networked operations outside the user's intent.

Content

No source excerpt is available for this finding.

External Script Fetching

Low
Category
Supply Chain
Confidence
15% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
required: false
      bins:
        - python3
        - curl
    primaryEnv: GOOGLE_SERVICE_ACCOUNT_JSON
    homepage: https://github.com/your-username/google-sheets-soha
    repository: https://github.com/your-username/google-sheets-soha

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill includes a global clear_cache() mode that wipes the entire sheets cache directory rather than only data for the active spreadsheet. This exceeds least-privilege for the stated task and could delete unrelated cached sheet data from other conversations or sheets, causing avoidable data loss or workflow disruption.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest description emphasizes reading and analyzing Google Sheets data, which suggests a read-only analytics scope. However, the documented cache management flow includes clear_cache() operations that remove cached files and directories from local disk, which is behavior beyond pure read/analyze semantics.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.