(
input: { command: string },
parsed: ParsedPowerShellCommand,
toolPermissionContext: ToolPermissionContext,
)
| 130 | * - 'passthrough' if no mode-specific handling applies |
| 131 | */ |
| 132 | export function checkPermissionMode( |
| 133 | input: { command: string }, |
| 134 | parsed: ParsedPowerShellCommand, |
| 135 | toolPermissionContext: ToolPermissionContext, |
| 136 | ): PermissionResult { |
| 137 | // Skip bypass and dontAsk modes (handled elsewhere) |
| 138 | if ( |
| 139 | toolPermissionContext.mode === 'bypassPermissions' || |
| 140 | toolPermissionContext.mode === 'dontAsk' |
| 141 | ) { |
| 142 | return { |
| 143 | behavior: 'passthrough', |
| 144 | message: 'Mode is handled in main permission flow', |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | if (toolPermissionContext.mode !== 'acceptEdits') { |
| 149 | return { |
| 150 | behavior: 'passthrough', |
| 151 | message: 'No mode-specific validation required', |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | // acceptEdits mode: check if all commands are filesystem-modifying cmdlets |
| 156 | if (!parsed.valid) { |
| 157 | return { |
| 158 | behavior: 'passthrough', |
| 159 | message: 'Cannot validate mode for unparsed command', |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | // SECURITY: Check for subexpressions, script blocks, or member invocations |
| 164 | // that could be used to smuggle arbitrary code through acceptEdits mode. |
| 165 | const securityFlags = deriveSecurityFlags(parsed) |
| 166 | if ( |
| 167 | securityFlags.hasSubExpressions || |
| 168 | securityFlags.hasScriptBlocks || |
| 169 | securityFlags.hasMemberInvocations || |
| 170 | securityFlags.hasSplatting || |
| 171 | securityFlags.hasAssignments || |
| 172 | securityFlags.hasStopParsing || |
| 173 | securityFlags.hasExpandableStrings |
| 174 | ) { |
| 175 | return { |
| 176 | behavior: 'passthrough', |
| 177 | message: |
| 178 | 'Command contains subexpressions, script blocks, or member invocations that require approval', |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | const segments = getPipelineSegments(parsed) |
| 183 | |
| 184 | // SECURITY: Empty segments with valid parse = no commands to check, don't auto-allow |
| 185 | if (segments.length === 0) { |
| 186 | return { |
| 187 | behavior: 'passthrough', |
| 188 | message: 'No commands found to validate for acceptEdits mode', |
| 189 | } |
no test coverage detected