T09 · Insecure Skill Coding Practices
- 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: HighVulnerable 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
--outputcommand-line value reaches theoutputvariable 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.runuses 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 generatedps_scriptas 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
--outputargument. Exploitation does not require modifying the Skill package.Attack Path
- A victim or an automated agent invokes the Skill on Windows.
- The attacker supplies or influences a crafted
--outputargument. main()passes that value totake_screenshot()without validation.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.
- 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-Fileor through another parameter mechanism that preserves it as data. - Prefer storing a fixed PowerShell script in a file and invoking it with a separately supplied path argument.
- 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.
- 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. - Reject control characters and invalid path forms, and enforce expected file extensions.
- 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.
- Avoid broad
except:clauses around this code. Catch specific exceptions and report failures so security-relevant parsing or execution errors are not silently hidden.
- Pass the output path as a distinct PowerShell parameter rather than embedding it into the script body. For example, define a
