Back to skill

Security audit

Google Sheet API

Security checks for vulnerabilities and agentic risk

Overview

This Google Sheets CLI is mostly purpose-aligned, but it can modify or delete spreadsheet data with limited safeguards and has supply-chain and credential-selection risks.

Install only if you are comfortable giving this CLI service-account access to the target spreadsheets. Use a least-privilege service account shared only with intended sheets, prefer explicit credential environment variables over automatic credential-file discovery, review commands before allowing an agent to run clear/deleteSheet/batch operations, and pin dependencies or add a reviewed lockfile before production use.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
package.json:10
Finding
Non-Reproducible Dependency Installation Without a Lockfile<![CDATA[ ## Vulnerability Details **File Location**: `package.json:10-12`; installation guidance at `SKILL.md:28-31` **Vulnerability Type**: Supply-chain exposure caused by an unlocked dependency range **Risk Level**: Medium ### Vulnerable Code `package.json:10-12`: ```json "dependencies": { "googleapis": "^140.0.0" } ``` `SKILL.md:28-31`: ```bash cd google-sheet-api npm install ``` No dependency lockfile is present in the audited project. ### Technical Analysis The project permits any semver-compatible `googleapis` release through the caret range and instructs users to run `npm install`. Without a committed `package-lock.json`, the exact direct and transitive dependency versions installed are determined at installation time rather than by the versions reviewed during the audit. This is especially sensitive because installed dependency code executes in the same Node.js process as the CLI. It can therefore access: - Service-account credentials loaded into memory. - Environment variables available to the process. - Credential files readable by the current user. - Spreadsheet identifiers, request payloads, and returned spreadsheet data. - The network and filesystem privileges of the invoking user. The audit found no malicious dependency declaration or unsafe package source in the current manifest. Exploitation therefore requires a future compromised, malicious, or unexpectedly vulnerable direct or transitive package version. Nevertheless, the absence of a lockfile prevents reproducible installation and creates a material supply-chain risk. ### Attack Path 1. An attacker compromises a future semver-compatible release of `googleapis` or one of its transitive dependencies, or a newly resolved version introduces exploitable behavior. 2. A user follows the documented instruction and runs `npm install`. 3. npm resolves the dependency tree at that time because no reviewed lockfile constrains it. 4. The compromised dependency is installed and loaded by: ...[truncated 850 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate and commit a reviewed `package-lock.json`. 2. Replace the documented `npm install` workflow with `npm ci` for production and automated installations. 3. Consider pinning `googleapis` to an exact reviewed version instead of using a caret range. 4. Review lockfile changes as security-sensitive code changes. 5. Run dependency vulnerability and provenance checks in CI, such as `npm audit` and an appropriate software-composition-analysis tool. 6. Use automated dependency updates that produce reviewable pull requests rather than resolving new versions during deployment. 7. Run the CLI in an environment with only the credential and filesystem access required for the specific operation. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/sheets-cli.js:11
Finding
Implicit Discovery and Loading of Credential Files from Broad Default Locations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sheets-cli.js:11-16` and `scripts/sheets-cli.js:62-80`; documented at `SKILL.md:44-51` and `env_example.md:14-18` **Vulnerability Type**: Unsafe implicit credential selection **Risk Level**: Low ### Vulnerable Code `scripts/sheets-cli.js:11-16`: ```js const DEFAULT_CRED_FILES = [ 'service-account.json', 'credentials.json', 'google-service-account.json', path.join(process.env.HOME || '', '.config/google-sheets/credentials.json'), ]; ``` `scripts/sheets-cli.js:62-80`: ```js function resolveCredentials() { const inlineJson = process.env.GOOGLE_SHEETS_CREDENTIALS_JSON || process.env.GOOGLE_SERVICE_ACCOUNT_JSON; if (inlineJson) { return { credentials: JSON.parse(inlineJson), source: 'env:GOOGLE_SHEETS_CREDENTIALS_JSON' }; } const envPath = process.env.GOOGLE_SERVICE_ACCOUNT_KEY || process.env.GOOGLE_SHEETS_KEY_FILE || process.env.GOOGLE_APPLICATION_CREDENTIALS; if (envPath && fs.existsSync(envPath)) { return { credentials: readFileJson(envPath), source: `file:${envPath}` }; } for (const rel of DEFAULT_CRED_FILES) { const fullPath = path.isAbsolute(rel) ? rel : path.join(process.cwd(), rel); if (fs.existsSync(fullPath)) { return { credentials: readFileJson(fullPath), source: `file:${fullPath}` }; } } return null; } ``` ### Technical Analysis Reading service-account credentials is necessary for the declared Google Sheets functionality. The home-directory path is documented, and the audit found no code that directly logs the private key or sends it to an unknown endpoint. However, the CLI silently searches multiple generic filenames in the current working directory and a default location under the user's home directory. The first existing file is accepted without requiring an explicit credential selection or confirming the intended service-account identity. Current-working-directory discovery is particularly fragile because credentia ...[truncated 2223 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit credential selection through a dedicated command-line option, a documented environment variable, or standard Google Application Default Credentials. 2. Remove generic current-working-directory fallback names, especially `credentials.json`. 3. If a default path must remain, use one application-specific path under the user's configuration directory. 4. Validate the requested command and its arguments before resolving or parsing credentials. 5. Validate that loaded JSON has the expected service-account structure and reject unsupported credential types. 6. Optionally display the selected credential source and service-account email, while never displaying private-key material. 7. Check credential-file permissions and warn when a key is readable by group or other users. 8. Document that credential directories must not be writable by untrusted users. 9. Prefer short-lived or externally managed credentials over long-lived downloaded service-account keys where deployment constraints permit. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (15)

Credential Access

High
Category
Privilege Escalation
Content
GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.json

# Option 2: alternative env var name
# GOOGLE_SHEETS_KEY_FILE=/path/to/credentials.json

# Option 3: standard Google env var
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.json

# Option 2: alternative env var name
# GOOGLE_SHEETS_KEY_FILE=/path/to/credentials.json

# Option 3: standard Google env var
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.json

# Option 2: alternative env var name
# GOOGLE_SHEETS_KEY_FILE=/path/to/credentials.json

# Option 3: standard Google env var
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.json

# Option 2: alternative env var name
# GOOGLE_SHEETS_KEY_FILE=/path/to/credentials.json

# Option 3: standard Google env var
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.json

# Option 2: alternative env var name
# GOOGLE_SHEETS_KEY_FILE=/path/to/credentials.json

# Option 3: standard Google env var
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.json

# Option 2: alternative env var name
# GOOGLE_SHEETS_KEY_FILE=/path/to/credentials.json

# Option 3: standard Google env var
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.json

# Option 2: alternative env var name
# GOOGLE_SHEETS_KEY_FILE=/path/to/credentials.json

# Option 3: standard Google env var
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.json

# Option 2: alternative env var name
# GOOGLE_SHEETS_KEY_FILE=/path/to/credentials.json

# Option 3: standard Google env var
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

High
Confidence
98% confidence
Finding
The `deleteSheet` command deletes an entire sheet via `deleteSheet: { sheetId }` with no confirmation, warning, or explanatory output. Deleting a sheet is an irreversible, safety-critical operation affecting user data, so the lack of disclosure is a meaningful safety gap.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill documents code that uses environment-provided credentials and network access to Google Sheets, but it declares no explicit tool scope such as permissions or allowed-tools. In an agent environment, that mismatch can cause the skill to run with broader-than-expected capabilities, reducing reviewability and increasing the chance of unintended credential access or external data exfiltration.

Session Persistence

Medium
Category
Rogue Agent
Content
## Best fit
- You need a repeatable CLI for automation tasks.
- You want JSON-in/JSON-out for pipelines.
- You need more than basic read/write (formatting, sheet ops, batch updates).

## Not a fit
- You must use end-user OAuth consent flows (this skill is service-account focused).
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This markdown file documents data-write endpoints like `values.update`, `values.append`, and structural `batchUpdate` requests including `deleteSheet`, but it does not include any caution about user data modification or destructive changes. For markdown files, safety-relevant behaviors that can affect user data should be accompanied by a warning or disclosure.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The `clear` command permanently removes cell contents in the specified range by calling the Sheets API clear endpoint, but the code provides no confirmation prompt, warning message, or other user-facing disclosure before doing so. Because this is a destructive operation that affects user data, the absence of any warning increases the risk of accidental data loss.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"help": "node scripts/sheets-cli.js help"
  },
  "dependencies": {
    "googleapis": "^140.0.0"
  }
}
Confidence
95% confidence
Finding
The dependency is specified with a caret range (^140.0.0), which allows installation of newer minor/patch releases that are not fixed or reproducibly audited. This creates supply-chain uncertainty and can inadvertently pull in vulnerable or breaking versions over time, especially for a skill that interacts with external Google APIs and may handle credentials.

Unverifiable Dependency: googleapis has 1 known advisory(ies) (GHSA-7543-mr7h-6v86 (Improper Authorization in googleapis)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding
The manifest references googleapis without pinning an exact version, while the package has a known advisory for improper authorization. Because the allowed version range is not deterministic from the manifest alone, consumers may install an affected release, which is more concerning in a Google Sheets skill that likely uses OAuth tokens or service-account credentials to access and modify spreadsheet data.

Static analysis

No suspicious patterns detected.