File size: 7,229 Bytes
064bfd6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | /**
* PowerShell Constrained Language Mode allowed types.
*
* Microsoft's CLM restricts .NET type usage to this allowlist when PS runs
* under AppLocker/WDAC system lockdown. Any type NOT in this set is considered
* unsafe for untrusted code execution.
*
* We invert this: type literals not in this set β ask. One canonical check
* replaces enumerating individual dangerous types (named pipes, reflection,
* process spawning, P/Invoke marshaling, etc.). Microsoft maintains the list.
*
* Source: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes
*
* Normalization: entries stored lowercase, short AND full names where both
* exist (PS resolves type accelerators like [int] β System.Int32 at runtime;
* we match against what the AST emits, which is the literal text).
*/
export const CLM_ALLOWED_TYPES: ReadonlySet<string> = new Set(
[
// Type accelerators (short names as they appear in AST TypeName.Name)
// SECURITY: 'adsi' and 'adsisearcher' REMOVED. Both are Active Directory
// Service Interface types that perform NETWORK BINDS when cast:
// [adsi]'LDAP://evil.com/...' β connects to LDAP server
// [adsisearcher]'(objectClass=user)' β binds to AD and queries
// Microsoft's CLM allows these because it's for Windows admins in trusted
// domains; we block them since the target isn't validated.
'alias',
'allowemptycollection',
'allowemptystring',
'allownull',
'argumentcompleter',
'argumentcompletions',
'array',
'bigint',
'bool',
'byte',
'char',
'cimclass',
'cimconverter',
'ciminstance',
// 'cimsession' REMOVED β see wmi/adsi comment below
'cimtype',
'cmdletbinding',
'cultureinfo',
'datetime',
'decimal',
'double',
'dsclocalconfigurationmanager',
'dscproperty',
'dscresource',
'experimentaction',
'experimental',
'experimentalfeature',
'float',
'guid',
'hashtable',
'int',
'int16',
'int32',
'int64',
'ipaddress',
'ipendpoint',
'long',
'mailaddress',
'norunspaceaffinity',
'nullstring',
'objectsecurity',
'ordered',
'outputtype',
'parameter',
'physicaladdress',
'pscredential',
'pscustomobject',
'psdefaultvalue',
'pslistmodifier',
'psobject',
'psprimitivedictionary',
'pstypenameattribute',
'ref',
'regex',
'sbyte',
'securestring',
'semver',
'short',
'single',
'string',
'supportswildcards',
'switch',
'timespan',
'uint',
'uint16',
'uint32',
'uint64',
'ulong',
'uri',
'ushort',
'validatecount',
'validatedrive',
'validatelength',
'validatenotnull',
'validatenotnullorempty',
'validatenotnullorwhitespace',
'validatepattern',
'validaterange',
'validatescript',
'validateset',
'validatetrusteddata',
'validateuserdrive',
'version',
'void',
'wildcardpattern',
// SECURITY: 'wmi', 'wmiclass', 'wmisearcher', 'cimsession' REMOVED.
// WMI type casts perform WMI queries which can target remote computers
// (network request) and access dangerous classes like Win32_Process.
// cimsession creates a CIM session (network connection to remote host).
// [wmi]'\\evil-host\root\cimv2:Win32_Process.Handle="1"' β remote WMI
// [wmisearcher]'SELECT * FROM Win32_Process' β runs WQL query
// Same rationale as adsi/adsisearcher removal above.
'x500distinguishedname',
'x509certificate',
'xml',
// Full names for accelerators that resolve to System.* (AST may emit either)
'system.array',
'system.boolean',
'system.byte',
'system.char',
'system.datetime',
'system.decimal',
'system.double',
'system.guid',
'system.int16',
'system.int32',
'system.int64',
'system.numerics.biginteger',
'system.sbyte',
'system.single',
'system.string',
'system.timespan',
'system.uint16',
'system.uint32',
'system.uint64',
'system.uri',
'system.version',
'system.void',
'system.collections.hashtable',
'system.text.regularexpressions.regex',
'system.globalization.cultureinfo',
'system.net.ipaddress',
'system.net.ipendpoint',
'system.net.mail.mailaddress',
'system.net.networkinformation.physicaladdress',
'system.security.securestring',
'system.security.cryptography.x509certificates.x509certificate',
'system.security.cryptography.x509certificates.x500distinguishedname',
'system.xml.xmldocument',
// System.Management.Automation.* β FQ equivalents of PS-specific accelerators
'system.management.automation.pscredential',
'system.management.automation.pscustomobject',
'system.management.automation.pslistmodifier',
'system.management.automation.psobject',
'system.management.automation.psprimitivedictionary',
'system.management.automation.psreference',
'system.management.automation.semanticversion',
'system.management.automation.switchparameter',
'system.management.automation.wildcardpattern',
'system.management.automation.language.nullstring',
// Microsoft.Management.Infrastructure.* β FQ equivalents of CIM accelerators
// SECURITY: cimsession FQ REMOVED β same network-bind hazard as short name
// (creates a CIM session to a remote host).
'microsoft.management.infrastructure.cimclass',
'microsoft.management.infrastructure.cimconverter',
'microsoft.management.infrastructure.ciminstance',
'microsoft.management.infrastructure.cimtype',
// FQ equivalents of remaining short-name accelerators
// SECURITY: DirectoryEntry/DirectorySearcher/ManagementObject/
// ManagementClass/ManagementObjectSearcher FQ REMOVED β same network-bind
// hazard as short names adsi/adsisearcher/wmi/wmiclass/wmisearcher
// (LDAP bind, remote WMI). See short-name removal comments above.
'system.collections.specialized.ordereddictionary',
'system.security.accesscontrol.objectsecurity',
// Arrays of allowed types are allowed (e.g. [string[]])
// normalizeTypeName strips [] before lookup, so store the base name
'object',
'system.object',
// ModuleSpecification β full qualified name
'microsoft.powershell.commands.modulespecification',
].map(t => t.toLowerCase()),
)
/**
* Normalize a type name from AST TypeName.FullName or TypeName.Name.
* Handles array suffix ([]) and generic brackets.
*/
export function normalizeTypeName(name: string): string {
// Strip array suffix: "String[]" β "string" (arrays of allowed types are allowed)
// Strip generic args: "List[int]" β "list" (conservative β the generic wrapper
// might be unsafe even if the type arg is safe, so we check the outer type)
return name
.toLowerCase()
.replace(/\[\]$/, '')
.replace(/\[.*\]$/, '')
.trim()
}
/**
* True if typeName (from AST) is in Microsoft's CLM allowlist.
* Types NOT in this set trigger ask β they access system APIs CLM blocks.
*/
export function isClmAllowedType(typeName: string): boolean {
return CLM_ALLOWED_TYPES.has(normalizeTypeName(typeName))
}
|