Back to skill

Security audit

Docker Osx

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it starts a high-trust macOS VM container with risky network exposure and weak supply-chain controls.

Install only on a dedicated, trusted Linux host where Docker/KVM use is acceptable. Prefer a reviewed and pinned Docker-OSX image digest, bind SSH/VNC to localhost or firewall them tightly, change or disable the default password, avoid the `curl | sh` Docker install shortcut, and treat `stop macos` as removing the container rather than merely pausing it.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:58
Finding
Unverified Remote Installation Script Piped Directly to a Shell<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:55-58`; `scripts/docker_osx.py:29-35` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### Vulnerable Code `SKILL.md:55-58`: ```markdown | Error | Fix | |-------|-----| | KVM not available | Server needs hardware virtualization | | Docker not installed | `curl -sSL get.docker.com | sh` | ``` `scripts/docker_osx.py:29-35`: ```python if not check_docker(): return { 'success': False, 'error': 'Docker not installed. Install with: curl -sSL get.docker.com | sh' } ``` ### Technical Analysis The documentation and runtime error instruct users to download a mutable remote response and immediately execute it with `sh`. The content is not inspected, pinned to a version, checked against a cryptographic digest, or verified using a digital signature. The Python program does not automatically execute this command. Exploitation therefore requires a user or automation layer to follow the displayed instruction. Nevertheless, piping a remote response directly into a shell establishes a code-execution channel whose effective payload can change after this Skill has been reviewed. Although `get.docker.com` is associated with Docker's convenience installation script, reliance on the current content of a remote endpoint introduces supply-chain and delivery-path risk. Installing Docker can also modify package repositories, install system packages and services, and commonly requires root or `sudo` privileges. This exceeds the minimum privileges needed by the Skill itself because its metadata already declares Docker as a prerequisite. ### Attack Path 1. A user invokes the Skill on a host where Docker is unavailable. 2. The Skill returns the `curl -sSL get.docker.com | sh` installation instruction. 3. The user executes the instruction, potentially through a privileged shell. 4. `curl` retrieves whatever content the remote endpoint supplies at that time. ...[truncated 855 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the `curl | sh` command from both the documentation and runtime error. - Continue treating Docker as a prerequisite, as already specified by the Skill metadata. - Direct users to Docker's official, platform-specific installation documentation over HTTPS. - If command-line installation instructions are necessary, use the operating system's trusted package manager and document repository-signing-key verification. - Pin downloaded installation artifacts to a reviewed version and verify a published cryptographic checksum or signature before execution. - Download scripts to a local file for inspection rather than streaming them directly into a shell. - Clearly state when installation requires administrative privileges and require explicit user approval before any privileged system modification. ]]>

T08 · Insecure Dependencies

Error
Location
scripts/docker_osx.py:11
Finding
Mutable Third-Party Container Image Executed with KVM Device Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/docker_osx.py:11`; `scripts/docker_osx.py:50-58` **Vulnerability Type**: Unpinned third-party runtime dependency **Risk Level**: High ### Vulnerable Code `scripts/docker_osx.py:11`: ```python IMAGE = "sickcodes/docker-osx:stable" ``` `scripts/docker_osx.py:50-58`: ```python # Start container result = subprocess.run([ 'docker', 'run', '-d', '--device', '/dev/kvm', '-p', '50922:10022', '-p', '5900:5900', '--name', CONTAINER_NAME, IMAGE ], capture_output=True, text=True) ``` ### Technical Analysis The container dependency is referenced using the mutable `stable` tag rather than an immutable content digest. A registry tag can be reassigned to different image content without changing this repository. Consequently, the code executed by future Skill invocations may differ from the image reviewed during an audit. Docker retrieves the tagged image when it is not present locally. The resulting container receives access to `/dev/kvm` and has network services published on the host. KVM access is functionally necessary for the declared macOS virtualization feature, but combining privileged device access with an unpinned third-party image weakens supply-chain assurance. This finding does not establish that the current `sickcodes/docker-osx` image is malicious. The vulnerability is the absence of immutable version and integrity control for a security-sensitive runtime dependency. ### Attack Path 1. An attacker compromises the upstream image publisher, registry account, or image distribution process. 2. The attacker replaces the image referenced by `sickcodes/docker-osx:stable` with altered content. 3. A user invokes the Skill on a host where the changed image is pulled, or manually updates the tagged image. 4. Docker starts the altered image and grants it access to `/dev/kvm`. 5. The altered container can execute attacker-selected code inside the container, communicate over the n ...[truncated 819 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the reviewed image to an immutable digest, for example: ```python IMAGE = "sickcodes/docker-osx@sha256:<reviewed-digest>" ``` - Record the corresponding upstream version and provenance in `SKILL.md`. - Establish an explicit update procedure in which each new image digest is reviewed and tested before release. - Use image-signature or provenance verification, such as Sigstore/Cosign, where supported. - Run the container with the smallest feasible capability set and retain only the KVM device access necessary for virtualization. - Apply Docker daemon, kernel, KVM, and container-runtime security updates promptly. - Consider enforcing an image allowlist or admission policy so a mutable tag cannot silently replace the approved artifact. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/docker_osx.py:50
Finding
SSH and VNC Exposed on All Interfaces with a Documented Default Password<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:33-36`; `scripts/docker_osx.py:50-67` **Vulnerability Type**: Insecure network exposure and hardcoded default credential **Risk Level**: High ### Vulnerable Code `SKILL.md:33-36`: ```markdown ## Connection - **SSH**: port 50922, password: `alpine` - **VNC**: port 5900 ``` `scripts/docker_osx.py:50-67`: ```python # Start container result = subprocess.run([ 'docker', 'run', '-d', '--device', '/dev/kvm', '-p', '50922:10022', '-p', '5900:5900', '--name', CONTAINER_NAME, IMAGE ], capture_output=True, text=True) if result.returncode == 0: return { 'success': True, 'message': '🚀 macOS VM starting!', 'details': 'Takes 2-5 minutes to boot. Use "status macos" to check.', 'ssh': 'ssh -p 50922 user@localhost', 'vnc': 'vnc://localhost:5900', 'password': 'alpine' } ``` ### Technical Analysis Docker port-publishing rules that omit a host address normally bind to all host interfaces, subject to daemon configuration. The Skill publishes host ports `50922` and `5900` in this manner while presenting connection strings using `localhost`. The actual exposure can therefore be broader than the user-facing output suggests. The Skill also documents and returns the fixed password `alpine`. A credential embedded in public Skill code is not secret and cannot provide meaningful protection against network attackers. If the corresponding SSH or VNC service accepts this default password, any party that can reach the published port can attempt to authenticate with a known credential. VNC may additionally lack transport encryption depending on the image's configuration. The audited code does not establish the image's precise authentication or encryption behavior, so exploitation is conditional on the services using the documented credential and being network-reachable. ### Attack Path 1. A user starts the macOS container on a host connecte ...[truncated 1226 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Bind both published ports explicitly to loopback: ```python '-p', '127.0.0.1:50922:10022', '-p', '127.0.0.1:5900:5900', ``` - If remote access is required, expose services only through an authenticated VPN, SSH tunnel, or tightly restricted firewall rule. - Replace the fixed password with a unique, randomly generated credential for each deployment. - Prefer SSH public-key authentication and disable password authentication where the image supports it. - Do not print reusable plaintext passwords in normal command output or documentation. - Confirm that VNC authentication and transport encryption are enabled; otherwise, require a secure tunnel. - Warn users when ports are published and clearly report the actual bind addresses. - Add automated checks that reject wildcard port bindings unless the user explicitly opts in after receiving a security warning. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Privileged Container / Container Escape

High
Category
Privilege Escalation
Content
if not check_kvm():
        return {
            'success': False,
            'error': 'KVM not available. This server does not support hardware virtualization (--device /dev/kvm required).'
        }
    
    if not check_docker():
Confidence
98% confidence
Finding
This skill is specifically designed to start a macOS VM and therefore intentionally grants the container access to /dev/kvm, a privileged host device, while also pulling and running a third-party image. In an automated agent context, exposing hardware virtualization to a container significantly raises the blast radius of a compromised or malicious image and can weaken host isolation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill documents shell-capable operations (`start`, `stop`, `ssh`, `logs`) but does not declare any tool scope or allowed-tools boundary. That omission weakens enforcement and review, making it easier for an agent to invoke shell actions beyond what users expect, especially in a high-privilege context involving Docker and KVM.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The documentation exposes a default SSH password (`alpine`) for a reachable service on port 50922 without any warning or requirement to rotate it. In a Docker/KVM-based macOS VM workflow, this creates a straightforward credential exposure path that can enable unauthorized access if the port is accessible locally, remotely, or through port forwarding.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def check_docker():
    """Check if Docker is installed"""
    result = subprocess.run(['docker', '--version'], capture_output=True)
    return result.returncode == 0

def start_macos():
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
}
    
    # Check if already running
    result = subprocess.run(['docker', 'ps', '--filter', f'name={CONTAINER_NAME}', '--format', '{{.ID}}'], 
                          capture_output=True, text=True)
    if result.stdout.strip():
        return {
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
}
    
    # Remove old container if exists
    subprocess.run(['docker', 'rm', '-f', CONTAINER_NAME], capture_output=True)
    
    # Start container
    result = subprocess.run([
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
subprocess.run(['docker', 'rm', '-f', CONTAINER_NAME], capture_output=True)
    
    # Start container
    result = subprocess.run([
        'docker', 'run', '-d',
        '--device', '/dev/kvm',
        '-p', '50922:10022',
Confidence
95% confidence
Finding
Although the subprocess usage itself is safe from shell injection, this call launches a Docker container with direct access to /dev/kvm and exposes SSH and VNC services on the host. In the context of an agent skill that starts infrastructure automatically, this materially increases attack surface and grants a highly sensitive device to an unpinned third-party image.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The stop action unconditionally removes the container after stopping it, but the user-facing interface describes this as a simple stop operation. In this skill context, that can cause unexpected data loss or loss of build artifacts, which is especially risky for users relying on the VM for iOS development work.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def stop_macos():
    """Stop macOS container"""
    result = subprocess.run(['docker', 'stop', CONTAINER_NAME], capture_output=True, text=True)
    subprocess.run(['docker', 'rm', CONTAINER_NAME], capture_output=True)
    
    return {
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def stop_macos():
    """Stop macOS container"""
    result = subprocess.run(['docker', 'stop', CONTAINER_NAME], capture_output=True, text=True)
    subprocess.run(['docker', 'rm', CONTAINER_NAME], capture_output=True)
    
    return {
        'success': True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def status_macos():
    """Check macOS status"""
    result = subprocess.run([
        'docker', 'ps', '--filter', f'name={CONTAINER_NAME}', 
        '--format', '{{.Status}}|{{.Ports}}'
    ], capture_output=True, text=True)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def logs_macos():
    """Get macOS logs"""
    result = subprocess.run(['docker', 'logs', '-f', '--tail', '50', CONTAINER_NAME], 
                          capture_output=True, text=True, timeout=30)
    return {
        'success': True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

External Script Fetching

Low
Category
Supply Chain
Content
| Error | Fix |
|-------|-----|
| KVM not available | Server needs hardware virtualization |
| Docker not installed | `curl -sSL get.docker.com | sh` |

## Resources
Confidence
94% confidence
Finding
The skill recommends `curl -sSL get.docker.com | sh`, which fetches and executes a remote script without verification. If the remote host, transport, DNS, or distribution path is compromised, users may execute attacker-controlled code directly on the host system.

External Script Fetching

Low
Category
Supply Chain
Content
if not check_docker():
        return {
            'success': False,
            'error': 'Docker not installed. Install with: curl -sSL get.docker.com | sh'
        }
    
    # Check if already running
Confidence
86% confidence
Finding
The code returns an installation instruction that pipes a remote script directly into a shell. Even though it is not executed automatically by this script, suggesting this pattern encourages insecure operator behavior and could lead to arbitrary code execution if the remote source is compromised or intercepted.

Static analysis

No suspicious patterns detected.