Back to skill

Security audit

Google Drive File Management

Security checks for vulnerabilities and agentic risk

Overview

This Google Drive skill does what it claims, but its implementation has unsafe command execution and download path handling that could let crafted inputs run local commands or write files outside the intended folder.

Review before installing. This skill should only be used with trusted inputs and a limited Google account until fixed. The publisher should replace shell-based exec calls with execFile or spawn argument arrays, validate Drive IDs, emails, roles, limits, paths, and account names, prevent download path traversal and unintended overwrites, and add explicit confirmations for uploads, downloads, and sharing.

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

T09 · Insecure Skill Coding Practices

Error
Location
src/index.js:30
Finding
OS Command Injection in the Primary Google Drive Implementation<![CDATA[ ## Vulnerability Details **File Location**: `src/index.js:30-31, 61-71, 106-108, 137-148, 179-181` **Vulnerability Type**: OS command injection through shell command construction **Risk Level**: High ### Vulnerable Code ```js const command = `gog drive files upload --account ${account} --file "${filePath}" --name "${fileName}" --parents "${folder}" --mime-type "${mimeType}" --json`; const { stdout } = await execAsync(command, { shell: true }); ``` ```js let command = `gog drive files list --account ${account} --max ${limit} --json`; if (folder !== 'root') { command += ` --parents "${folder}"`; } if (query) { command += ` --query "name contains '${query}'"`; } const { stdout } = await execAsync(command, { shell: true }); ``` ```js const command = `gog drive files list --account ${account} --max ${limit} --query "${searchQuery}" --json`; const { stdout } = await execAsync(command, { shell: true }); ``` ```js const infoCommand = `gog drive files get --account ${account} --file ${fileId} --json`; const { stdout: infoStdout } = await execAsync(infoCommand, { shell: true }); const fileInfo = JSON.parse(infoStdout); const fileName = fileInfo.name; const destination = path.join(outputPath, fileName); const downloadCommand = `gog drive files download --account ${account} --file ${fileId} --output "${destination}"`; await execAsync(downloadCommand, { shell: true }); ``` ```js const command = `gog drive permissions create --account ${account} --file ${fileId} --role ${role} --type user --email-address "${email}" --json`; const { stdout } = await execAsync(command, { shell: true }); ``` ### Technical Analysis The implementation creates command strings by directly interpolating caller-controlled or remotely derived values and then passes those strings to `child_process.exec` with shell processing enabled. Affected values include: - `account` - `filePath` - `customName` or the derived filename - `folder` - `limit` - `query` - `fileType` - `fileId ...[truncated 1993 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `exec` with `execFile` or `spawn` and pass arguments as an array. Do not enable shell processing. ```js import { execFile } from 'child_process'; import { promisify } from 'util'; const execFileAsync = promisify(execFile); const { stdout } = await execFileAsync('gog', [ 'drive', 'files', 'list', '--account', account, '--max', String(limit), '--query', searchQuery, '--json' ]); ``` 2. Apply strict validation in addition to argument separation: - Require `limit` to be a bounded positive integer. - Allow only supported sharing roles such as `reader`, `writer`, and `commenter`. - Validate email addresses and Google Drive IDs. - Validate account identifiers using an appropriate allowlist. - Reject null bytes and unexpected control characters in paths and names. 3. Treat Google Drive metadata, including filenames, as untrusted input. 4. Centralize all `gog` invocations in one shell-free helper to prevent future regressions. 5. Add automated tests containing spaces, quotes, semicolons, backticks, and `$()` expressions, confirming that they remain literal arguments and never execute. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/index_corrected.js:22
Finding
OS Command Injection in the Alternate Google Drive Implementation<![CDATA[ ## Vulnerability Details **File Location**: `src/index_corrected.js:22-28, 58-60, 87-96` **Vulnerability Type**: OS command injection through shell command construction **Risk Level**: High ### Vulnerable Code ```js let command = `gog drive ls --account ${account} --max ${limit} --json`; if (folder !== 'root') { command += ` --folder "${folder}"`; } const { stdout } = await execAsync(command, { shell: true }); ``` ```js const command = `gog drive search "${query}" --account ${account} --max ${limit} --json`; const { stdout } = await execAsync(command, { shell: true }); ``` ```js const infoCommand = `gog drive get ${fileId} --account ${account} --json`; const { stdout: infoStdout } = await execAsync(infoCommand, { shell: true }); const fileInfo = JSON.parse(infoStdout); const fileName = fileInfo.name; const destination = path.join(outputPath, fileName); const downloadCommand = `gog drive get ${fileId} --account ${account} --output "${destination}"`; await execAsync(downloadCommand, { shell: true }); ``` ### Technical Analysis Although this file is named `index_corrected.js`, it retains the same unsafe command-execution pattern. Caller-controlled values are interpolated into command strings executed through a shell. Double-quoting `query`, `folder`, or `destination` does not prevent all shell evaluation. Values such as `fileId`, `account`, and `limit` are unquoted, making exploitation even more direct. The file is not the package entry point identified by `package.json`, but it remains exploitable if imported or run independently. ### Attack Path 1. An attacker reaches an exported function or the included CLI search handler. 2. The attacker supplies a value containing shell syntax through `query`, `fileId`, `account`, `folder`, `limit`, or another affected input. 3. The value is concatenated into the `gog` command. 4. `execAsync` invokes the operating-system shell. 5. The shell interprets the injected syntax and executes attacker-selected ...[truncated 394 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every use of `execAsync` with shell-free `execFile` or `spawn` calls. 2. Supply every command-line parameter as a distinct argument array element. 3. Enforce strict types and bounds for `limit`. 4. Validate Drive IDs, account identifiers, folders, and other structured values against narrow allowlists. 5. Keep search text as a literal process argument rather than attempting to escape it for a shell. 6. Remove this alternate implementation if it is obsolete; otherwise, apply the same hardened command helper used by the package entry point. 7. Add command-injection regression tests for both direct API use and CLI invocation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/index.js:141
Finding
Download Path Traversal and Arbitrary File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `src/index.js:141-148` **Vulnerability Type**: Path traversal through an untrusted remote filename **Risk Level**: Medium ### Vulnerable Code ```js const fileName = fileInfo.name; const destination = path.join(outputPath, fileName); // Descargar el archivo const downloadCommand = `gog drive files download --account ${account} --file ${fileId} --output "${destination}"`; await execAsync(downloadCommand, { shell: true }); ``` ### Technical Analysis The destination filename comes from Google Drive metadata and is therefore outside the local application's trust boundary. The code passes that filename directly to `path.join(outputPath, fileName)` without: - Reducing it to a safe basename. - Rejecting absolute paths or path separators. - Resolving and verifying containment under `outputPath`. - Preventing overwrite of an existing destination. A malicious filename containing traversal components such as `../` can cause the normalized destination to escape the intended output directory. An absolute or platform-specific path may create similar risks depending on path semantics and CLI behavior. This path is subsequently embedded in a shell command, which also contributes to the separate command-injection vulnerability. ### Attack Path 1. An attacker creates or shares a Google Drive file whose name contains path traversal components. 2. The victim or an automated workflow calls `downloadFile` with the attacker's file ID. 3. The skill retrieves the attacker-controlled name from Drive metadata. 4. `path.join` normalizes the name with the requested output directory but performs no containment check. 5. The download command writes the file to a location outside the intended workspace or output directory. 6. If an existing writable file is targeted and the CLI permits replacement, that file may be overwritten. ### Impact Assessment The attacker may create or overwrite files anywhere writable by the skill proces ...[truncated 451 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat the Drive filename as untrusted and derive a safe local name: ```js const safeName = path.basename(fileInfo.name); if (!safeName || safeName === '.' || safeName === '..') { throw new Error('Invalid remote filename'); } ``` 2. Resolve both paths and verify containment: ```js const outputRoot = path.resolve(outputPath); const destination = path.resolve(outputRoot, safeName); if ( destination !== outputRoot && !destination.startsWith(outputRoot + path.sep) ) { throw new Error('Download destination escapes the output directory'); } ``` 3. Reject filenames containing path separators, null bytes, or platform-specific reserved forms. 4. Refuse to overwrite existing files by default. Require an explicit, authorized overwrite option if replacement is necessary. 5. Use a shell-free process API and pass `destination` as a separate argument. 6. Consider downloading to a securely created temporary file and atomically moving it after validation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/index_corrected.js:91
Finding
Download Path Traversal in the Alternate Implementation<![CDATA[ ## Vulnerability Details **File Location**: `src/index_corrected.js:91-96` **Vulnerability Type**: Path traversal through an untrusted remote filename **Risk Level**: Medium ### Vulnerable Code ```js const fileName = fileInfo.name; const destination = path.join(outputPath, fileName); // Descargar el archivo const downloadCommand = `gog drive get ${fileId} --account ${account} --output "${destination}"`; await execAsync(downloadCommand, { shell: true }); ``` ### Technical Analysis The implementation trusts `fileInfo.name`, obtained from Google Drive, and combines it with a local output directory without validating the filename or checking that the resolved destination remains inside that directory. A remote filename containing parent-directory components can therefore select a destination outside the intended workspace. The code also does not explicitly prevent overwriting an existing file. Although this alternate file is not the configured package entry point, the flaw is reachable if the module is imported or executed. ### Attack Path 1. An attacker makes a Drive file with a traversal filename available to the victim. 2. The victim invokes `downloadFile` for that file. 3. The module reads the malicious filename from Drive metadata. 4. The filename is joined to `outputPath` without sanitization or containment validation. 5. The `gog` process writes the downloaded content outside the intended directory. 6. A writable existing file may be replaced if overwrite behavior is supported. ### Impact Assessment An attacker can potentially create or overwrite files in locations writable by the skill process. This can cause data loss, configuration tampering, or code execution when a subsequently loaded or executed file is replaced. The impact is constrained by the filesystem permissions of the runtime account. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Normalize remote names with `path.basename` and reject names that differ because of path separators or traversal components. 2. Resolve the final path and verify that it remains beneath the resolved output root. 3. Reject absolute paths, null bytes, reserved names, and empty filenames. 4. Disable overwriting by default and use exclusive file creation where possible. 5. Download into a secure temporary location before performing a validated atomic move. 6. Replace shell-based command execution with `execFile` or `spawn` and an argument array. 7. Remove `src/index_corrected.js` if it is obsolete so that a vulnerable alternate implementation cannot be used accidentally. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented purpose emphasizes file management, but the skill also supports sharing files and assigning roles, which changes access control and can expose data to third parties. When a skill can create permissions without clearly foregrounding that behavior, users may invoke it expecting storage actions only and accidentally disclose sensitive files.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented purpose emphasizes file management, but the skill also supports sharing files and assigning roles, which changes access control and can expose data to third parties. When a skill can create permissions without clearly foregrounding that behavior, users may invoke it expecting storage actions only and accidentally disclose sensitive files.

Missing User Warnings

High
Confidence
95% confidence
Finding
Sharing a file with an arbitrary email address grants external access to Google Drive content without an explicit warning or confirmation step. In this context, the action is especially sensitive because it changes access permissions and can cause immediate data exposure to third parties, not just local file handling.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill exposes capabilities that can access environment-derived credentials or configuration for Google Drive operations, but it declares no explicit tool scope or permission boundaries. In an agent setting, undocumented access to env-backed auth increases the risk of unintended data access or exfiltration because users and orchestration layers cannot constrain what the skill is allowed to use.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill encourages uploading, downloading, and sharing files with a third-party cloud service but does not warn about data sensitivity, privacy implications, or the risk of overwriting or exposing user content. In a file-management context, omission of these warnings makes accidental transfer of confidential workspace data more likely.

Context-Inappropriate Capability

Medium
Confidence
99% confidence
Finding
The module builds shell command strings from user-controlled inputs such as account, file paths, folder IDs, queries, file IDs, and email addresses, then executes them with exec(..., { shell: true }). This is a classic command-injection risk: crafted input containing shell metacharacters can break out of intended arguments and execute arbitrary commands on the host.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
Uploading local files to Google Drive transmits potentially sensitive workspace data off-system without any built-in explicit confirmation or warning. In an agent setting, this can enable unintended exfiltration of local files if a user request is ambiguous or if the skill is invoked through indirect prompt manipulation.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The download function writes remote content directly into the local workspace without any confirmation, creating a risk of unreviewed file introduction into trusted local storage. This can overwrite expectations, introduce dangerous scripts or documents, and facilitate follow-on attacks if other tools later process the downloaded file.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The skill description is limited to file management, but the implementation also modifies Google Drive permissions by sharing files with arbitrary email addresses. This expands the capability from file operations into access-control changes, increasing the risk of unauthorized external disclosure of data if the action is invoked unexpectedly or by prompt manipulation.

Missing User Warnings

Medium
Confidence
80% confidence
Finding
The skill accesses Google Drive using configured account credentials and enumerates remote file metadata without any built-in consent prompt, disclosure, or scope limitation visible in this code. In a file-management skill this behavior is expected, but in an agent context it is still security-relevant because it can expose private cloud data to downstream agent actions without making the data access explicit to the user.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The download function writes Drive content directly into the local workspace using a file name derived from remote metadata, without any confirmation, policy check, or user-visible disclosure. In an agent environment, automatically materializing remote files into a trusted workspace can introduce unreviewed content that may later be opened, processed, or executed by other tools, increasing the risk of workspace poisoning and unintended data flow.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The user-facing documentation is written in Spanish, but there is no indication that the skill is region-specific or that users can choose another language. This creates a natural-language locale policy issue because the skill appears to impose a language without opt-in or justification.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
Comments, function descriptions, and user-facing error messages are consistently presented in Spanish, with no indication that the user can choose a language or that the locale restriction is intentional. This can violate language/locale policy when a skill imposes one language by default without opt-in.