Back to skill

Security audit

download-guard

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent download-management purpose, but it ships with risky default configuration and can make persistent tool-setting changes with weak user-control boundaries.

Review this before installing. Use it only if you want an agent to manage download locations and inspect developer-tool caches, and reset config.md to an unconfigured state before first use. Do not run 'fix warnings' or cache migration unless you have reviewed the target path and are comfortable with persistent npm, pip, yarn, pnpm, uv, PATH, and environment changes. Treat the download log as untrusted display data if filenames or paths may come from outside sources.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • 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 (3)

T02 · Agent Memory Poisoning

Warning
Location
scripts/log-download.ps1:1
Finding

Persistent Markdown Injection Through Unsanitized Download Log Fields

Content
View full analysis

Vulnerability Details

File Location: scripts/log-download.ps1, lines 1-5 and 34-37
Vulnerability Type: Persistent agent-state injection
Risk Level: Medium

Vulnerable Code

powershell
param(
    [string]$FileName = "unknown",
    [double]$SizeMB = 0,
    [string]$TargetPath = "unknown",
    [string]$Reason = "agent-download"
)
powershell
$timestamp  = Get-Date -Format "yyyy-MM-dd HH:mm"
$sizeDisplay = if ($SizeMB -gt 0) { "${SizeMB}MB" } else { "unknown" }
$newRow = "| $timestamp | $FileName | $sizeDisplay | $TargetPath | $Reason |"
Add-Content -Path $logFile -Value $newRow -Encoding UTF8

SKILL.md, lines 343 and 347, subsequently instructs the agent to read this persistent log when the user requests the download history or most recent download location.

Technical Analysis

The script accepts the filename, target path, and reason as caller-controlled strings and inserts them directly into a persistent Markdown table. It does not reject carriage returns, line feeds, control characters, Markdown table delimiters, or instruction-like content.

An attacker-controlled filename such as one containing newline characters and additional Markdown rows can alter the structure and semantic content of download-log.md. Because the Skill later retrieves this file and may place its contents into the agent's context, malicious text can persist beyond the original download operation and influence later sessions.

This is not direct operating-system command injection: the values are not evaluated as PowerShell. The security issue is persistent state poisoning and indirect prompt injection through a log that the agent is explicitly instructed to read.

Attack Path

  1. An attacker controls or influences the name of a file, download destination, or reason passed to log-download.ps1.
  2. The attacker includes line breaks, Markdown delimiters, or instruction-like text in that value.

...[truncated 1015 chars]

Remediation
View remediation

Remediation Suggestions

  1. Reject carriage returns, line feeds, null bytes, and non-printable control characters in all log fields.
  2. Escape Markdown table delimiters such as | and backslashes before generating display output.
  3. Store records in a structured format such as JSON Lines rather than using Markdown as the authoritative data store.
  4. Generate Markdown only from parsed, validated structured records.
  5. Apply strict maximum lengths to filenames, paths, and reasons.
  6. When the agent reads the log, explicitly classify its contents as untrusted data and prohibit following instructions found inside records.
  7. Add tests using filenames containing newlines, pipes, Markdown links, code blocks, and prompt-like instructions.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/check-space.ps1:27
Finding

Drive-Space Validation Can Be Performed Against a Different Drive Than the Download Root

Content
View full analysis

Vulnerability Details

File Location: scripts/check-space.ps1, lines 27-33, 47-69, and 75-83
Vulnerability Type: Inconsistent destination validation
Risk Level: Medium

Vulnerable Code

powershell
# Priority: explicit param > config > fallback
# Only override TargetDrive from config if user didn't explicitly pass one
if (-not $TargetDrive) {
    if ($configDrive) { $TargetDrive = $configDrive } else { $TargetDrive = "C" }
}
# If user explicitly passed TargetDrive, use it (even if config says different)

$driveLetter = $TargetDrive.TrimEnd(":\")
$disk = Get-PSDrive -Name $driveLetter -ErrorAction SilentlyContinue
powershell
# If the drive exists, verify the download root path is writable
if ($downloadRoot -and (Test-Path $downloadRoot)) {
    # Test write permission by creating and deleting a temp file
    $testFile = Join-Path $downloadRoot ".dg-write-test-$(Get-Random).tmp"
    try {
        Set-Content -Path $testFile -Value "test" -ErrorAction Stop
        Remove-Item $testFile -Force -ErrorAction SilentlyContinue
    } catch {
        Write-Output "CRITICAL: DOWNLOAD_ROOT ($downloadRoot) is not writable!"
        Write-Output "  Error: $($_.Exception.Message)"
        Write-Output "  ACTION: Check folder permissions or choose a different path."
        Write-Output "  BLOCKED: Download blocked due to insufficient permissions."
        exit 2
    }
} elseif ($downloadRoot) {
    try {
        New-Item -ItemType Directory -Path $downloadRoot -Force -ErrorAction Stop | Out-Null
        Write-Output "CREATED: Download directory created at $downloadRoot"
    } catch {
        Write-Output "CRITICAL: Cannot create DOWNLOAD_ROOT ($downloadRoot)!"
        Write-Output "  Error: $($_.Exception.Message)"
        Write-Output "  ACTION: Choose a different path or create the directory manually."
        Write-Output "  BLOCKED: Download blocked due to inaccessible 
...[truncated 2204 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove TargetDrive as an independent source of truth and derive the drive from the canonical, fully resolved destination path.
  2. If backward compatibility requires TargetDrive, reject the invocation unless it matches the drive associated with DOWNLOAD_ROOT.
  3. Resolve the destination with a filesystem provider API and validate the corresponding volume, including mounted folders and network paths.
  4. Apply existence, writability, and capacity checks to the same resolved destination.
  5. Fail closed when DOWNLOAD_ROOT is empty or malformed instead of falling back to C:.
  6. Add tests where TargetDrive and DOWNLOAD_ROOT refer to different drives.
  7. Recheck available capacity immediately before beginning large downloads to reduce time-of-check/time-of-use risk.

T09 · Insecure Skill Coding Practices

Warning
Location
config.md:8
Finding

Preconfigured Author-Specific Download Root Enables Unsafe Persistent Tool Reconfiguration

Content
View full analysis

Vulnerability Details

File Location: config.md, lines 8-10, 19-27, and 47-53; scripts/migrate-cache.ps1, lines 49-80 and 85-126
Vulnerability Type: Unsafe default configuration and unvalidated persistent configuration changes
Risk Level: Medium

Vulnerable Code

text
## Setup Status

SETUP_DONE: true

text
text
## Download Root

DOWNLOAD_ROOT: F:\ProgramData\Workbuddy Data

> Where the Agent puts downloaded files (git clones, models, datasets, etc.).
> Example: `DOWNLOAD_ROOT: D:\AI-Downloads`
>
> - Safe to include spaces (for file storage only).
> - Do NOT point npm prefix or conda envs at a path with spaces (Windows compat issue).
text
## PATH Safety

ALLOW_SPACE_IN_TOOL_PATH: false

text

> Keep `false`. Spaces in npm prefix / conda envs paths cause known Windows bugs.
powershell
# npm prefix
$npmCurrentPrefix = (npm config get prefix 2>$null) -replace "`n",""
if ($npmCurrentPrefix -match '^C:\\') {
    $newPrefix = "$TargetRoot\npm-global"
    $newCache  = "$TargetRoot\npm-cache"
    $ok = Migrate-Tool "npm prefix" $newPrefix {
        npm config set prefix $newPrefix
    }
    if ($ok) {
        Migrate-Tool "npm cache" $newCache {
            npm config set cache $newCache
        }
        Write-Output "  [ACTION NEEDED] Add to PATH: $newPrefix"
        $migrated++
    }
}
powershell
# pip cache
$pipRaw = pip cache dir 2>$null
$pipCurrentCache = ($pipRaw | Where-Object { $_ -match '^[A-Za-z]:\\' } | Select-Object -First 1)
if (-not $pipCurrentCache) { $pipCurrentCache = $env:PIP_CACHE_DIR }
if ($pipCurrentCache -match '^[Cc]:\\') {
    $newPipCache = "$TargetRoot\pip-cache"
    Migrate-Tool "pip cache" $newPipCache {
        pip config set global.cache-dir $newPipCache
    }
    [Environment]::SetEnvironmentVariable("PIP_CACHE_DIR", $newPipCache, "User")
    $migrated++
}

` ...[truncated 2726 chars]

Remediation
View remediation

Remediation Suggestions

  1. Distribute the project with SETUP_DONE: false and an empty DOWNLOAD_ROOT.
  2. Require explicit user selection and confirmation before writing the initial destination.
  3. Validate that the selected drive exists, the path is writable, and sufficient space is available.
  4. Enforce ALLOW_SPACE_IN_TOOL_PATH; reject migration targets containing spaces when the setting is false.
  5. Separate file-download storage from executable installation prefixes so a storage-safe path is not automatically reused for npm global binaries.
  6. Record all previous package-manager settings and environment-variable values before migration.
  7. Apply changes transactionally and restore previous values if any step fails.
  8. Check native process exit codes instead of assuming that absence of a PowerShell exception means success.
  9. Verify each setting after modification and report partial failures accurately.
  10. Provide a documented rollback command that restores npm, pip, yarn, pnpm, and uv settings individually.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • 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
Findings (15)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The promotion states that logs are 'automatically archived + automatically cleaned' and that archive files over 10 MB are automatically deleted, but it does not present a clear warning, retention policy details, or user-consent flow. Because this skill's purpose is to record download activity for transparency and troubleshooting, silent deletion can destroy audit history the user may rely on to investigate storage use, unintended downloads, or agent behavior.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The activation phrases include common conversational requests such as '下载了什么', '磁盘空间', '刚才下的在哪', and '检查路径', which are broad enough to trigger during ordinary user discussion rather than an explicit request to run the skill. In a guard skill that can inspect logs, paths, and potentially alter download behavior, accidental invocation can cause unintended monitoring, state changes, or disruptive blocking of normal workflows.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README makes a strong guarantee that downloads will 'never' fall back to C:, but later admits cases such as pip install --user and Docker storage that still use C:. This can mislead users into trusting the guard to prevent system-drive consumption in scenarios it does not actually control, increasing the risk of disk exhaustion or operational disruption.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README describes automatic cache migration and configuration writes as seamless or one-click operations without a prominent warning that these actions modify system state, file locations, or environment-dependent behavior. In an agent setting, under-disclosed state-changing actions can lead to unintended filesystem changes, broken tool paths, or surprise modifications that the user did not knowingly authorize.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger phrase '帮我修复' / 'fix warnings' is overly broad and may activate during ordinary troubleshooting conversations unrelated to download management. In an agent skill, ambiguous triggers can cause unintended execution paths or system-changing guidance in contexts where the user did not intend to invoke this skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file instructs automatic activation on Chinese phrases and consistently presents user-facing setup and status text in Chinese, but does not offer the user a language or locale choice. SQP-3 applies because this is a natural-language locale policy constraint without explicit opt-in or documented justification such as a region-specific tool.

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 62)May include surrounding context.

md
- `bun install -g` (v5.4)
- `pip install` (NOT inside active venv — check `VIRTUAL_ENV` env var first)
- `uv pip install` (v5.4 — same venv rule applies)
- `conda install / conda create / conda env update`
- `cargo install` (v5.4 — installs to `~/.cargo/bin`)
- `go install` (v5.4 — installs to `$GOPATH/bin`)
- `git clone`

Session Persistence

Medium
Category
Rogue Agent
Confidence
81% confidence
Finding

The first-time setup explicitly creates directories and writes persistent configuration under the user's profile, which is a form of session persistence. In context this is expected functionality, but it still changes durable state on disk; if auto-triggered or performed without clear consent, it can create unwanted persistence and influence future download behavior.

Content

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

md
1. Normalize input (drive letter only → `{letter}:\AI-Downloads`, full path → use as-is)
2. **Verify the path is writable** before accepting (v5.4)
3. Create directory if not exists
4. Write config.md: `SETUP_DONE: false` → `true`, `DOWNLOAD_ROOT:` → user choice
5. **Read-back verify** the config was written correctly (v5.4)
6. Run `scan-tool-cache.ps1`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill exposes an unconditional 'fix warnings' action that can automatically modify caches, PATH-related settings, or download-directory configuration without clearly requiring explicit per-change user confirmation. In a Windows environment, silent or bundled remediation can alter persistent system/user configuration in unexpected ways, making future command execution behavior less predictable and potentially breaking developer tooling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document instructs the agent to ask the user for answers and then directly write them into config.md, with immediate effect and no restart. This creates a persistent configuration-modification path based on conversational input, which can lead to unsafe file changes, surprising persistence, or path/environment abuse if the agent does not clearly disclose the write action and validate the values before saving.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest emphasizes checking disk space, validating path availability, logging downloads, and blocking unsafe download destinations. In addition to validation, this script creates the configured download directory when it does not exist, which is a behavioral expansion from passive guarding/checking into actively provisioning filesystem paths.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The top-level description and badge present the skill as 'Windows only', which implies the skill is limited to Windows environments. However, later documentation explicitly provides macOS/Linux installation steps and states those platforms can work if PowerShell Core is installed, which contradicts the claimed platform scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The reference content and operational instructions are presented in Chinese, and the file does not indicate that the user can choose another language or that the locale restriction is required for a justified regional purpose. This can violate language or locale policy when a skill effectively forces one language without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

This PowerShell script inspects local tool configuration and environment-derived directories such as USERPROFILE, APPDATA, CARGO_HOME, GOPATH, HF_HOME, and OLLAMA_MODELS, and it executes multiple external commands to enumerate cache locations. Although it is read-only, the code lacks a comment or user-facing disclosure that it will scan installed tooling paths and environment-based locations on the machine.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.