Back to skill

Security audit

Data Cleaning & Annotation Workflow

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed dataset-preparation workflow, but its downloader can delete or overwrite unrelated files in the chosen output folder and the upload guidance lacks privacy/licensing safeguards.

Install only if you intend to use this specific Kaggle-to-data.smlcrm.com workflow. Use a fresh empty output directory for downloads, review any dataset license and sensitivity before uploading it to the external platform, and install Kaggle tooling in a virtual environment with secure credential handling.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/download_kaggle.sh:29
Finding
Wildcard Archive Handling Can Delete or Overwrite Unrelated Files## Vulnerability Details **File Location**: `scripts/download_kaggle.sh`, lines 29-35 **Vulnerability Type**: Unsafe wildcard extraction and deletion **Risk Level**: Medium **Vulnerable Code**: ```bash # Unzip if downloaded successfully if [ $? -eq 0 ]; then echo "Download successful. Extracting..." cd "$OUTPUT_DIR" unzip -q *.zip rm *.zip echo "Dataset ready in: $OUTPUT_DIR" ``` ### Technical Analysis The script uses the `*.zip` wildcard for both archive extraction and deletion. Consequently, it does not restrict these operations to the archive downloaded by the current Kaggle command. If the output directory contains multiple ZIP files, shell expansion passes all matching names to `unzip`. The `unzip` utility does not reliably interpret multiple positional ZIP names as independent archives; additional names may instead be treated as archive member patterns. More importantly, the subsequent `rm *.zip` command deletes every matching archive regardless of whether each archive was downloaded by this execution or successfully extracted. Archive contents are also extracted directly into the selected output directory without checking entry paths, detecting collisions, or preventing replacement of existing files. The exact overwrite and path traversal behavior depends on the installed `unzip` implementation, but the script itself provides no protective validation. ### Attack Path 1. A user selects an output directory that already contains one or more unrelated ZIP archives. 2. Alternatively, another local process or user with write access places an archive in that directory before extraction. 3. The Kaggle download completes successfully, causing the script to enter the extraction branch. 4. `unzip -q *.zip` operates on the wildcard expansion rather than a specifically identified downloaded file. 5. Extraction may overwrite files in the output directory, depending on archive contents and `unzip` ...[truncated 1003 chars]
Remediation
## Remediation Suggestions - Create a unique temporary directory for every download using `mktemp -d`. - Capture or deterministically construct the exact downloaded archive path. - Never use `*.zip` for destructive operations. - List and validate archive entries before extraction. Reject absolute paths, parent-directory traversal components, symbolic links, and other unsafe entries. - Extract into a newly created destination directory with no-overwrite behavior where supported. - Delete only the exact archive created by the current operation. - Delete the archive only after extraction and validation have completed successfully. - Check the results of `cd`, `unzip`, and `rm`, or enable strict shell behavior with appropriate error handling. Example hardening pattern: ```bash set -euo pipefail mkdir -p -- "$OUTPUT_DIR" OUTPUT_DIR="$(cd -- "$OUTPUT_DIR" && pwd)" WORK_DIR="$(mktemp -d "$OUTPUT_DIR/.kaggle-download.XXXXXX")" trap 'rm -rf -- "$WORK_DIR"' EXIT kaggle datasets download -d "$DATASET_NAME" -p "$WORK_DIR" mapfile -d '' archives < <(find "$WORK_DIR" -maxdepth 1 -type f -name '*.zip' -print0) if [ "${#archives[@]}" -ne 1 ]; then echo "Expected exactly one downloaded ZIP archive" >&2 exit 1 fi archive="${archives[0]}" if unzip -Z1 "$archive" | grep -Eq '(^/|(^|/)\.\.(/|$))'; then echo "Archive contains unsafe paths" >&2 exit 1 fi unzip -q -n -- "$archive" -d "$OUTPUT_DIR" rm -- "$archive" ```

T08 · Insecure Dependencies

Note
Location
SKILL.md:64
Finding
Unpinned Kaggle Dependency Creates a Supply-Chain Risk## Vulnerability Details **File Location**: `SKILL.md`, line 64 **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Low **Vulnerable Code**: ```bash # Install if needed: pip install kaggle ``` ### Technical Analysis The documented installation command installs whichever `kaggle` package release the configured Python package index considers current at execution time. It does not pin a reviewed version, verify package hashes, identify a trusted index, or use a lock file. Python packages can execute code during installation and when their modules or command-line entry points are invoked. Therefore, the effective code trusted by this workflow can change after the Skill has been reviewed. The package name is legitimate and there is no evidence that the project intentionally introduces a malicious dependency; the issue is the lack of reproducible dependency controls. ### Attack Path 1. A user follows the Skill instructions and runs `pip install kaggle`. 2. `pip` resolves the package using the user's configured package indexes and selects an unpinned release. 3. If an upstream release, package index, mirror, or local package-resolution configuration is compromised, malicious package code may be returned. 4. Installation hooks or subsequently invoked Kaggle CLI code execute with the permissions of the installing user. 5. That code can access resources available to the user, potentially including Kaggle credentials used by the CLI. This path requires compromise or manipulation of the dependency supply chain; no such compromise is present in the audited project itself. ### Impact Assessment A compromised dependency would execute with the privileges of the user performing the installation or running the Kaggle CLI. Depending on the environment, this could permit: - Reading or modifying files accessible to that user. - Accessing Kaggle API credentials available to the CLI. - Performing n ...[truncated 271 chars]
Remediation
## Remediation Suggestions - Pin the Kaggle package to a specific version that has been reviewed and tested. - Record cryptographic hashes in a requirements file and install with `--require-hashes`. - Use a lock file or equivalent reproducible dependency mechanism. - Explicitly use a trusted package index and avoid untrusted extra indexes. - Install the dependency in a dedicated virtual environment rather than globally. - Do not recommend elevated installation unless it is strictly necessary. - Establish a controlled process for reviewing and updating the pinned version. Example documentation: ```bash python3 -m venv .venv . .venv/bin/activate python3 -m pip install --require-hashes -r requirements.txt ``` The corresponding `requirements.txt` should pin an audited version and include all required hashes: ```text kaggle==REVIEWED_VERSION \ --hash=sha256:VERIFIED_DISTRIBUTION_HASH ```
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description promises a full workflow spanning dataset acquisition, cleaning, platform upload, metadata configuration, unit setting, grouping, and status progression. The supplied code only performs a narrow subset: basic local CSV cleaning and summary printing. There is no network access, no Kaggle integration, no interaction with data.smlcrm.com, and no logic for metadata/schema/unit/group configuration. While the cleaning portion is consistent with part of the description, the overall declared purpose materially overstates the implemented behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description promises a full Kaggle-to-annotation-platform workflow for time series datasets, including cleaning, uploading, metadata configuration, column typing, unit setting, group assignment, and completion to CLEAN status. The supplied code only implements a narrow initial step: downloading and extracting a Kaggle dataset locally. While downloading is one part of the stated workflow, the code lacks all of the core downstream behaviors that define the declared purpose. Therefore the description materially overstates what this code chunk actually does.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The manifest description says to use the skill for broad activities like 'finding Kaggle datasets,' 'cleaning for ML,' and 'uploading with metadata,' which overlap with many ordinary data-preparation tasks. It does not define specific trigger phrases, boundaries, or exclusion conditions, increasing the chance of unintended invocation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs users to upload datasets to an external platform without warning about privacy, confidentiality, licensing, or data-sharing restrictions. In context, this increases the chance that users transfer sensitive, proprietary, or regulated data to a third-party service without proper authorization, creating data exposure and compliance risk.

Vague Triggers

Low
Confidence
82% confidence
Finding
The introduction presents the skill as a generic 'end-to-end workflow for time series dataset preparation and annotation' without clarifying the exact context in which it should activate. Because the scope is described functionally rather than through specific triggers or constraints, users or systems may over-apply it to unrelated dataset workflows.

Missing User Warnings

Low
Confidence
81% confidence
Finding
The Kaggle CLI guidance omits credential-handling precautions, which can lead users to store API tokens insecurely or expose them in shared environments. While the file does not directly exfiltrate credentials, poor setup hygiene can result in accidental token leakage and unauthorized use of the user's Kaggle account.

Static analysis

No suspicious patterns detected.