@mitre-attack/attack-data-model
Version:
A TypeScript API for the MITRE ATT&CK data model
247 lines (244 loc) • 10.1 kB
TypeScript
import { z } from 'zod/v4';
import { StixType } from './stix-type.js';
/**
* Comprehensive ATT&CK ID configuration map.
* This single source of truth defines all ATT&CK ID types, their patterns, messages, and STIX type mappings.
*
* To add a new ATT&CK ID type:
* 1. Add an entry to this map with the pattern, message, example, and stixTypes
* 2. That's it! All other functionality will automatically work.
*/
declare const attackIdConfig: {
readonly tactic: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Tactic ID format (TA####)";
readonly example: "TA####";
readonly stixTypes: readonly ["x-mitre-tactic"];
};
readonly technique: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Technique ID format (T####)";
readonly example: "T####";
readonly stixTypes: readonly ["attack-pattern"];
};
readonly subtechnique: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Sub-technique ID format (T####.###)";
readonly example: "T####.###";
readonly stixTypes: readonly ["attack-pattern"];
};
readonly group: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Group ID format (G####)";
readonly example: "G####";
readonly stixTypes: readonly ["intrusion-set"];
};
readonly software: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Software ID format (S####)";
readonly example: "S####";
readonly stixTypes: readonly ["malware", "tool"];
};
readonly mitigation: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Mitigation ID format (M####)";
readonly example: "M####";
readonly stixTypes: readonly ["course-of-action"];
};
readonly asset: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Asset ID format (A####)";
readonly example: "A####";
readonly stixTypes: readonly ["x-mitre-asset"];
};
readonly 'data-source': {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Data Source ID format (DS####)";
readonly example: "DS####";
readonly stixTypes: readonly ["x-mitre-data-source"];
};
readonly campaign: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Campaign ID format (C####)";
readonly example: "C####";
readonly stixTypes: readonly ["campaign"];
};
readonly 'data-component': {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Data Component Source ID format (DC####)";
readonly example: "DC####";
readonly stixTypes: readonly ["x-mitre-data-component"];
};
readonly 'detection-strategy': {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Detection Strategy Source ID format (DET####)";
readonly example: "DET####";
readonly stixTypes: readonly ["x-mitre-detection-strategy"];
};
readonly analytic: {
readonly pattern: RegExp;
readonly message: "Must match ATT&CK Analytic Source ID format (AN####)";
readonly example: "AN####";
readonly stixTypes: readonly ["x-mitre-analytic"];
};
};
/**
* Union type of all valid ATT&CK ID type keys.
*
* @example
* ```typescript
* const idType: AttackIdType = 'technique'; // Valid
* const idType: AttackIdType = 'tactic'; // Valid
* const idType: AttackIdType = 'invalid'; // Type error
* ```
*/
type AttackIdType = keyof typeof attackIdConfig;
/**
* Union type of all STIX types that have associated ATT&CK IDs.
*
* This extracts only the STIX types that appear in the attackIdConfig mapping,
* excluding STIX types that don't have ATT&CK IDs (e.g., marking-definition, identity, etc.).
*
* @example
* ```typescript
* const stixType: StixTypesWithAttackIds = 'attack-pattern'; // Valid
* const stixType: StixTypesWithAttackIds = 'x-mitre-tactic'; // Valid
* const stixType: StixTypesWithAttackIds = 'marking-definition'; // Type error - no ATT&CK ID
* ```
*/
type StixTypesWithAttackIds = Extract<StixType, (typeof attackIdConfig)[AttackIdType]['stixTypes'][number]>;
/**
* Reverse mapping from STIX type to ATT&CK ID type.
*
* This allows looking up which ATT&CK ID format corresponds to a given STIX type.
* Note that 'attack-pattern' defaults to 'technique', but subtechniques are handled
* contextually where needed.
*
* @example
* ```typescript
* stixTypeToAttackIdMapping['x-mitre-tactic']; // 'tactic'
* stixTypeToAttackIdMapping['malware']; // 'software'
* stixTypeToAttackIdMapping['attack-pattern']; // 'technique'
* ```
*/
declare const stixTypeToAttackIdMapping: Record<StixTypesWithAttackIds, AttackIdType>;
/**
* Map of ATT&CK ID types to their respective RegEx patterns.
*
* Maps `AttackIdType` instead of `StixType` because not all STIX types have ATT&CK ID patterns.
* For example, `marking-definition`, `identity`, `relationship`, `bundle`, and `collection`
* do not have ATT&CK ID patterns.
*
* @example
* ```typescript
* attackIdPatterns.technique; // /^T\d{4}$/
* attackIdPatterns.tactic; // /^TA\d{4}$/
* attackIdPatterns.subtechnique; // /^T\d{4}\.\d{3}$/
* ```
*/
declare const attackIdPatterns: Record<AttackIdType, RegExp>;
/**
* Map of ATT&CK ID types to their validation error messages.
*
* Used for providing helpful error messages when ATT&CK ID validation fails.
*
* @example
* ```typescript
* attackIdMessages.technique; // 'Must match ATT&CK Technique ID format (T####)'
* attackIdMessages.group; // 'Must match ATT&CK Group ID format (G####)'
* ```
*/
declare const attackIdMessages: Record<AttackIdType, string>;
/**
* Map of ATT&CK ID types to their format examples.
*
* Provides example formats for documentation and error messages.
*
* @example
* ```typescript
* attackIdExamples.technique; // 'T####'
* attackIdExamples.subtechnique; // 'T####.###'
* attackIdExamples['data-source']; // 'DS####'
* ```
*/
declare const attackIdExamples: Record<AttackIdType, string>;
/**
* Gets the ATT&CK ID format example for a given STIX type.
*
* Provides special handling for 'attack-pattern' which can be either a technique
* or a subtechnique, returning both possible formats.
*
* @param stixType - The STIX type to get the ATT&CK ID example for
* @returns The format example string (e.g., 'T####' or 'T#### or T####.###')
*
* @example
* ```typescript
* getAttackIdExample('x-mitre-tactic'); // 'TA####'
* getAttackIdExample('attack-pattern'); // 'T#### or T####.###'
* getAttackIdExample('malware'); // 'S####'
* ```
*/
declare function getAttackIdExample(stixType: StixTypesWithAttackIds): string;
/**
* Creates a Zod schema for validating ATT&CK IDs based on STIX type.
*
* This factory function generates a Zod string schema that validates ATT&CK IDs
* according to the format required for the given STIX type. Special handling is
* provided for 'attack-pattern' which accepts both technique and subtechnique formats.
*
* @param stixType - The STIX type that determines which ATT&CK ID format to validate
* @returns A Zod string schema configured for the appropriate ATT&CK ID format
*
* @example
* ```typescript
* const tacticIdSchema = createAttackIdSchema('x-mitre-tactic');
* tacticIdSchema.parse('TA0001'); // Valid - returns 'TA0001'
* tacticIdSchema.parse('T0001'); // Invalid - throws error
*
* const techniqueIdSchema = createAttackIdSchema('attack-pattern');
* techniqueIdSchema.parse('T1234'); // Valid - technique format
* techniqueIdSchema.parse('T1234.001'); // Valid - subtechnique format
* techniqueIdSchema.parse('TA0001'); // Invalid - wrong format
* ```
*/
declare const createAttackIdSchema: (stixType: StixTypesWithAttackIds) => z.ZodString;
/**
* Creates a type-specific schema for validating old mobile ATT&CK IDs (`x_mitre_old_attack_id`).
*
* This factory function generates schemas that validate old mobile ATT&CK IDs based on
* the STIX type. Software types (malware, tool) use MOB-S####, while mitigations
* (course-of-action) use MOB-M####.
*
* @param stixType - The STIX type to create the schema for (malware, tool, or course-of-action)
* @returns A Zod schema configured for the appropriate old ATT&CK ID format
*
* @example
* ```typescript
* const softwareOldIdSchema = createOldMitreAttackIdSchema('malware');
* softwareOldIdSchema.parse("MOB-S0012"); // Valid
* softwareOldIdSchema.parse("MOB-M1008"); // Invalid - wrong prefix for software
*
* const mitigationOldIdSchema = createOldMitreAttackIdSchema('course-of-action');
* mitigationOldIdSchema.parse("MOB-M1008"); // Valid
* ```
*/
declare function createOldMitreAttackIdSchema(stixType: Extract<StixType, 'malware' | 'tool' | 'course-of-action'>): z.ZodString & z.ZodType<`MOB-M${number}` | `MOB-S${number}`, string, z.core.$ZodTypeInternals<`MOB-M${number}` | `MOB-S${number}`, string>>;
/**
* Generic schema for validating old mobile ATT&CK IDs (`x_mitre_old_attack_id`).
*
* Validates IDs in the format MOB-X#### where X is either 'M' or 'S', followed by
* exactly four digits. For type-specific validation, use `createOldMitreAttackIdSchema()`.
*
* @example
* ```typescript
* xMitreOldAttackIdSchema.parse("MOB-M1008"); // Valid
* xMitreOldAttackIdSchema.parse("MOB-S0012"); // Valid
* xMitreOldAttackIdSchema.parse("MOB-T1234"); // Invalid - wrong prefix
* ```
*/
declare const xMitreOldAttackIdSchema: z.ZodString & z.ZodType<`MOB-M${number}` | `MOB-S${number}`, string, z.core.$ZodTypeInternals<`MOB-M${number}` | `MOB-S${number}`, string>>;
/**
* Type representing a validated old mobile ATT&CK ID.
*/
type XMitreOldAttackId = z.infer<typeof xMitreOldAttackIdSchema>;
export { type AttackIdType, type StixTypesWithAttackIds, type XMitreOldAttackId, attackIdExamples, attackIdMessages, attackIdPatterns, createAttackIdSchema, createOldMitreAttackIdSchema, getAttackIdExample, stixTypeToAttackIdMapping, xMitreOldAttackIdSchema };