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