UNPKG

@mitre-attack/attack-data-model

Version:

A TypeScript API for the MITRE ATT&CK data model

211 lines (207 loc) 7.73 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/schemas/common/property-schemas/attack-id.ts var attack_id_exports = {}; __export(attack_id_exports, { attackIdExamples: () => attackIdExamples, attackIdMessages: () => attackIdMessages, attackIdPatterns: () => attackIdPatterns, createAttackIdSchema: () => createAttackIdSchema, createOldMitreAttackIdSchema: () => createOldMitreAttackIdSchema, getAttackIdExample: () => getAttackIdExample, stixTypeToAttackIdMapping: () => stixTypeToAttackIdMapping, xMitreOldAttackIdSchema: () => xMitreOldAttackIdSchema }); module.exports = __toCommonJS(attack_id_exports); var import_v4 = require("zod/v4"); // src/schemas/common/property-schemas/generics.ts var import_zod = require("zod"); var nonEmptyRequiredString = import_zod.z.string().trim().min(1, { error: "At least one character is required. Whitespace is not permissible." }); var emptyStixListErrorMessage = "Empty lists are prohibited in STIX and MUST NOT be used as a substitute for omitting the property if it is optional. The list MUST be present and MUST have at least one value."; var stixListOfString = import_zod.z.array(nonEmptyRequiredString).min(1, { error: emptyStixListErrorMessage }); // src/schemas/common/property-schemas/attack-id.ts var attackIdConfig = { tactic: { pattern: /^TA\d{4}$/, message: "Must match ATT&CK Tactic ID format (TA####)", example: "TA####", stixTypes: ["x-mitre-tactic"] }, technique: { pattern: /^T\d{4}$/, message: "Must match ATT&CK Technique ID format (T####)", example: "T####", stixTypes: ["attack-pattern"] // Note: attack-pattern can be technique or subtechnique }, subtechnique: { pattern: /^T\d{4}\.\d{3}$/, message: "Must match ATT&CK Sub-technique ID format (T####.###)", example: "T####.###", stixTypes: ["attack-pattern"] // Note: attack-pattern can be technique or subtechnique }, group: { pattern: /^G\d{4}$/, message: "Must match ATT&CK Group ID format (G####)", example: "G####", stixTypes: ["intrusion-set"] }, software: { pattern: /^S\d{4}$/, message: "Must match ATT&CK Software ID format (S####)", example: "S####", stixTypes: ["malware", "tool"] }, mitigation: { pattern: /^M\d{4}$/, message: "Must match ATT&CK Mitigation ID format (M####)", example: "M####", stixTypes: ["course-of-action"] }, asset: { pattern: /^A\d{4}$/, message: "Must match ATT&CK Asset ID format (A####)", example: "A####", stixTypes: ["x-mitre-asset"] }, "data-source": { pattern: /^DS\d{4}$/, message: "Must match ATT&CK Data Source ID format (DS####)", example: "DS####", stixTypes: ["x-mitre-data-source"] }, campaign: { pattern: /^C\d{4}$/, message: "Must match ATT&CK Campaign ID format (C####)", example: "C####", stixTypes: ["campaign"] }, "data-component": { pattern: /^DC\d{4}$/, message: "Must match ATT&CK Data Component Source ID format (DC####)", example: "DC####", stixTypes: ["x-mitre-data-component"] }, "detection-strategy": { pattern: /^DET\d{4}$/, message: "Must match ATT&CK Detection Strategy Source ID format (DET####)", example: "DET####", stixTypes: ["x-mitre-detection-strategy"] }, analytic: { pattern: /^AN\d{4}$/, message: "Must match ATT&CK Analytic Source ID format (AN####)", example: "AN####", stixTypes: ["x-mitre-analytic"] } }; var stixTypeToAttackIdMapping = { "x-mitre-tactic": "tactic", "attack-pattern": "technique", // Default to technique; subtechnique handling is done contextually "intrusion-set": "group", malware: "software", tool: "software", "course-of-action": "mitigation", "x-mitre-asset": "asset", "x-mitre-data-source": "data-source", campaign: "campaign", "x-mitre-data-component": "data-component", "x-mitre-detection-strategy": "detection-strategy", "x-mitre-analytic": "analytic" }; var attackIdPatterns = Object.fromEntries( Object.entries(attackIdConfig).map(([key, config]) => [key, config.pattern]) ); var attackIdMessages = Object.fromEntries( Object.entries(attackIdConfig).map(([key, config]) => [key, config.message]) ); var attackIdExamples = Object.fromEntries( Object.entries(attackIdConfig).map(([key, config]) => [key, config.example]) ); function getAttackIdExample(stixType) { if (stixType === "attack-pattern") { return `${attackIdExamples.technique} or ${attackIdExamples.subtechnique}`; } const attackIdType = stixTypeToAttackIdMapping[stixType]; return attackIdExamples[attackIdType]; } var createAttackIdSchema = (stixType) => { const attackIdType = stixTypeToAttackIdMapping[stixType]; if (stixType === "attack-pattern") { return import_v4.z.string().refine( (id) => attackIdPatterns.technique.test(id) || attackIdPatterns.subtechnique.test(id), { error: `Must match either ATT&CK Technique ID format (${attackIdExamples.technique}) or Sub-technique ID format (${attackIdExamples.subtechnique})` } ); } return import_v4.z.string().regex(attackIdPatterns[attackIdType], attackIdMessages[attackIdType]).meta({ description: "ATT&CK IDs are human-readable identifiers commonly used for referencing objects in documentation and communication. Each ATT&CK object type follows a specific ID format, typically denoted by a type code prefix (e.g., `TA` for tactic) followed by a four-digit identifier (e.g., 0001)" }); }; var oldAttackIdRegex = /^MOB-(M|S)\d{4}$/; function createOldMitreAttackIdSchema(stixType) { const baseSchema = nonEmptyRequiredString.meta({ description: "Old ATT&CK IDs that may have been associated with this object" }); switch (stixType) { case "malware": case "tool": return baseSchema.refine( (value) => { return /^MOB-S\d{4}$/.test(value); }, { message: `x_mitre_old_attack_id for ${stixType} need to be in the format MOB-S####` } ); case "course-of-action": return baseSchema.refine( (value) => { return /^MOB-M\d{4}$/.test(value); }, { message: `x_mitre_old_attack_id for ${stixType} need to be in the format MOB-M####` } ); default: throw new Error(`Unsupported STIX type: ${stixType}`); } } var xMitreOldAttackIdSchema = nonEmptyRequiredString.refine( (value) => { return oldAttackIdRegex.test(value); }, { message: "Must be in the format 'MOB-X0000' where X is either 'M' or 'S', followed by exactly four digits" } ).meta({ description: "Old ATT&CK IDs that may have been associated with this object" }); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { attackIdExamples, attackIdMessages, attackIdPatterns, createAttackIdSchema, createOldMitreAttackIdSchema, getAttackIdExample, stixTypeToAttackIdMapping, xMitreOldAttackIdSchema });