T09 · Insecure Skill Coding Practices
- Location
sync.js:52- Finding
Shell Command Injection Through Unvalidated Google Drive Folder IDs
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill has a coherent Google Drive RAG purpose, but it handles sensitive documents and credentials with several serious implementation and disclosure risks.
Review this skill carefully before installing. It can recursively read Google Drive folders, extract text including OCR, send content to embedding providers and optionally Qdrant, persist raw document chunks locally, and upload/download files. Do not use it with sensitive folders until folder ID validation, credential removal/rotation, safer subprocess calls, pinned tooling, explicit deletion confirmation, and clearer data-retention controls are added.
sync.js:52Shell Command Injection Through Unvalidated Google Drive Folder IDs
tests/credentials.json:2Google OAuth Client Secret and Gemini API Key Committed to Source
sync.js:207Sensitive Drive Document Content Stored in Plaintext and Sent to Unvalidated Qdrant Endpoints
If the skill actually executes arbitrary subprocesses, exports API keys, and deletes local files while presenting itself as a benign RAG utility, the mismatch materially increases operational risk. In security-sensitive agent ecosystems, inaccurate declarations can bypass scrutiny and lead to over-privileged deployment.
If the skill actually executes arbitrary subprocesses, exports API keys, and deletes local files while presenting itself as a benign RAG utility, the mismatch materially increases operational risk. In security-sensitive agent ecosystems, inaccurate declarations can bypass scrutiny and lead to over-privileged deployment.
If the skill actually executes arbitrary subprocesses, exports API keys, and deletes local files while presenting itself as a benign RAG utility, the mismatch materially increases operational risk. In security-sensitive agent ecosystems, inaccurate declarations can bypass scrutiny and lead to over-privileged deployment.
The skill instructs creation and use of a plaintext .env file for embedding provider configuration and API keys. Storing secrets in a workspace path used by an agent skill increases the likelihood of accidental disclosure through logs, file reads, packaging, or other tool access.
Create the .env file like this:
echo "EMBEDDING_PROVIDER=gemini" > ./skills/filechat/.env
echo "GEMINI_API_KEY=your_key_here" >> ./skills/filechat/.env
This line directly demonstrates writing a sensitive API key into a local .env file. In the context of a document-processing skill with shell access, that secret may be exposed to other commands, subprocesses, or accidental file exfiltration.
Create the .env file like this:
echo "EMBEDDING_PROVIDER=gemini" > ./skills/filechat/.env
echo "GEMINI_API_KEY=your_key_here" >> ./skills/filechat/.env
Google Workspace Authentication:
The command deletes a path derived from <FOLDER_ID> without any visible sanitization or path restriction checks. If the folder identifier is attacker-controlled or malformed, this pattern can enable unintended file deletion or shell/path manipulation when used by an agent or copied into scripts.
Note: Syncs are highly incremental and use a local cache! If a file hasn't been modified in Drive, the script will skip it instantly and output "0 chunks" embedded. This is NORMAL behavior. If you are debugging, testing, or the user specifically requests a hard flush, you MUST delete the cache files first:
rm ./skills/filechat/meta_<FOLDER_ID>.json
rm ./skills/filechat/vector_db_<FOLDER_ID>.json
This deletion command has the same unsafe parameterization issue for the vector database file. In a skill that handles persistent state and potentially sensitive document embeddings, unintended deletion can cause loss of data availability and integrity.
Note: Syncs are highly incremental and use a local cache! If a file hasn't been modified in Drive, the script will skip it instantly and output "0 chunks" embedded. This is NORMAL behavior. If you are debugging, testing, or the user specifically requests a hard flush, you MUST delete the cache files first:
rm ./skills/filechat/meta_<FOLDER_ID>.json
rm ./skills/filechat/vector_db_<FOLDER_ID>.json
Combining multiple rm -f targets with an interpolated <FOLDER_ID> inside a validation workflow amplifies the risk of destructive misuse. Because it is presented as a routine test step, an operator or agent may execute it with untrusted or mistaken input, causing broader file deletion than intended.
(If this fails, check folder permissions or GWS credentials.) 3. Force a Clean Sync: Clear the cache for the test folder to guarantee a fresh run, then sync.
rm -f ./skills/filechat/meta_<FOLDER_ID>.json ./skills/filechat/vector_db_<FOLDER_ID>.json
node ./skills/filechat/sync.js <FOLDER_ID>
(You should see files being downloaded, OCR'd, and chunks being embedded. If it says "0 chunks", verify the folder isn't empty.)
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const fs = require('fs');
const path = require('path');
const { QdrantClient } = require('@qdrant/js-client-rest');
require('dotenv').config({ path: path.join(__dirname, '.env') });
const folderArg = process.argv[2];
const query = process.argv[3];
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const fs = require('fs');
const path = require('path');
const { QdrantClient } = require('@qdrant/js-client-rest');
require('dotenv').config({ path: path.join(__dirname, '.env') });
const folderArg = process.argv[2];
const query = process.argv[3];
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const fs = require('fs');
describe('FileChat RAG Skill', () => {
const credentialsPath = path.join(__dirname, 'credentials.json');
beforeAll(() => {
// Ensure we have the credentials to authenticate GWS CLI
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const fs = require('fs');
describe('FileChat RAG Skill', () => {
const credentialsPath = path.join(__dirname, 'credentials.json');
beforeAll(() => {
// Ensure we have the credentials to authenticate GWS CLI
Injecting a hardcoded API key into the environment without any safeguards is a true credential exposure issue, not merely a documentation problem. The key is plainly recoverable from source and can be reused by anyone with repository access, making the skill more dangerous because it touches external services and may run in shared CI or developer environments.
The README advertises recursive Google Drive syncing, OCR of images, embedding, and persistent local vector storage, but it does not warn users that potentially sensitive document contents will be copied, transformed, and retained locally. In this context, the omission is security-relevant because users may unknowingly index private files, including data reachable through subfolders and shortcuts, creating confidentiality and retention risks.
The skill declares no explicit tool scope or allowed-tools despite requiring environment access, package installation, network access, and Google Drive operations. This increases the chance of overbroad execution and makes it harder to constrain what the agent may do when handling sensitive documents and credentials.
The trigger conditions are broad enough that the skill may activate on generic user requests about files, saving, retrieval, or syncing. In a skill with Drive access, upload/download behavior, and indexing, accidental invocation could cause unintended document access, storage, or modification.
Using npx @googleworkspace/cli without pinning a specific version causes runtime retrieval of whatever package version is current, creating a supply-chain risk. A malicious or compromised upstream release could execute arbitrary code in the agent environment with access to local files, OAuth tokens, and document data.
This invocation again relies on an unpinned npx package fetch for authentication flow. Because it is used during login, compromise here would be especially sensitive: the executed code could intercept tokens or manipulate OAuth behavior.
The instructions tell the agent to delete cache/index files as part of debugging or hard flush without requiring user confirmation or emphasizing data-loss consequences. In practice, this can destroy local indexing state and backups, causing availability loss and potentially forcing reprocessing of sensitive documents.