Mechanisms
absent builtin noop
Section titled “absent builtin noop”POSIX builtins absent in PowerShell (command -v) parse as argument noise and fail silently instead of erroring.
Cases: command-v-noop
folder lookup answers empty instead of failing
Section titled “folder lookup answers empty instead of failing”A known-folder lookup verifies the directory before answering and returns an empty string rather than an error when it is absent, and that empty string is a valid argument to every path function downstream, so the failure becomes a relative path instead of an exception.
Cases: known-folder-empty-not-error
non-atomic ACL mutation order
Section titled “non-atomic ACL mutation order”Windows permissions are changed by a sequence of separate mutations with no atomic replace, and removing inheritance takes effect immediately, so an interrupted restrict-then-grant order leaves an empty DACL that denies everyone including the owner.
Cases: icacls-inheritance-r-empty-dacl
alias shadowing
Section titled “alias shadowing”Built-in aliases (curl, wget) and PATH shims shadow the binaries users intend to run.
Cases: curl-alias · ps51-vs-7-split
AltGr is reported as Ctrl+Alt
Section titled “AltGr is reported as Ctrl+Alt”Windows implements right Alt as Ctrl plus Alt, so a character typed with AltGr arrives carrying both modifiers and any handler treating Ctrl as a shortcut prefix silently consumes real text, but only on layouts that need AltGr to produce it.
Cases: altgr-reports-as-ctrl-alt
appexeclink
Section titled “appexeclink”WindowsApps store aliases are zero-byte IO_REPARSE_TAG_APPEXECLINK files that pass stat probes but EPERM on spawn.
Cases: windowsapps-alias-eperm
bom sniffing
Section titled “bom sniffing”Windows PowerShell 5.1 decides a script file’s encoding by BOM presence; no BOM means the legacy ANSI code page.
Cases: bom-less-ps1-cp949
bun windowstyle argv reject
Section titled “bun windowstyle argv reject”Bun 1.3.14 Windows spawn fails outright when powershell.exe argv contains the -WindowStyle Hidden pair.
Cases: bun-ps-windowstyle-argv
case-insensitive filesystem, case-sensitive containers
Section titled “case-insensitive filesystem, case-sensitive containers”NTFS matches paths without regard to case while preserving the casing written, so two spellings name one file, but every ordinary string container treats them as distinct keys and the same lowercasing fix would be wrong on a case-sensitive filesystem.
Cases: path-case-sensitive-map
cmd bat spawn hardening
Section titled “cmd bat spawn hardening”Node CVE-2024-27980 hardening: spawning .bat/.cmd without shell errors EINVAL (18.20.2/20.12.2/21.7.3+).
Cases: spawn-npm-enoent-einval
cmd reparse
Section titled “cmd reparse”Any command line routed through cmd.exe is re-tokenized; metacharacters and newlines inside arguments become command syntax.
Cases: get-command-where-disagree · cmd-shim-reparses-argv · cmd-start-ampersand-splits · shell-true-fallback-injects
collection unrolling
Section titled “collection unrolling”PowerShell unrolls pipelines: zero items become null, one item loses its array, many become Object[] — types change with count.
Cases: if-nativecmd-truthiness · return-does-not-mean-return · get-content-scalar-collapse
CreateProcess command line capped at 32767
Section titled “CreateProcess command line capped at 32767”CreateProcess limits the whole assembled command line to 32767 characters and reports the overflow with the same Win32 code used for an over-long path, so a payload passed as an argument fails under an error that describes filenames.
Cases: createprocess-cmdline-32767
comparison as filter
Section titled “comparison as filter”Comparison operators against a collection FILTER it (returning matching elements) instead of returning a boolean.
Cases: ne-filters-instead-of-compares
console allocation
Section titled “console allocation”Console-subsystem binaries get a new console at CreateProcess when the parent has none — before any flag is parsed.
Cases: windowstyle-hidden-vs-windowshide
CRLF residue after LF-only splitting
Section titled “CRLF residue after LF-only splitting”Windows tools end lines with CRLF, so splitting text on LF alone leaves a trailing CR on every line; exact comparisons and anchored patterns then fail against a character that is invisible in editors, diffs, and terminal output.
Cases: lf-pure-transform-mixes-eol · split-n-leaves-cr · cmd-lf-drops-first-byte
culture parsing
Section titled “culture parsing”Numeric/date casts honor the host culture; comma-decimal locales parse differently than invariant culture.
Cases: culture-comma-decimal-cast
default encoding
Section titled “default encoding”5.1 cmdlets default to UTF-16LE or ANSI when writing; 7 defaults to BOM-less UTF-8 — same code, different bytes.
Cases: bomless-bat-oem-codepage · redirected-ps-output-mojibake · oss-outfile-bom · tee-object-utf16 · utf8-bom-still-breaks-grep · bom-less-ps1-cp949 · ps51-vs-7-split
default shell selection
Section titled “default shell selection”CI runners pick a default shell per OS (pwsh on windows-latest); unmarked run: steps inherit it.
Cases: npm-script-runs-under-cmd · actions-default-shell
MS-DOS device names reserved in every directory
Section titled “MS-DOS device names reserved in every directory”Win32 path parsing recognizes legacy device names such as CON, NUL, and COM1 as their own path type and rewrites them into the NT device namespace before any directory applies, with or without an extension, so opening one succeeds as a device rather than creating a file.
Cases: reserved-dos-device-names
drive letter parses as a URL scheme
Section titled “drive letter parses as a URL scheme”A Windows absolute path begins with a drive letter and colon, so any API that parses its input as a URL reads that letter as the protocol, while an absolute POSIX path coincidentally parses as root-relative and works.
Cases: dynamic-import-needs-file-url
env casing
Section titled “env casing”Windows env names are case-insensitive but JS objects are not; Path and PATH can coexist and fight.
Cases: env-path-vs-PATH-casing
env derived identity
Section titled “env derived identity”USERDOMAIN/USERNAME env vars are writable, unreliable identity sources; workgroup machines put the computer name in USERDOMAIN.
Cases: env-domain-principal · wslenv-shared-with-host
errorrecord format
Section titled “errorrecord format”Formatting an ErrorRecord (Out-String) renders multi-line error views including position/script text, multiplying one line into many.
Cases: out-string-multiplies-stderr
execution policy gate
Section titled “execution policy gate”Execution policy gates script FILES (.ps1, -File) while in-memory command text bypasses it.
Cases: execution-policy-file-block · npm-ps1-not-comspec
exit code propagation
Section titled “exit code propagation”Exit codes cross process/host boundaries by convention, not guarantee: hosts, wrappers, and CI steps each apply their own rule.
Cases: startup-artifact-is-not-a-process · start-process-no-lastexitcode · explorer-exits-one · exit-code-vs-dollar-q · pwsh-leaks-lastexitcode
extension dispatch
Section titled “extension dispatch”powershell/pwsh -File dispatches on filename extension; non-.ps1 files are rejected before parsing.
Cases: ps-file-extension-dispatch
exit races a closing handle
Section titled “exit races a closing handle”An immediate process exit tears the runtime down without waiting for libuv to finish closing handles; a handle still in the closing state trips an assertion, which Windows surfaces as a fastfail while POSIX teardown absorbs the same race silently.
Cases: process-exit-fastfail-0xc0000409
host vs pipeline
Section titled “host vs pipeline”Write-Host and return semantics: host output bypasses the success pipeline, and functions emit every uncaptured value.
Cases: start-process-no-lastexitcode · write-host-not-success-stream · return-does-not-mean-return
iex session
Section titled “iex session”Invoke-Expression runs text in the CURRENT session: exit kills the caller’s host, and parameters cannot be forwarded.
Cases: irm-iex-kills-host · piped-iex-drops-params
json depth default
Section titled “json depth default”ConvertTo-Json defaults to -Depth 2, replacing deeper data with type names; 5.1/7.0 truncate silently, 7.1+ warn.
Cases: convertto-json-depth-two
locale preferred encoding is the ANSI codepage
Section titled “locale preferred encoding is the ANSI codepage”Python text mode without an explicit encoding decodes with the locale preferred encoding, which on Windows is the ANSI codepage rather than UTF-8, and UTF-8 mode changes what that function reports without changing what native children emit.
Cases: python-subprocess-locale-encoding
localized tool output
Section titled “localized tool output”Windows built-in command-line tools translate their column headings, status words, and error messages to the system UI language, so only structure and exit codes are stable; matching English substrings tests the machine’s language rather than its state.
Cases: localized-cli-output-parsing
mandatory file locking
Section titled “mandatory file locking”Windows enforces file locks at the OS level: a handle opened without FILE_SHARE_DELETE blocks deletes and renames until it closes, where POSIX unlink only removes a name and lets the data outlive its last reference.
Cases: atomic-rename-loses-to-scanner · unlink-while-open-ebusy
MAX_PATH is an API ceiling, not a filesystem limit
Section titled “MAX_PATH is an API ceiling, not a filesystem limit”Win32 caps a pathname at 260 characters including drive, separators, and the terminating NUL, and directory creation reserves twelve more, so a path NTFS would store is refused by the API unless the caller uses the extended-length prefix or opts in with both the registry value and a long-path-aware manifest.
Cases: max-path-260
native argv rebuild
Section titled “native argv rebuild”PowerShell historically rebuilds one command-line string for native processes, re-quoting heuristically; quotes and empty args are lost.
Cases: backslash-quote-ends-span · oss-native-arg-quoting · prose-as-unknown-flags
no POSIX process group
Section titled “no POSIX process group”Windows offers termination of one process or of a live parent-PID tree, with no group you opted into, so killing a child orphans its descendants while a tree kill sweeps up any caller that happens to descend from the target.
Cases: kill-hits-one-pid-or-the-whole-tree
output truthiness
Section titled “output truthiness”A native command in a PowerShell expression evaluates to its captured OUTPUT; if() branches on output presence, not exit code.
Cases: if-nativecmd-truthiness
path delimiter
Section titled “path delimiter”PATH list separator is host-dependent (‘;’ Windows, ‘:’ POSIX); colon-joined lists corrupt drive-letter entries.
Cases: path-colon-not-delimiter · node-path-host-delimiter
pathext resolution
Section titled “pathext resolution”Windows resolves extensionless command names by walking PATH entries and PATHEXT extensions in order; results differ from POSIX execvp and between resolvers.
Cases: get-command-where-disagree · spawn-npm-enoent-einval · npm-ps1-not-comspec · pathext-bare-name-enoent · path-dot-hijacks-bare-npm · pathext-exe-beats-cmd
pipeline chain ops
Section titled “pipeline chain ops”&& and || are PowerShell 7.0+ pipeline chain operators; 5.1 treats them as parser errors.
Cases: ps51-no-and-and
posix dev null
Section titled “posix dev null”/dev/null is a POSIX device path; Windows treats it as a relative file path under the current drive.
Cases: dev-null-redirect
posix inline env
Section titled “posix inline env”VAR=value cmd per-command environment is POSIX shell syntax; cmd.exe executes the literal token instead.
Cases: cmd-posix-env-prefix
prose as argument
Section titled “prose as argument”English connectors like ‘and’ between commands parse as positional arguments of the first command.
Cases: english-and-not-separator
PATH entries may be quoted
Section titled “PATH entries may be quoted”A Windows PATH entry may be wrapped in quotes so a directory name can contain a semicolon, which forces correct parsers to be quote-aware; an unmatched quote then opens a span that swallows every later entry into one fictional path.
Cases: path-unmatched-quote-swallows
registry env snapshot
Section titled “registry env snapshot”Environment variables live in the registry; a process gets a merge snapshot at creation and never sees later writes.
Cases: envpath-pollutes-user · session-path-stale
backslash is data inside a URL path
Section titled “backslash is data inside a URL path”A general-purpose URL type percent-encodes a backslash because it is an ordinary path character rather than a separator; only implementations following the WHATWG special-scheme rule convert it, so the same conversion is correct in one language and broken in another.
Cases: file-url-encodes-backslash
statement terminator
Section titled “statement terminator”‘;’ terminates a PowerShell statement; joining fragments of ONE call with ‘;’ splits it into broken statements.
Cases: cmd-c-newline-not-separator · join-semicolon-splits-startprocess
stream wrapping
Section titled “stream wrapping”5.1 wraps redirected native stderr lines in ErrorRecord objects, converting output into error-stream objects.
Cases: native-stderr-errorrecord · out-string-multiplies-stderr
strictmode contract
Section titled “strictmode contract”Set-StrictMode changes property access on missing members from returning null to throwing.
Cases: strictmode-missing-property
string interpolation
Section titled “string interpolation”Double-quoted PowerShell strings interpolate $tokens; backslash is not an escape — backtick is.
Cases: dollar-backslash-vars · prose-as-unknown-flags · dq-regex-interpolates
TCP control block outlives the socket
Section titled “TCP control block outlives the socket”Windows retains the transmission control block for a closed socket so the endpoint stays unbindable, and its SO_REUSEADDR waives that state by also permitting an active listener to be hijacked, so runtimes refuse to set it and the POSIX escape hatch is unavailable rather than merely ineffective.
Cases: tcp-tcb-survives-listener
cmd.exe cannot hold a UNC current directory
Section titled “cmd.exe cannot hold a UNC current directory”The current directory is drive-relative in cmd.exe’s model, so a UNC path cannot be one; started in a UNC directory it warns and silently relocates to the Windows directory, and every batch shim that hops through it inherits the wrong working directory.
Cases: cmd-unc-cwd-not-supported
a UNC path may be served by a non-NTFS provider
Section titled “a UNC path may be served by a non-NTFS provider”A UNC root can be backed by a provider with entirely different semantics from NTFS, such as the WSL 9P filesystem, so operations that assume a Windows security descriptor fail with access-denied on a path that reads and lists normally.
Cases: wsl-unc-rejects-nt-acl
text-mode write translates newlines
Section titled “text-mode write translates newlines”CPython text I/O applies universal newlines when writing as well as reading, so a lone line feed becomes the platform terminator wherever a TextIOWrapper sits in the path, including inside a subprocess pipe opened in text mode.
Cases: python-textio-newline-translation
win32 path normalization
Section titled “win32 path normalization”Win32 trims trailing dots/spaces from paths at the API boundary; different runtimes normalize differently, so existence checks disagree.
Cases: esm-is-main-file-url · test-path-trailing-whitespace · basename-split-slash-only · zip-entry-drive-letter-escapes