Join our Newsletter — 33% off our NHI Course

What breaks when a desktop app passes filenames into PowerShell without sanitising them?

Unsanitised filenames can turn an ordinary browse or import action into code execution. When the application builds a shell command from text it did not clean first, an attacker who can place a crafted file or directory name in a readable location may inject commands that run as the current user. The safe pattern is to treat every filename as untrusted input and avoid shell interpolation.

How the command line turns a filename into an execution path

The failure starts when the app treats a filename as command text instead of data. PowerShell does not know that a path came from a file picker or directory scan unless the application keeps it separate from the shell command it is building. Once interpolation happens, characters with command meaning can change the intended action, which is why even a normal browse or import flow can become an execution path.

The important distinction is between passing a value to PowerShell and asking PowerShell to parse a string. If the app uses a shell command string, the filename becomes part of the syntax tree. If it uses argument passing, encoding, or a direct API call, the filename stays data and does not get a chance to alter the command structure.

That is why sanitising is not just about removing a few bad characters. The real issue is preserving a boundary between untrusted input and executable syntax. A filename is only harmless if the code path never gives it command semantics.

What attackers can do with a crafted filename

A malicious filename can hijack a trusted local action. If the app reads from a writable folder, temp directory, sync location, archive extraction path, or import source, an attacker may place a name that alters the PowerShell command and causes additional statements to run under the current user. The result is command injection through an otherwise ordinary workflow.

PowerShell is especially sensitive here because many desktop apps use it for automation, file handling, or administrative convenience. Once the filename is embedded in a command line, the attacker is no longer limited to influencing the file being opened. They may influence what gets executed, what arguments get passed, and which follow-on actions the script performs. MITRE ATT&CK Enterprise Matrix is a useful reference for understanding how attackers turn initial execution into broader privilege abuse, persistence, or credential theft.

The practical abuse pattern is simple: get a crafted name into a place the app trusts, wait for the user or process to enumerate or import it, and let unsafe shell construction do the rest. That is why filename handling belongs in the same review as any other code injection path, not just in file validation.

How to prevent filename-driven PowerShell injection

The safest approach is to avoid building PowerShell command strings from filenames at all. Call the underlying API directly, pass arguments as discrete values, or use a form of invocation that does not re-parse the text as shell syntax. If PowerShell is unavoidable, keep the filename in a parameter position and use explicit quoting or escaping that is designed for PowerShell parsing, not generic string cleanup.

Sanitisation still matters, but it is secondary to command construction. Removing suspicious characters can reduce exposure, yet it is not a reliable substitute for a non-interpolated design. Many injection failures come from assuming that a short denylist is enough, when the real fix is to stop mixing executable text with untrusted file names in the first place.

For broader application-hardening guidance, OWASP SAMM helps teams place secure coding and code review practices around input handling, while ISO/IEC 27002:2022 Information Security Controls provides implementation-oriented control guidance for preventing unsafe processing of untrusted input.

Risk and Threat Considerations

This issue is a command-injection problem, not a cosmetic input-validation problem. The risk is that a low-privilege local file name can trigger code execution in a higher-trust desktop workflow, especially when users browse shared folders, unpack archives, or import content from locations an attacker can influence.

Failure mechanism: The application concatenates or interpolates an untrusted filename into a PowerShell command, so special characters or crafted structure change what the shell executes.

Impact: The attacker may run commands as the current user, manipulate files, stage persistence, or pivot into other resources that the user account can reach.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

OWASP API Security Top 10 addresses the attack surface, OWASP ASVS and OWASP SAMM set the technical controls, and ISO/IEC 27001:2022 defines the regulatory obligations.

Framework Control / Reference Relevance
OWASP ASVS V15 — Secure Coding and Architecture Unsafe shell interpolation is a secure coding and architecture flaw.
Recommendation — Eliminate command construction from untrusted filenames and use parameterised APIs.
OWASP SAMM SFD — Security Requirements and Design The issue is rooted in insecure design and review of input handling paths.
Recommendation — Add design reviews that block shell interpolation of attacker-controlled input.
ISO/IEC 27001:2022 A.8.28 — Secure coding Desktop code that passes filenames to PowerShell needs secure coding controls.
Recommendation — Apply secure coding practices to prevent command injection from untrusted filenames.
OWASP API Security Top 10 API8 — Security Misconfiguration Unsafe command construction is a misconfiguration-like exposure in execution handling.
Recommendation — Harden execution paths so user input cannot alter command parsing.

Practitioner Guidance

What to verify: Review every code path that sends a filename into PowerShell and confirm whether it uses a string command, a parameterised call, or a direct API. If the filename is ever rendered into a shell command for convenience, treat that as a security defect even when the current test cases appear to work.

Common mistake: Teams often focus on “invalid characters” and miss the larger design flaw, which is letting the shell interpret user-controlled text at all. If you must keep PowerShell in the flow, prefer argument separation, strict allowlists for expected path shapes, and testing with filenames that include spaces, quotes, and shell metacharacters.

Practitioner takeaway: The safe pattern is not “clean the filename well enough”, it is “never let an untrusted filename become executable syntax”.