Public/Test-CustomDetectionMitreTechnique.ps1

function Test-CustomDetectionMitreTechnique {
    <#
    .SYNOPSIS
        Validates that MITRE ATT&CK techniques in a detection rule are supported by XDR for the selected category.
 
    .DESCRIPTION
        Reads the alertCategory and mitreTechniques from a detection YAML file or object and checks
        each technique against the set of techniques that Microsoft XDR supports for that category.
        Techniques not supported by XDR for the given category are reported as invalid.
 
        The technique mapping is derived from the XDR portal's front-end data and reflects the
        actual techniques available in each alert category dropdown.
 
        Categories not present in the XDR mapping (e.g. SuspiciousActivity) cannot be validated;
        in that case the function emits a warning and returns IsValid = $true with no invalid techniques.
 
    .PARAMETER InputFile
        Path to a detection YAML (.yaml/.yml) file.
 
    .PARAMETER InputObject
        A parsed YAML/detection PSObject. Accepts pipeline input.
 
    .OUTPUTS
        PSCustomObject with:
          IsValid - $true if all listed techniques are supported for the category
          Category - the alertCategory value
          ValidTechniques - techniques that are supported for the category
          InvalidTechniques- techniques that are NOT supported for the category
          IsValid - $true if all listed techniques are supported for the category
          Category - the alertCategory value
          ValidTechniques - techniques that are supported for the category
          InvalidTechniques- techniques that are NOT supported for the category
 
    .EXAMPLE
        Test-CustomDetectionMitreTechnique -InputFile '.\detection.yaml'
 
        Validates all MITRE techniques in the YAML file against the XDR category mapping.
 
    .EXAMPLE
        Get-ChildItem '.\detections\*.yaml' | ForEach-Object { Test-CustomDetectionMitreTechnique -InputFile $_.FullName }
 
        Validates all YAML files in a directory.
 
    .EXAMPLE
        Import-CustomDetectionYamlFile -FilePath '.\detection.yaml' | Test-CustomDetectionMitreTechnique
 
        Pipeline input from a parsed YAML object.
 
    .EXAMPLE
        $result = Test-CustomDetectionMitreTechnique -InputFile '.\detection.yaml'
        if (-not $result.IsValid) {
            Write-Warning "Unsupported techniques: $($result.InvalidTechniques -join ', ')"
        }
    #>

    [CmdletBinding(DefaultParameterSetName = 'File')]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory, ParameterSetName = 'File', HelpMessage = 'Path to a detection YAML file')]
        [ValidateScript({ Test-Path $_ -PathType Leaf })]
        [string]$InputFile,

        [Parameter(Mandatory, ParameterSetName = 'Object', ValueFromPipeline, HelpMessage = 'Parsed detection object')]
        [ValidateNotNull()]
        [PSObject]$InputObject
    )

    begin {
        # XDR MITRE technique mapping per alert category
        # Source: Microsoft XDR portal front-end (xdr-main.js)
        $xdrTechniqueMap = @{
            DefenseEvasion          = @('T1055.011', 'T1205.002', 'T1066', 'T1027.011', 'T1218.011', 'T1143', 'T1027.009', 'T1150', 'T1556.003', 'T1578.004', 'T1148', 'T1564.012', 'T1222.002', 'T1216.001', 'T1574.007', 'T1006', 'T1666', 'T1564.008', 'T1027.013', 'T1014', 'T1109', 'T1036.007', 'T1548.002', 'T1099', 'T1548.003', 'T1578', 'T1542.001', 'T1574.011', 'T1542.003', 'T1116', 'T1218.013', 'T1093', 'T1036.005', 'T1600', 'T1036.008', 'T1121', 'T1564', 'T1484.002', 'T1527', 'T1562.009', 'T1542.005', 'T1497.001', 'T1070.002', 'T1218.004', 'T1089', 'T1027.008', 'T1574.001', 'T1553.001', 'T1553.002', 'T1036.009', 'T1222.001', 'T1574.014', 'T1218.007', 'T1556.002', 'T1070.007', 'T1600.001', 'T1070.003', 'T1202', 'T1536', 'T1140', 'T1562', 'T1055.003', 'T1036', 'T1070.008', 'T1055', 'T1205', 'T1218', 'T1038', 'T1070.006', 'T1620', 'T1480.002', 'T1564.011', 'T1497.003', 'T1218.003', 'T1562.002', 'T1218.002', 'T1599.001', 'T1036.011', 'T1009', 'T1550', 'T1181', 'T1562.004', 'T1152', 'T1553.003', 'T1556.007', 'T1218.015', 'T1562.012', 'T1207', 'T1553.006', 'T1610', 'T1107', 'T1112', 'T1574.008', 'T1535', 'T1564.013', 'T1027.001', 'T1484.001', 'T1078.001', 'T1183', 'T1085', 'T1574.006', 'T1070.001', 'T1222', 'T1027.016', 'T1548', 'T1134.002', 'T1548.001', 'T1117', 'T1054', 'T1108', 'T1218.008', 'T1548.005', 'T1144', 'T1045', 'T1055.013', 'T1578.003', 'T1574.005', 'T1198', 'T1562.006', 'T1564.014', 'T1562.007', 'T1036.002', 'T1027.017', 'T1542.002', 'T1070', 'T1550.003', 'T1036.004', 'T1055.004', 'T1647', 'T1127.003', 'T1191', 'T1553.005', 'T1600.002', 'T1542', 'T1064', 'T1612', 'T1055.002', 'T1218.012', 'T1562.010', 'T1497', 'T1218.005', 'T1480', 'T1134.001', 'T1205.001', 'T1027.012', 'T1564.002', 'T1134.003', 'T1196', 'T1562.003', 'T1556.008', 'T1497.002', 'T1134.004', 'T1055.014', 'T1122', 'T1502', 'T1574.010', 'T1149', 'T1170', 'T1574.013', 'T1542.004', 'T1218.001', 'T1070.005', 'T1562.001', 'T1601', 'T1574', 'T1027.005', 'T1078', 'T1073', 'T1055.012', 'T1564.009', 'T1027', 'T1556.006', 'T1036.001', 'T1564.006', 'T1027.014', 'T1134.005', 'T1599', 'T1553', 'T1548.004', 'T1218.010', 'T1036.003', 'T1562.011', 'T1574.009', 'T1186', 'T1027.003', 'T1550.004', 'T1078.002', 'T1218.009', 'T1506', 'T1553.004', 'T1027.004', 'T1564.007', 'T1197', 'T1127.001', 'T1656', 'T1578.005', 'T1088', 'T1562.008', 'T1564.003', 'T1127.002', 'T1070.010', 'T1147', 'T1556.009', 'T1578.002', 'T1500', 'T1055.009', 'T1223', 'T1601.001', 'T1070.009', 'T1146', 'T1036.010', 'T1556.001', 'T1027.006', 'T1556.005', 'T1027.010', 'T1130', 'T1070.004', 'T1158', 'T1221', 'T1134', 'T1027.002', 'T1564.005', 'T1672', 'T1151', 'T1055.005', 'T1622', 'T1036.006', 'T1550.002', 'T1574.002', 'T1216.002', 'T1126', 'T1548.006', 'T1055.008', 'T1027.007', 'T1055.015', 'T1484', 'T1220', 'T1564.001', 'T1578.001', 'T1550.001', 'T1078.004', 'T1480.001', 'T1564.004', 'T1096', 'T1055.001', 'T1556', 'T1216', 'T1118', 'T1556.004', 'T1027.015', 'T1574.004', 'T1601.002', 'T1078.003', 'T1211', 'T1127', 'T1218.014', 'T1564.010', 'T1574.012')
            PrivilegeEscalation     = @('T1055.011', 'T1053.005', 'T1037', 'T1150', 'T1574.007', 'T1044', 'T1546.013', 'T1514', 'T1543', 'T1546.006', 'T1053.007', 'T1548.002', 'T1548.003', 'T1574.011', 'T1178', 'T1547', 'T1013', 'T1206', 'T1547.014', 'T1484.002', 'T1543.003', 'T1053.003', 'T1165', 'T1098.003', 'T1547.012', 'T1574.001', 'T1103', 'T1574.014', 'T1098.006', 'T1053', 'T1058', 'T1098.007', 'T1055.003', 'T1546.011', 'T1547.010', 'T1037.002', 'T1055', 'T1038', 'T1050', 'T1611', 'T1547.009', 'T1182', 'T1547.005', 'T1181', 'T1543.004', 'T1574.008', 'T1484.001', 'T1078.001', 'T1547.003', 'T1183', 'T1546.005', 'T1574.006', 'T1053.001', 'T1179', 'T1547.011', 'T1548', 'T1134.002', 'T1548.001', 'T1547.004', 'T1098.004', 'T1546.012', 'T1548.005', 'T1055.013', 'T1574.005', 'T1546.008', 'T1504', 'T1055.004', 'T1138', 'T1546.009', 'T1098.005', 'T1055.002', 'T1547.015', 'T1134.001', 'T1098.001', 'T1134.003', 'T1053.004', 'T1546.003', 'T1134.004', 'T1546.001', 'T1055.014', 'T1015', 'T1546.014', 'T1502', 'T1169', 'T1574.010', 'T1547.001', 'T1098', 'T1547.006', 'T1574.013', 'T1053.006', 'T1157', 'T1574', 'T1543.005', 'T1078', 'T1055.012', 'T1068', 'T1546', 'T1546.004', 'T1134.005', 'T1548.004', 'T1547.002', 'T1546.015', 'T1574.009', 'T1166', 'T1037.005', 'T1100', 'T1078.002', 'T1034', 'T1037.003', 'T1088', 'T1546.010', 'T1546.002', 'T1543.001', 'T1055.009', 'T1519', 'T1546.016', 'T1037.004', 'T1134', 'T1543.002', 'T1547.013', 'T1055.005', 'T1547.007', 'T1574.002', 'T1098.002', 'T1548.006', 'T1160', 'T1055.008', 'T1037.001', 'T1055.015', 'T1484', 'T1547.008', 'T1078.004', 'T1053.002', 'T1055.001', 'T1546.017', 'T1546.007', 'T1574.004', 'T1078.003', 'T1574.012', 'T0874', 'T0890')
            Execution               = @('T1053.005', 'T1047', 'T1129', 'T1059.007', 'T1053.007', 'T1121', 'T1559.002', 'T1204.002', 'T1053.003', 'T1559.001', 'T1675', 'T1053', 'T1059.002', 'T1106', 'T1059.010', 'T1153', 'T1569.003', 'T1152', 'T1059.009', 'T1610', 'T1155', 'T1085', 'T1674', 'T1053.001', 'T1117', 'T1177', 'T1059', 'T1175', 'T1609', 'T1191', 'T1064', 'T1569.001', 'T1059.008', 'T1559.003', 'T1204', 'T1196', 'T1053.004', 'T1072', 'T1059.001', 'T1170', 'T1053.006', 'T1061', 'T1059.004', 'T1559', 'T1059.011', 'T1204.003', 'T1154', 'T1203', 'T1168', 'T1028', 'T1059.006', 'T1569', 'T1059.003', 'T1223', 'T1059.012', 'T1651', 'T1059.005', 'T1204.004', 'T1151', 'T1648', 'T1173', 'T1204.001', 'T1569.002', 'T1053.002', 'T1035', 'T1086', 'T1118', 'T0821', 'T0807', 'T0863', 'T0858', 'T0853', 'T0871', 'T0895', 'T0875', 'T0874', 'T0844', 'T0823', 'T0834')
            Persistence             = @('T1053.005', 'T1205.002', 'T1156', 'T1067', 'T1037', 'T1161', 'T1150', 'T1556.003', 'T1574.007', 'T1044', 'T1546.013', 'T1501', 'T1543', 'T1133', 'T1109', 'T1546.006', 'T1053.007', 'T1542.001', 'T1574.011', 'T1163', 'T1542.003', 'T1547', 'T1013', 'T1547.014', 'T1176.001', 'T1180', 'T1542.005', 'T1543.003', 'T1053.003', 'T1165', 'T1137', 'T1098.003', 'T1547.012', 'T1574.001', 'T1103', 'T1137.006', 'T1505.002', 'T1574.014', 'T1098.006', 'T1053', 'T1162', 'T1556.002', 'T1505.005', 'T1176', 'T1058', 'T1137.005', 'T1098.007', 'T1546.011', 'T1547.010', 'T1037.002', 'T1205', 'T1038', 'T1050', 'T1547.009', 'T1062', 'T1182', 'T1525', 'T1547.005', 'T1004', 'T1131', 'T1152', 'T1556.007', 'T1112', 'T1543.004', 'T1574.008', 'T1505.003', 'T1078.001', 'T1547.003', 'T1183', 'T1031', 'T1546.005', 'T1574.006', 'T1136.001', 'T1053.001', 'T1176.002', 'T1179', 'T1547.011', 'T1547.004', 'T1019', 'T1042', 'T1164', 'T1108', 'T1098.004', 'T1215', 'T1101', 'T1546.012', 'T1177', 'T1574.005', 'T1546.008', 'T1504', 'T1198', 'T1136.002', 'T1542.002', 'T1137.001', 'T1138', 'T1546.009', 'T1098.005', 'T1542', 'T1547.015', 'T1205.001', 'T1098.001', 'T1053.004', 'T1556.008', 'T1546.003', 'T1060', 'T1554', 'T1023', 'T1546.001', 'T1122', 'T1015', 'T1546.014', 'T1574.010', 'T1547.001', 'T1136.003', 'T1098', 'T1547.006', 'T1574.013', 'T1053.006', 'T1542.004', 'T1137.003', 'T1157', 'T1574', 'T1543.005', 'T1078', 'T1556.006', 'T1505.004', 'T1154', 'T1546', 'T1546.004', 'T1547.002', 'T1128', 'T1546.015', 'T1137.004', 'T1574.009', 'T1168', 'T1166', 'T1037.005', 'T1100', 'T1671', 'T1078.002', 'T1034', 'T1037.003', 'T1197', 'T1546.010', 'T1546.002', 'T1556.009', 'T1543.001', 'T1519', 'T1505', 'T1556.001', 'T1556.005', 'T1546.016', 'T1158', 'T1037.004', 'T1209', 'T1159', 'T1543.002', 'T1668', 'T1136', 'T1547.013', 'T1547.007', 'T1574.002', 'T1098.002', 'T1084', 'T1160', 'T1653', 'T1037.001', 'T1137.002', 'T1547.008', 'T1078.004', 'T1053.002', 'T1556', 'T1546.017', 'T1546.007', 'T1505.006', 'T1505.001', 'T1556.004', 'T1574.004', 'T1078.003', 'T1574.012', 'T0857', 'T0891', 'T0859', 'T0873', 'T0839', 'T0889')
            CommandAndControl       = @('T1205.002', 'T1132.001', 'T1568.002', 'T1071.004', 'T1172', 'T1071.005', 'T1573.001', 'T1568.001', 'T1071', 'T1024', 'T1219', 'T1079', 'T1659', 'T1205', 'T1032', 'T1572', 'T1483', 'T1071.003', 'T1092', 'T1090.002', 'T1090', 'T1219.001', 'T1568', 'T1188', 'T1102', 'T1568.003', 'T1104', 'T1205.001', 'T1026', 'T1071.002', 'T1102.003', 'T1090.003', 'T1219.003', 'T1001', 'T1571', 'T1573', 'T1102.002', 'T1573.002', 'T1095', 'T1001.003', 'T1065', 'T1090.004', 'T1132', 'T1219.002', 'T1132.002', 'T1071.001', 'T1105', 'T1665', 'T1001.002', 'T1008', 'T1090.001', 'T1094', 'T1102.001', 'T1001.001', 'T1043', 'T0884', 'T0869', 'T0885')
            Collection              = @('T1560.001', 'T1113', 'T1557', 'T1056.001', 'T1602', 'T1213.002', 'T1123', 'T1560.003', 'T1114', 'T1025', 'T1074.001', 'T1114.001', 'T1119', 'T1115', 'T1530', 'T1074.002', 'T1005', 'T1560.002', 'T1557.004', 'T1602.002', 'T1560', 'T1185', 'T1557.003', 'T1557.001', 'T1056.003', 'T1125', 'T1213.001', 'T1114.003', 'T1074', 'T1056.002', 'T1039', 'T1114.002', 'T1056', 'T1213.004', 'T1557.002', 'T1213.003', 'T1213', 'T1602.001', 'T1056.004', 'T1213.005', 'T0887', 'T0850', 'T0861', 'T0868', 'T0801', 'T0845', 'T0811', 'T0802', 'T0877', 'T0825', 'T0870', 'T0830', 'T0852', 'T0893')
            LateralMovement         = @('T1021.005', 'T1080', 'T1527', 'T1021.004', 'T1017', 'T1091', 'T1021.008', 'T1563.001', 'T1021.002', 'T1550', 'T1076', 'T1021', 'T1563', 'T1021.006', 'T1021.003', 'T1175', 'T1550.003', 'T1051', 'T1021.007', 'T1072', 'T1210', 'T1534', 'T1097', 'T1570', 'T1184', 'T1075', 'T1028', 'T1550.004', 'T1506', 'T1563.002', 'T1550.002', 'T1021.001', 'T1550.001', 'T1077', 'T0866', 'T0812', 'T0844', 'T0843', 'T0891', 'T0859', 'T0886', 'T0867')
            CredentialAccess        = @('T1557', 'T1556.003', 'T1056.001', 'T1110.001', 'T1003', 'T1171', 'T1539', 'T1003.002', 'T1552.005', 'T1555.002', 'T1522', 'T1110.002', 'T1555.001', 'T1003.004', 'T1606.002', 'T1167', 'T1214', 'T1003.007', 'T1555.005', 'T1040', 'T1552.002', 'T1556.002', 'T1558.005', 'T1558.004', 'T1558', 'T1555', 'T1552', 'T1139', 'T1503', 'T1557.004', 'T1556.007', 'T1145', 'T1555.003', 'T1557.003', 'T1552.004', 'T1557.001', 'T1003.001', 'T1179', 'T1110.003', 'T1056.003', 'T1003.005', 'T1558.001', 'T1649', 'T1552.003', 'T1552.001', 'T1606.001', 'T1528', 'T1552.006', 'T1556.008', 'T1141', 'T1606', 'T1621', 'T1552.008', 'T1212', 'T1142', 'T1056.002', 'T1110', 'T1110.004', 'T1208', 'T1556.006', 'T1187', 'T1174', 'T1081', 'T1056', 'T1557.002', 'T1556.009', 'T1555.006', 'T1003.008', 'T1558.002', 'T1555.004', 'T1556.001', 'T1556.005', 'T1111', 'T1003.003', 'T1558.003', 'T1003.006', 'T1556', 'T1056.004', 'T1552.007', 'T1556.004')
            Discovery               = @('T1033', 'T1613', 'T1016.001', 'T1069', 'T1069.003', 'T1615', 'T1652', 'T1087.002', 'T1063', 'T1087.001', 'T1497.001', 'T1069.002', 'T1007', 'T1040', 'T1135', 'T1120', 'T1082', 'T1016.002', 'T1010', 'T1087.003', 'T1497.003', 'T1580', 'T1217', 'T1673', 'T1016', 'T1087', 'T1482', 'T1083', 'T1049', 'T1497', 'T1619', 'T1654', 'T1087.004', 'T1057', 'T1497.002', 'T1069.001', 'T1201', 'T1614.001', 'T1012', 'T1614', 'T1518.001', 'T1526', 'T1018', 'T1046', 'T1518', 'T1538', 'T1622', 'T1124', 'T0887', 'T0888', 'T0842', 'T0841', 'T0854', 'T0808', 'T0846', 'T0824', 'T0840')
            ResourceDevelopment     = @('T1583', 'T1583.007', 'T1588.007', 'T1584.008', 'T1583.008', 'T1588.004', 'T1583.002', 'T1587.003', 'T1587.001', 'T1586.001', 'T1588.006', 'T1583.005', 'T1608.004', 'T1587.002', 'T1584.003', 'T1586.003', 'T1586.002', 'T1608.001', 'T1583.001', 'T1608.002', 'T1583.004', 'T1585.002', 'T1588.001', 'T1583.003', 'T1584', 'T1586', 'T1584.005', 'T1608', 'T1608.005', 'T1583.006', 'T1585.003', 'T1588.002', 'T1584.006', 'T1585.001', 'T1587.004', 'T1608.003', 'T1584.002', 'T1585', 'T1588', 'T1650', 'T1584.007', 'T1584.004', 'T1608.006', 'T1588.003', 'T1587', 'T1588.005', 'T1584.001')
            Reconnaissance          = @('T1592', 'T1596.003', 'T1597.002', 'T1590.005', 'T1590.002', 'T1596.002', 'T1594', 'T1596.001', 'T1591.003', 'T1592.001', 'T1598.003', 'T1590.004', 'T1590.003', 'T1597.001', 'T1589', 'T1595.002', 'T1596', 'T1595', 'T1589.002', 'T1598.004', 'T1590.006', 'T1593.002', 'T1591.002', 'T1593.003', 'T1589.003', 'T1592.004', 'T1598.002', 'T1596.004', 'T1591', 'T1590', 'T1593', 'T1597', 'T1592.003', 'T1592.002', 'T1593.001', 'T1589.001', 'T1595.003', 'T1591.004', 'T1598', 'T1595.001', 'T1590.001', 'T1596.005', 'T1591.001', 'T1598.001')
            Impact                  = @('T1561.002', 'T1498.001', 'T1492', 'T1491.002', 'T1499.001', 'T1485.001', 'T1496.003', 'T1499.003', 'T1561', 'T1565.001', 'T1489', 'T1499.004', 'T1487', 'T1565.003', 'T1498.002', 'T1499.002', 'T1491', 'T1496.002', 'T1657', 'T1491.001', 'T1496.004', 'T1496.001', 'T1565', 'T1531', 'T1486', 'T1488', 'T1667', 'T1499', 'T1494', 'T1493', 'T1496', 'T1565.002', 'T1485', 'T1498', 'T1495', 'T1490', 'T1561.001', 'T1529', 'T0829', 'T0831', 'T0837', 'T0832', 'T0815', 'T0880', 'T0828', 'T0879', 'T0827', 'T0826', 'T0882', 'T0813')
            InitialAccess           = @('T1133', 'T1195.001', 'T1192', 'T1566.002', 'T1566.001', 'T1195.003', 'T1091', 'T1195', 'T1190', 'T1659', 'T1078.001', 'T1193', 'T1199', 'T1566', 'T1078', 'T1566.004', 'T1195.002', 'T1078.002', 'T1194', 'T1200', 'T1189', 'T1078.004', 'T1566.003', 'T1078.003', 'T1669', 'T0860', 'T0819', 'T0864', 'T0810', 'T0862', 'T0865', 'T0817', 'T0866', 'T0822', 'T0848', 'T0847', 'T0818', 'T0886', 'T0883')
            Exfiltration            = @('T1567', 'T1567.004', 'T1029', 'T1011', 'T1011.001', 'T1020', 'T1048.001', 'T1020.001', 'T1567.001', 'T1048.002', 'T1041', 'T1048', 'T1052.001', 'T1002', 'T1567.003', 'T1567.002', 'T1030', 'T1537', 'T1022', 'T1052', 'T1048.003')
            InhibitResponseFunction = @('T0803', 'T0881', 'T0800', 'T0814', 'T0805', 'T0816', 'T0878', 'T0835', 'T0851', 'T0804', 'T0809', 'T0857', 'T0833', 'T0838', 'T0892')
            ImpairProcessControl    = @('T0836', 'T0855', 'T0856', 'T0806', 'T0875', 'T0833', 'T0839')
            Evasion                 = @('T0894', 'T0858', 'T0851', 'T0872', 'T0856', 'T0820', 'T0849')
        }
    }

    process {
        try {
            $yamlObj = if ($PSCmdlet.ParameterSetName -eq 'File') {
                Import-CustomDetectionYamlFile -FilePath $InputFile
            } else {
                $InputObject
            }

            $category = $yamlObj.alertCategory
            $techniques = @($yamlObj.mitreTechniques)

            if (-not $category) {
                throw "The detection object does not contain an 'alertCategory' property."
            }

            # No techniques defined — nothing to validate
            if (-not $techniques -or $techniques.Count -eq 0) {
                Write-Verbose "No mitreTechniques defined in the detection. Nothing to validate."
                return [PSCustomObject]@{
                    IsValid           = $true
                    Category          = $category
                    ValidTechniques   = @()
                    InvalidTechniques = @()
                }
            }

            # Category not present in XDR mapping — cannot validate
            if (-not $xdrTechniqueMap.ContainsKey($category)) {
                Write-Warning "Category '$category' is not present in the XDR technique mapping. Validation skipped."
                return [PSCustomObject]@{
                    IsValid           = $true
                    Category          = $category
                    ValidTechniques   = @($techniques)
                    InvalidTechniques = @()
                }
            }

            $supported = $xdrTechniqueMap[$category]
            $validTechniques = [System.Collections.Generic.List[string]]::new()
            $invalidTechniques = [System.Collections.Generic.List[string]]::new()

            foreach ($technique in $techniques) {
                if ($technique -in $supported) {
                    $validTechniques.Add($technique)
                } else {
                    $invalidTechniques.Add($technique)
                }
            }

            $isValid = $invalidTechniques.Count -eq 0

            if (-not $isValid) {
                $invalidList = $invalidTechniques -join ', '
                Write-Warning "The following MITRE technique(s) are not supported by XDR for category '$category': $invalidList"
            }

            [PSCustomObject]@{
                IsValid           = $isValid
                Category          = $category
                ValidTechniques   = $validTechniques.ToArray()
                InvalidTechniques = $invalidTechniques.ToArray()
            }
        } catch {
            Write-Error "Error validating MITRE techniques: $_"
            throw
        }
    }
}