Back to skill

Security audit

Screenshot Tool

Security checks for vulnerabilities and agentic risk

Overview

This screenshot skill does what it says, but it needs Review because screen capture is privacy-sensitive and its Windows output-path handling can run unintended PowerShell commands.

Install only if you are comfortable with an agent taking screenshots of visible screen contents. Avoid using it when sensitive information is visible, and do not pass untrusted or externally supplied output paths, especially on Windows, until the PowerShell path handling is fixed.

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

Error
Location
scripts/screenshot.py:82
Finding

PowerShell Command Injection Through the Output Path

Content
View full analysis

Vulnerability Details

File Location: scripts/screenshot.py, lines 82–96
Vulnerability Type: PowerShell command injection
Risk Level: High

Vulnerable Code

python
elif sys.platform == 'win32':
    try:
        # Use PowerShell's Get-Screenshot
        ps_script = f'''
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$screens = [System.Windows.Forms.Screen]::AllScreens
$screen = $screens[0]
$bitmap = New-Object System.Drawing.Bitmap($screen.Bounds.Width, $screen.Bounds.Height)
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$graphics.CopyFromScreen($screen.Bounds.Location, [System.Drawing.Point]::Empty, $screen.Bounds.Size)
$bitmap.Save("{output}")
$graphics.Dispose()
$bitmap.Dispose()
'''
        subprocess.run(['powershell', '-Command', ps_script], check=True)

Technical Analysis

The --output command-line value reaches the output variable without validation or PowerShell-safe encoding. The code then inserts that value directly into executable PowerShell source through an f-string:

python
$bitmap.Save("{output}")

Although subprocess.run uses an argument list rather than a shell command string, that does not prevent this vulnerability. PowerShell is explicitly invoked with -Command, and therefore parses the generated ps_script as source code. An attacker-controlled output value containing a double quote, closing syntax, and additional PowerShell statements can escape the intended string context and alter the script.

The vulnerability is exploitable on Windows when an attacker can control the --output argument. Exploitation does not require modifying the Skill package.

Attack Path

  1. A victim or an automated agent invokes the Skill on Windows.
  2. The attacker supplies or influences a crafted --output argument.
  3. main() passes that value to take_screenshot() without validation.
  4. take_screenshot() interpolates the value into $bitmap.Save("{output}"). ...[truncated 781 chars]
Remediation
View remediation

Remediation Suggestions

Do not construct executable PowerShell source by directly interpolating untrusted values.

  1. Pass the output path as a distinct PowerShell parameter rather than embedding it into the script body. For example, define a param([string]$OutputPath) block and supply the path after -File or through another parameter mechanism that preserves it as data.
  2. Prefer storing a fixed PowerShell script in a file and invoking it with a separately supplied path argument.
  3. If inline PowerShell is unavoidable, encode the path using a robust serialization mechanism and decode it as data inside PowerShell. Do not rely on replacing quotes alone.
  4. Resolve and validate the path with pathlib.Path. If output should be restricted to an approved directory, resolve both paths and verify that the destination remains inside that directory.
  5. Reject control characters and invalid path forms, and enforce expected file extensions.
  6. Add Windows security tests using paths that contain quotes, semicolons, dollar signs, parentheses, backticks, and newline characters. Verify that these values cannot change the PowerShell syntax.
  7. Avoid broad except: clauses around this code. Catch specific exceptions and report failures so security-relevant parsing or execution errors are not silently hidden.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
Findings (11)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill invokes shell commands to run a Python screenshot utility, but the manifest does not declare any tool scope such as permissions or allowed-tools. That omission weakens reviewability and enforcement, making it harder to constrain or audit a privacy-sensitive capability that can capture on-screen secrets or record user activity.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The description uses broad activation language like 'use when user needs to take screenshots' without clear limits or confirmation requirements. Because screen capture is inherently privacy-sensitive, broad invocation boundaries increase the chance the skill is triggered in situations where sensitive data, credentials, messages, or unrelated applications are visible on screen.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The markdown presents screen capture and recording functionality without any warning that these actions may collect sensitive personal or enterprise information visible on the display. In this context, the lack of a privacy warning is dangerous because users may not realize screenshots or recordings can expose credentials, chats, documents, notifications, or other confidential material.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring says the tool can capture screen recordings, matching the manifest, but the implementation of recording only prints an ffmpeg command and reports 'Recording not implemented' instead of starting any recording. This is an active contradiction between the documented capability and the code's real behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This tool captures and writes screenshots to disk without any explicit privacy warning, confirmation, or guardrails around sensitive on-screen data. In the context of an agent skill, screenshot functionality is inherently more dangerous because it can expose credentials, personal information, internal documents, or other secrets visible on the user's screen.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/screenshot.py (reported line 43)May include surrounding context.

python
cmd.extend(['-a'])
            if output:
                cmd.extend(['-f', output])
            subprocess.run(cmd, check=True)
            success = True
        except:
            pass

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/screenshot.py (reported line 58)May include surrounding context.

python
cmd.extend(['-a'])
            if output:
                cmd.extend(['-f', output])
            subprocess.run(cmd, check=True)
            success = True
        except:
            pass

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/screenshot.py (reported line 67)May include surrounding context.

python
cmd.extend(['-a'])
            if output:
                cmd.extend(['-f', output])
            subprocess.run(cmd, check=True)
            success = True
        except:
            pass

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/screenshot.py (reported line 82)May include surrounding context.

python
cmd.extend(['-a'])
            if output:
                cmd.extend(['-f', output])
            subprocess.run(cmd, check=True)
            success = True
        except:
            pass

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
83% confidence
Finding

The PowerShell script embeds the user-supplied output path directly inside a quoted script string. If the output value contains PowerShell metacharacters or quote-breaking content, it could alter the script and lead to unintended PowerShell command execution on Windows.

Content

Scanner excerpt · scripts/screenshot.py (reported line 103)May include surrounding context.

python
$graphics.Dispose()
$bitmap.Dispose()
'''
            subprocess.run(['powershell', '-Command', ps_script], check=True)
            success = True
        except:
            pass

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Recording mode lacks an explicit warning that it may persist sensitive screen contents to a file. Even though recording is only partially implemented, the skill advertises this capability, and in an agent context such capture features materially increase privacy and data-exfiltration risk if invoked without informed consent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.