Back to skill

Security audit

Homelab Runbook

Security checks for vulnerabilities and agentic risk

Overview

This skill performs the host service inventory it advertises, with no hidden network transfer, credential access, or destructive behavior found.

Install only if you want an agent to inventory this host. Treat generated runbooks as sensitive because they can reveal services, ports, container names, images, mount names, and process details; keep reports out of public repos and shared folders, and use sudo only when you intentionally want broader port visibility.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

other

Warning
Location
scripts/generate_runbook.py:206
Finding
Host-Wide Service and Network Reconnaissance Produces a Sensitive Inventory<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/generate_runbook.py:28-46` - `scripts/generate_runbook.py:206-217` - `scripts/scan_docker.py:30-61` - `scripts/scan_services.py:16-53` - `scripts/scan_services.py:62-99` - `scripts/scan_ports.py:22-75` - `scripts/scan_ports.py:87-142` - `scripts/scan_ports.py:152-194` **Vulnerability Type**: `other: Excessive Host Reconnaissance` **Risk Level**: Medium The skill systematically collects Docker container details, running system services, listening network addresses and ports, process names, PIDs, images, container identifiers, and mount names. This behavior is consistent with the documented runbook-generation purpose, and no data exfiltration was identified. Nevertheless, the generated report is a consolidated, security-sensitive host inventory that could materially assist an attacker if exposed. ### Relevant Code Automatic scanner execution and optional persistence of the resulting report in `scripts/generate_runbook.py:28-46` and `scripts/generate_runbook.py:206-217`: ```python def run_scanner(script_name): """Run a scanner script and return its parsed JSON output.""" script = os.path.join(SCRIPTS_DIR, script_name) try: result = subprocess.run( [sys.executable, script], capture_output=True, text=True, timeout=30, ) if result.stdout.strip(): return json.loads(result.stdout) return {"error": result.stderr.strip() or "No output", "data": []} except subprocess.TimeoutExpired: return {"error": f"{script_name} timed out"} except json.JSONDecodeError as e: return {"error": f"JSON parse error: {e}"} except Exception as e: return {"error": str(e)} ``` ```python else: # Run all scanners inline print("Running scanners...", file=sys.stderr) docker_data = run_scanner("scan_docker.py") services_data = run_scanner("scan_services.py") ports_data = run_ ...[truncated 9235 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit user confirmation before performing a complete host-wide scan, particularly when it includes process ownership, PIDs, mounts, or Docker metadata. 2. Add independent command-line switches such as `--scan-docker`, `--scan-services`, and `--scan-ports`, and default to the minimum category requested by the user. 3. Minimize report contents by default: - Omit container IDs. - Redact mount information. - Exclude PIDs unless explicitly requested. - Consider omitting loopback-only listeners. - Normalize image references to avoid exposing private registry details. 4. Create output files with restrictive permissions. On POSIX systems, use an explicit mode equivalent to `0600`, or safely create the file with `os.open()` using `O_CREAT | O_WRONLY | O_TRUNC` and mode `0o600`. 5. Warn users that the generated runbook contains sensitive infrastructure information and should not be stored in public repositories, shared workspaces, or broadly readable directories. 6. Validate the destination path and optionally refuse symbolic links or non-regular files when writing reports in automated environments. 7. Avoid recommending elevated execution by default. Request `sudo` only after explicit user consent and only when privileged process visibility is essential. 8. Add configurable allowlists and exclusion filters so operators can suppress sensitive containers, services, addresses, and ports without modifying source code. 9. Consider separating collection from rendering and provide a redacted output profile suitable for routine or scheduled reports. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents a broad host-service inventory tool spanning Docker, init/system services, and network listening ports, with Markdown documentation output. The supplied code chunk is much narrower: it only interacts with the Docker CLI (`docker info`, `docker ps`) to enumerate running containers and returns structured JSON. There is no code for launchd/systemd inspection, port scanning, cron behavior, cross-platform service enumeration, or Markdown generation. This is a material description-versus-behavior mismatch because the implemented primary purpose is a Docker-only scanner, not a comprehensive machine-wide service/runbook generator.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents a broad host-service inventory and documentation tool, but the supplied code chunk implements only a network port scanner for listening TCP sockets. While port scanning is one subset of the declared behavior, the primary claimed functionality—documenting Docker containers and system services and producing a Markdown runbook with richer metadata—is absent. The actual code's purpose is materially narrower than the declared purpose, so this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The implemented code is substantially narrower than the declared description. It uses `launchctl list` on macOS and `systemctl list-units --type=service --state=running` on Linux to enumerate running system services only. Its output is JSON, not a human-readable Markdown runbook. It does not query Docker, network sockets, container images, volume mounts, or health checks, and there is no code for scheduled execution. While the description mentions macOS and Linux service scanning, the broader declared purpose materially overstates the actual behavior.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill instructs the agent to use shell execution and write a runbook file, but it does not declare any explicit tool scope or permissions. That omission weakens policy enforcement and user transparency, increasing the chance the skill runs with broader host access than intended while collecting sensitive host inventory data.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger phrases are broad enough to match common requests like 'what's running' or 'scan ports', which can cause the skill to activate in situations where the user did not clearly intend host enumeration. Because the skill gathers sensitive local infrastructure details, overbroad activation increases the risk of unnecessary reconnaissance and unintended disclosure.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill enumerates Docker containers, system services, open ports, images, mounts, PIDs, and health data, then writes them into a Markdown file, but the instructions omit a warning that this is sensitive host reconnaissance data. In context, this is especially dangerous because the output can expose internal topology, management ports, filesystem paths, and service metadata that could aid lateral movement or unauthorized access if shared or stored insecurely.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""Run a scanner script and return its parsed JSON output."""
    script = os.path.join(SCRIPTS_DIR, script_name)
    try:
        result = subprocess.run(
            [sys.executable, script],
            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 docker_available():
    try:
        result = subprocess.run(
            ["docker", "info"],
            capture_output=True,
            timeout=5,
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
# Try --format json (Docker 20.10+)
    try:
        result = subprocess.run(
            ["docker", "ps", "--format", "{{json .}}"],
            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
# Fallback: plain docker ps
    try:
        result = subprocess.run(
            ["docker", "ps", "--no-trunc"],
            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
"""Use lsof to find listening TCP ports."""
    lsof = _find_lsof()
    try:
        result = subprocess.run(
            [lsof, "-iTCP", "-sTCP:LISTEN", "-n", "-P"],
            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 scan_linux():
    """Use ss to find listening TCP ports."""
    try:
        result = subprocess.run(
            ["ss", "-tlnp"],
            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 scan_linux_netstat():
    """Fallback using netstat if ss is not available."""
    try:
        result = subprocess.run(
            ["netstat", "-tlnp"],
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The implementation materially underdelivers relative to the skill metadata, claiming broad host scanning and runbook generation while only enumerating launchd/systemd services and emitting JSON. This can create a false sense of coverage, causing users to rely on incomplete inventory data and overlook exposed ports, containers, mounts, or unhealthy services during security or operations workflows.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def scan_macos():
    """Use launchctl list to get running services."""
    try:
        result = subprocess.run(
            ["launchctl", "list"],
            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 scan_linux():
    """Use systemctl to list running services."""
    try:
        result = subprocess.run(
            [
                "systemctl",
                "list-units",
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Static analysis

No suspicious patterns detected.