( rawType: string, expressionType?: string, )
| 747 | /** Map raw .NET AST type name to our CommandElementType union */ |
| 748 | // exported for testing |
| 749 | export function mapElementType( |
| 750 | rawType: string, |
| 751 | expressionType?: string, |
| 752 | ): CommandElementType { |
| 753 | switch (rawType) { |
| 754 | case 'ScriptBlockExpressionAst': |
| 755 | return 'ScriptBlock' |
| 756 | case 'SubExpressionAst': |
| 757 | case 'ArrayExpressionAst': |
| 758 | // SECURITY: ArrayExpressionAst (@()) is a sibling of SubExpressionAst, |
| 759 | // not a subclass. Both evaluate arbitrary pipelines with side effects: |
| 760 | // Get-ChildItem @(Remove-Item ./data) runs Remove-Item inside @(). |
| 761 | // Map both to SubExpression so hasSubExpressions fires and isReadOnlyCommand |
| 762 | // rejects (it doesn't check nestedCommands, only pipeline.commands[]). |
| 763 | return 'SubExpression' |
| 764 | case 'ExpandableStringExpressionAst': |
| 765 | return 'ExpandableString' |
| 766 | case 'InvokeMemberExpressionAst': |
| 767 | case 'MemberExpressionAst': |
| 768 | return 'MemberInvocation' |
| 769 | case 'VariableExpressionAst': |
| 770 | return 'Variable' |
| 771 | case 'StringConstantExpressionAst': |
| 772 | case 'ConstantExpressionAst': |
| 773 | // ConstantExpressionAst covers numeric literals (5, 3.14). For |
| 774 | // permission purposes a numeric literal is as safe as a string |
| 775 | // literal — it's an inert value, not code. Without this mapping, |
| 776 | // `-Seconds:5` produced children[0].type='Other' and consumers |
| 777 | // checking `children.some(c => c.type !== 'StringConstant')` would |
| 778 | // false-positive ask on harmless numeric args. |
| 779 | return 'StringConstant' |
| 780 | case 'CommandParameterAst': |
| 781 | return 'Parameter' |
| 782 | case 'ParenExpressionAst': |
| 783 | return 'SubExpression' |
| 784 | case 'CommandExpressionAst': |
| 785 | // Delegate to the wrapped expression type so we catch SubExpressionAst, |
| 786 | // ExpandableStringExpressionAst, ScriptBlockExpressionAst, etc. |
| 787 | // without maintaining a manual list. Falls through to 'Other' if the |
| 788 | // inner type is unrecognised. |
| 789 | if (expressionType) { |
| 790 | return mapElementType(expressionType) |
| 791 | } |
| 792 | return 'Other' |
| 793 | default: |
| 794 | return 'Other' |
| 795 | } |
| 796 | } |
| 797 | |
| 798 | /** Classify command name as cmdlet, application, or unknown */ |
| 799 | // exported for testing |
no outgoing calls
no test coverage detected