T09 · Insecure Skill Coding Practices
- Location
sync.js:16- Finding
Shell Command Injection Through Interpolated Drive Identifiers
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
FileChat has a coherent document-search purpose, but it broadly copies and indexes Drive documents, sends document and query content to Gemini, and keeps sensitive text locally with weak containment.
Review this skill before installing. Only point it at a Drive folder whose contents you are comfortable copying into a local plaintext index and sending to Google Gemini for embeddings and image OCR. Protect the .env file and vector_db.json, avoid highly sensitive folders unless you accept that data flow, and prefer a version with explicit confirmation, scoped sync controls, pinned dependencies, safer command execution, and a documented delete/flush process.
sync.js:16Shell Command Injection Through Interpolated Drive Identifiers
sync.js:20Unpinned Runtime Package Retrieval and Execution
sync.js:112Predictable Temporary Files Permit Data Exposure and Path Manipulation
sync.js:127Sensitive Document Contents and Drive Identifiers Stored in Plaintext
The skill description advertises recursive download of all files, OCR of image contents, embedding with Gemini, and storage in a persistent local vector database, but it does not clearly warn users that sensitive document contents may be extensively copied, processed, retained locally, and partially transmitted to an external AI provider. In a document-ingestion skill, this omission is especially dangerous because users may trigger bulk processing of private files without understanding the scope of access or data handling.
If only sync/indexing is implemented while search, retrieval, and storage semantics differ from the description, the skill is overclaiming functionality and underdisclosing processing details such as Gemini multimodal/OCR use. In a document-handling skill, undeclared content extraction and alternate persistence mechanisms materially increase privacy and compliance risk.
If only sync/indexing is implemented while search, retrieval, and storage semantics differ from the description, the skill is overclaiming functionality and underdisclosing processing details such as Gemini multimodal/OCR use. In a document-handling skill, undeclared content extraction and alternate persistence mechanisms materially increase privacy and compliance risk.
If only sync/indexing is implemented while search, retrieval, and storage semantics differ from the description, the skill is overclaiming functionality and underdisclosing processing details such as Gemini multimodal/OCR use. In a document-handling skill, undeclared content extraction and alternate persistence mechanisms materially increase privacy and compliance risk.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Create the .env file like this:
echo "GEMINI_API_KEY=your_key_here" > ./skills/filechat/.env
echo "FILECHAT_DRIVE_FOLDER_ID=your_folder_id_here" >> ./skills/filechat/.env
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Create the .env file like this:
echo "GEMINI_API_KEY=your_key_here" > ./skills/filechat/.env
echo "FILECHAT_DRIVE_FOLDER_ID=your_folder_id_here" >> ./skills/filechat/.env
This code adds image OCR by sending image content to Gemini, which is outside the manifest’s stated purpose of securely searching and chatting with documents stored in a designated Google Drive folder using local RAG. That capability expansion matters because images may contain sensitive user data, and transmitting them to an external model service introduces a new data flow and privacy boundary not disclosed by the skill description.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const fs = require('fs');
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '.env') });
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
const DB_PATH = path.join(__dirname, 'vector_db.json');
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const fs = require('fs');
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '.env') });
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
const DB_PATH = path.join(__dirname, 'vector_db.json');
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const DB_PATH = path.join(__dirname, 'vector_db.json');
if (!GEMINI_API_KEY) {
console.error("Missing GEMINI_API_KEY in .env");
process.exit(1);
}
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const DB_PATH = path.join(__dirname, 'vector_db.json');
if (!GEMINI_API_KEY) {
console.error("Missing GEMINI_API_KEY in .env");
process.exit(1);
}
Downloaded document contents are transmitted to Google's embedding APIs without any explicit warning, consent flow, or prominent disclosure. In a file-search skill handling potentially sensitive user documents, silent third-party transfer materially increases privacy and compliance risk and could expose regulated or confidential content.
Image files are base64-encoded and sent to a generative AI service for OCR without explicit disclosure. This is especially sensitive because images may contain scanned IDs, signatures, medical records, or other high-risk content that users may not expect to leave the storage environment.
The README instructs users to simply tell the agent to 'sync', which is an extremely generic trigger for a high-impact operation. In this skill's context, 'sync' causes recursive download, OCR, embedding, and persistent local indexing of an entire Google Drive folder, so an ambiguous activation phrase increases the chance of accidental or contextually unintended execution.
The skill declares shell commands that read environment variables, perform networked Google Drive and Gemini operations, and write local files, but it does not declare any explicit tool scope or allowed-tools restrictions. This weakens least-privilege controls and increases the chance the agent can invoke broader capabilities than users expect.
The sync flow downloads and locally indexes all files from the configured Google Drive folder, but the instructions do not prominently warn the user that broad local replication and embedding/index creation will occur. In a knowledge skill operating on possibly sensitive documents, this is a meaningful privacy risk because users may assume remote-only search.
The skill instructs downloading a Drive file to /workspace and then sending it back to the user, but it does not require a clear user-facing warning that a local copy will be created. For sensitive documents, silent local persistence increases exposure through residual files, backups, or later unintended access by other tasks.
The skill description emphasizes local persistent ChromaDB indexing for Google Drive documents, but this file initializes an external Gemini API client using an environment API key. That creates an unjustified outbound dependency and potential exfiltration path for document-derived content, weakening the expectation that processing is local and contained.
At this call site, image content is sent to an external AI service for transcription with no visible warning, consent flow, or disclosure. In the context of a file storage and retrieval skill, users may reasonably expect their stored files to remain within the documented Drive/local RAG boundary, so silent transmission of image contents increases privacy and compliance risk.
The skill sends the user's raw query text to Google's Gemini embedding API, which is an external network service, without any visible notice, consent flow, or minimization step. In a document-search skill, user queries may contain sensitive document names, personal data, or confidential business content, so silent transmission to a third party creates a real privacy and data-handling risk.
The stated purpose is document storage, retrieval, and semantic search over a designated Drive folder. Implementing this by spawning shell commands introduces a broader execution capability than is necessary for that purpose and is not declared in the manifest.
The code loads and accesses GEMINI_API_KEY from a local .env file, which is a sensitive credential operation covered by the warning rule. While it errors when variables are missing, it does not include comments or user guidance about the sensitivity of these credentials or safe handling expectations.
The manifest states that the skill indexes documents into a local persistent ChromaDB instance. This code instead accumulates embeddings in memory and writes them to vector_db.json, which is a different storage mechanism than the one described.
The script executes npx @googleworkspace/cli without pinning an exact package version, so each run may fetch whatever version is currently published. That creates a supply-chain risk: a compromised or breaking upstream release could execute unintended code with the script's privileges and access to Google Drive data.
This second invocation has the same issue: unpinned npx execution allows an upstream package change or compromise to affect production behavior at runtime. Because this path downloads file contents, exploitation could expose sensitive documents or run attacker-controlled code.
Detected: suspicious.dangerous_exec