T09 · Insecure Skill Coding Practices
- Location
scripts/check_environment.py:46- Finding
Shell Command Injection Through Filesystem-Derived Python Interpreter Paths
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly aligned with YOLO vision work, but it includes a runnable diagnostics script with a real shell-injection risk and installation examples that use mutable remote packages and container images.
Review before installing. Use a virtual environment, pin package versions and container digests, avoid GitHub @main installs and Docker --ipc=host unless you accept the tradeoff, and do not run scripts/check_environment.py until its shell=True path handling is fixed. Treat generated YOLO outputs and environment reports as potentially sensitive, and keep W&B dataset upload disabled unless you intentionally want third-party upload.
scripts/check_environment.py:46Shell Command Injection Through Filesystem-Derived Python Interpreter Paths
SKILL.md:177Mutable and Unpinned Third-Party Installation Instructions
The skill's stated purpose does not clearly disclose local model-file inspection, cache enumeration/deletion under ~/.cache/ultralytics, benchmarking utilities, or dummy inference for validation. Cache deletion and filesystem inspection introduce destructive and privacy-sensitive behaviors that are more dangerous than ordinary end-user vision inference.
The skill's stated purpose does not clearly disclose local model-file inspection, cache enumeration/deletion under ~/.cache/ultralytics, benchmarking utilities, or dummy inference for validation. Cache deletion and filesystem inspection introduce destructive and privacy-sensitive behaviors that are more dangerous than ordinary end-user vision inference.
The skill's stated purpose does not clearly disclose local model-file inspection, cache enumeration/deletion under ~/.cache/ultralytics, benchmarking utilities, or dummy inference for validation. Cache deletion and filesystem inspection introduce destructive and privacy-sensitive behaviors that are more dangerous than ordinary end-user vision inference.
Referenced artifact was not completely inspected
ces/environment_check.md) or use the provided environment check script: `python scripts/check_environment.py`.
Referenced artifact was not completely inspected
ces/environment_check.md) or use the provided environment check script: `python scripts/check_environment.py`.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
def run_command(cmd):
"""Execute command and return output"""
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return result.stdout.strip() if result.returncode == 0 else f"Error: {result.stderr.strip()}"
except Exception as e:
return f"Exception: {str(e)}"
The guide recommends direct installation from GitHub via pip install git+https://..., which executes build/install logic from a remote repository at install time. Even when the repository is legitimate, this bypasses the stronger stability and review expectations of registry releases and raises supply-chain risk, especially when tracking a branch like @main.
==8.4.0
pip install -U ultralytics
### 2. Install from Source (Development Version)
If you need the latest development features or want to modify source code:
```bash
# Clone repository
git clone https://github.com/ultralytics/ultralytics.git
cd ultralytics
# Install in editable mode (development environment)
pip install -e .
# Or install directly from GitHub
pip install git+https://github.com/ultralytics/ultralytics.git
# Install from specific branch
pip install git+https://github.com/ultralytics/ultralytics.git@main
# Create new environment (optional)
conda create -n yolo python=3.10
conda activate yolo
# Install via conda-forge
conda install -c conda-forge ultralytics
# Or install PyTorch first, then ultralytics
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia
pip install ultralytics
# Install all packages together (CUDA environment)
conda install
Using --ipc=host shares the host IPC namespace with the container, weakening isolation and increasing the blast radius if the containerized workload or image is compromised. In multi-tenant or sensitive environments, this can expose inter-process communication resources and facilitate container breakout-adjacent abuse or host-level data exposure.
docker pull ultralytics/ultralytics:latest
# Run container with GPU support
docker run -it --ipc=host --runtime=nvidia --gpus all ultralytics/ultralytics:latest
# Mount local directory and run
docker run -it --rm --gpus all -v $(pwd):/workspace ultralytics/ultralytics:latest
This command again uses --ipc=host, which reduces container isolation by exposing the host IPC namespace to the container. If the container image, dependencies, or invoked code are malicious or vulnerable, this setting can materially increase impact compared with a default-isolated container.
docker run -it --rm --gpus all -v $(pwd):/workspace ultralytics/ultralytics:latest
docker run -it --ipc=host --runtime=nvidia --gpus '"device=2,3"' ultralytics/ultralytics:latest
Available Docker images:
This is the same underlying issue as the AST4 finding at line 26, but the TM1 classification correctly highlights abuse potential: a generic command runner with shell=True can become a powerful execution primitive if any untrusted data reaches it. In an agent skill context, such helpers are especially risky because later integrations often pass variable strings into reusable utilities.
def run_command(cmd):
"""Run command and return output"""
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
return result.stdout.strip()
except subprocess.CalledProcessError as e:
return f"Error: {e.stderr.strip()}"
This finding is valid because the code composes a shell command from path data and executes it during environment discovery. Any attacker who can influence scanned directory names or interpreter paths could potentially inject additional shell syntax, turning a diagnostics feature into arbitrary command execution.
try:
# Check if Python exists and can run
cmd = f'"{path}" -c "import sys; print(sys.version.split()[0])"'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=2)
if result.returncode == 0:
version = result.stdout.strip()
The skill documentation describes capabilities that imply shell execution, network access, and file read/write behavior, but it does not declare any explicit tool scope or permissions boundaries. That makes the effective privilege surface opaque to users and reviewers, increasing the risk that an agent invokes filesystem or command-execution behaviors beyond what the user expected from an image-analysis skill.
The manifest description limits the skill to performing vision tasks like detection, classification, pose estimation, and tracking on images and videos. In contrast, this section expands the skill into model training on custom datasets, which is a distinct model-development capability rather than straightforward inference or analysis.
The documentation states that the skill will automatically create directories, copy inputs, and save outputs and reports, but it does not prominently warn users that their local files may be duplicated and persisted. This can expose sensitive images, videos, paths, metadata, or analysis artifacts on disk longer than intended, especially in shared workspaces.
The document instructs users to generate a detailed environment report containing Python version, platform details, package versions, CUDA/GPU information, and other host metadata, and explicitly notes JSON report generation for sharing. While this is framed as troubleshooting guidance, it lacks any warning to review/redact sensitive details before sharing, which can expose system fingerprints useful for targeted attacks or unnecessary disclosure of internal environment information.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
curl -I https://ultralytics.com/images/bus.jpg
curl -I https://api.github.com/repos/ultralytics/ultralytics
## Summary
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
The documentation exposes an upload_dataset parameter that can send datasets to Weights & Biases but provides no warning that training datasets may contain sensitive, proprietary, or regulated data. In a vision skill, datasets commonly include images of people, facilities, documents, or other confidential material, so silently normalizing upload behavior increases the risk of unintentional data disclosure to a third-party service.
This helper executes arbitrary shell commands via subprocess.run(..., shell=True). Although current call sites use hardcoded strings, the function is generic and accepts unsanitized command text, so any future or indirect user-controlled input would become shell-injection-capable. In a diagnostic skill that probes the host environment, command execution is especially sensitive because it runs on the analyst's machine and can expose or alter system state.
def run_command(cmd):
"""Run command and return output"""
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
return result.stdout.strip()
except subprocess.CalledProcessError as e:
return f"Error: {e.stderr.strip()}"
The script builds a shell command from discovered interpreter paths and executes it with shell=True. While many paths are from fixed locations, some are derived from filesystem enumeration under user-writable directories such as ~/.virtualenvs; a crafted path containing shell metacharacters or quotes could break command boundaries and lead to command injection. The environment-enumeration context increases risk because the script intentionally scans and executes multiple local interpreters.
try:
# Check if Python exists and can run
cmd = f'"{path}" -c "import sys; print(sys.version.split()[0])"'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=2)
if result.returncode == 0:
version = result.stdout.strip()
This call repeats the same pattern of shell execution with a command string built from an enumerated Python path. If a discovered path contains shell metacharacters or malformed quoting, the shell can interpret injected commands when probing for ultralytics. Because this script explores multiple host environments, exploitation could result in arbitrary command execution during a seemingly harmless diagnostics run.
version = result.stdout.strip()
# Try to import ultralytics in this environment
ultralytics_check = subprocess.run(
f'"{path}" -c "import ultralytics; print(ultralytics.__version__)"',
shell=True, capture_output=True, text=True, timeout=2
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
from ultralytics import YOLO
# Check if yolo command is available
yolo_check = subprocess.run(
["yolo", "checks"],
capture_output=True,
text=True,
No suspicious patterns detected.