Back to skill

Security audit

Dockerfile Builder

Security checks for vulnerabilities and agentic risk

Overview

This Dockerfile helper is not clearly malicious, but it can read and print sensitive lines from arbitrary local files and its shell argument handling can broaden that access unexpectedly.

Install only if you are comfortable with a local shell script that can inspect files and print secret-like lines. Prefer fixing it first: restrict scan to intended Dockerfile paths, quote arguments, use $1 after shift, add -- before grep file operands, validate regular files, and avoid printing secret values directly.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:108
Finding

Unquoted File Arguments Allow GNU grep Option Injection and Unintended File Disclosure

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 108-136
Vulnerability Type: Unquoted shell argument and option injection
Risk Level: Medium

Complete Vulnerable Code

bash
cmd_lint() {
    local file="${2:-}"
    [ -z "$file" ] && die "Usage: $SCRIPT_NAME lint <file>"
    grep -n 'latest' $2 && echo 'WARN: Avoid :latest tag'; grep -c RUN $2 | awk '{if($1>5) print "WARN: Too many RUN layers"}'
}

cmd_optimize() {
    local file="${2:-}"
    [ -z "$file" ] && die "Usage: $SCRIPT_NAME optimize <file>"
    echo '=== Optimization suggestions for $2 ==='; grep -c RUN $2 | awk '{if($1>3) print "Combine RUN commands"}'
}

cmd_scan() {
    local file="${2:-}"
    [ -z "$file" ] && die "Usage: $SCRIPT_NAME scan <file>"
    echo 'Scanning $2...'; grep -in 'password\|secret\|key' $2 && echo 'WARN: Potential secrets' || echo 'Clean'
}

The associated dispatch logic is:

bash
lint) shift; cmd_lint "$@" ;;
optimize) shift; cmd_optimize "$@" ;;
scan) shift; cmd_scan "$@" ;;

Technical Analysis

The handlers use ${2:-} and $2 even though the dispatcher first removes the command name with shift. Under the documented invocation script.sh scan <file>, the requested filename consequently becomes $1, while $2 is empty and the command fails.

An attacker can provide an additional argument so that attacker-controlled content occupies $2. That value is then passed to grep without quoting and without the -- end-of-options delimiter. This creates two related shell-safety problems:

  1. Shell word splitting and pathname expansion may convert one supplied value into multiple file operands.
  2. A value beginning with - may be interpreted as a GNU grep option rather than as a filename.

For example, supplying -R as the second handler argument can enable recursive searching. Because the ...[truncated 2091 chars]

Remediation
View remediation

Remediation Suggestions

  1. Use $1 after the dispatcher removes the command name:

    bash
    local file="${1:-}"
    
  2. Quote every filename expansion to prevent word splitting and pathname expansion.

  3. Insert -- before file operands so values beginning with - cannot become options:

    bash
    grep -n -- 'latest' "$file"
    grep -c -- 'RUN' "$file"
    grep -in -- 'password\|secret\|key' "$file"
    
  4. Validate that the argument identifies an expected regular file before reading it:

    bash
    [[ -f "$file" ]] || die "Not a regular file: $file"
    
  5. If scans must be restricted to a trusted project directory, canonicalize the path and verify that it remains beneath that directory. Consider rejecting symbolic links when they are not required.

  6. Refactor the affected handlers consistently. For example:

    bash
    cmd_scan() {
        local file="${1:-}"
        [[ -n "$file" ]] || die "Usage: $SCRIPT_NAME scan <file>"
        [[ -f "$file" ]] || die "Not a regular file: $file"
    
        printf 'Scanning %s...\n' "$file"
        if grep -in -- 'password\|secret\|key' "$file"; then
            echo 'WARN: Potential secrets'
        else
            echo 'Clean'
        fi
    }
    
  7. Add regression tests covering ordinary filenames, filenames containing spaces or wildcard characters, filenames beginning with -, missing arguments, extra arguments, and symbolic links.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill description claims a narrow purpose of generating and linting Dockerfiles, but the documented commands and storage behavior indicate additional capabilities such as scanning files, optimization, templating, listing, and persistent local data storage. This mismatch is dangerous because users or higher-level agents may grant trust or invoke the skill under false assumptions, causing unintended file inspection or persistence beyond the declared scope.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 18)May include surrounding context.

create

bash
scripts/script.sh create <language>

lint

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
80% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · scripts/script.sh (reported line 9)May include surrounding context.

sh
DATA_DIR="$HOME/.local/share/dockerfile-builder"
mkdir -p "$DATA_DIR"

#
#
#
#

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes a skill for generating and linting Dockerfiles, but the script also provides optimize, template, and especially scan commands. Secret scanning of arbitrary files and broader template/optimization analysis extend the behavior beyond the narrower generate-and-lint scope stated in the manifest.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The scan command accepts an arbitrary file path and prints matching lines containing strings like password, secret, or key. In an agent context, this broadens the skill from Dockerfile assistance into generic local file inspection and can expose sensitive contents from unrelated files if an attacker or prompt steers the tool toward scanning them.

Content

No source excerpt is available for this finding.