UNPKG

@mitre-attack/attack-data-model

Version:

A TypeScript API for the MITRE ATT&CK data model

1,227 lines (1,189 loc) 130 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; 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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/main.ts var main_exports = {}; __export(main_exports, { loadDataModel: () => loadDataModel, registerDataSource: () => registerDataSource }); module.exports = __toCommonJS(main_exports); var import_axios = __toESM(require("axios"), 1); var import_uuid = require("uuid"); // src/schemas/sdo/stix-bundle.schema.ts var import_v434 = require("zod/v4"); // src/refinements/index.ts var import_v433 = require("zod/v4"); // src/schemas/common/attack-core.ts var import_v414 = 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-attribution.ts var import_v43 = require("zod/v4"); // src/schemas/common/property-schemas/stix-id.ts var import_v42 = require("zod/v4"); // src/schemas/common/property-schemas/stix-type.ts var import_v4 = require("zod/v4"); var stixTypeToTypeName = { "attack-pattern": "Technique", bundle: "StixBundle", campaign: "Campaign", "course-of-action": "Mitigation", "extension-definition": null, identity: "Identity", "intrusion-set": "Group", malware: "Malware", tool: "Tool", "marking-definition": "MarkingDefinition", "x-mitre-analytic": "Analytic", "x-mitre-data-component": "DataComponent", "x-mitre-detection-strategy": "DetectionStrategy", "x-mitre-data-source": "DataSource", "x-mitre-tactic": "Tactic", "x-mitre-asset": "Asset", "x-mitre-matrix": "Matrix", "x-mitre-collection": "Collection", relationship: "Relationship", file: "", // not used in ATT&CK but used in sample_refs for Malware artifact: "" // not used in ATT&CK but used in sample_refs for Malware // 'observed-data': 'ObservedData', // not used in ATT&CK // 'report': 'Report', // not used in ATT&CK // 'threat-actor': 'ThreatActor', // not used in ATT&CK // 'vulnerability': 'Vulnerability', // not used in ATT&CK }; var supportedStixTypes = [ "attack-pattern", "bundle", "campaign", "course-of-action", "extension-definition", "identity", "intrusion-set", "malware", "tool", "marking-definition", "x-mitre-analytic", "x-mitre-data-component", "x-mitre-detection-strategy", "x-mitre-tactic", "x-mitre-asset", "x-mitre-data-source", "x-mitre-matrix", "x-mitre-collection", "relationship", "file", // not used in ATT&CK but used in sample_refs for Malware "artifact" // not used in ATT&CK but used in sample_refs for Malware // "indicator", // not used in ATT&CK // "observed-data", // not used in ATT&CK // "report", // not used in ATT&CK // "threat-actor", // not used in ATT&CK // "vulnerability", // not used in ATT&CK ]; var stixTypeSchema = import_v4.z.enum(supportedStixTypes, { error: (issue) => { if (issue.code === "invalid_value") { const received = typeof issue.input === "string" ? issue.input : String(issue.input); return `Invalid STIX type '${received}'. Expected one of the supported STIX types.`; } return void 0; } }).meta({ description: "The type property identifies the type of STIX Object (SDO, Relationship Object, etc). The value of the type field MUST be one of the types defined by a STIX Object (e.g., indicator)." }); function createStixTypeValidator(stixType) { const objectName = stixTypeToTypeName[stixType]; return import_v4.z.literal(stixType).refine((val) => val === stixType, { error: (issue) => `Invalid 'type' property. Expected '${stixType}' for ${objectName} object, but received '${issue.input}'.` }); } function createMultiStixTypeValidator(stixTypes) { const objectNames = stixTypes.map((type) => stixTypeToTypeName[type]).join(" or "); const typeList = stixTypes.map((t) => `'${t}'`).join(" or "); const literals = stixTypes.map((type) => import_v4.z.literal(type)); return import_v4.z.union(literals).refine((val) => stixTypes.includes(val), { error: (issue) => `Invalid 'type' property. Expected ${typeList} for ${objectNames} object, but received '${issue.input}'.` }); } // src/schemas/common/property-schemas/stix-id.ts var stixIdentifierSchema = import_v42.z.string().refine((val) => val.includes("--") && val.split("--").length === 2, { error: (issue) => ({ code: "custom", message: "Invalid STIX Identifier: must comply with format 'type--UUIDv4'", input: issue.input, path: [] }) }).refine( (val) => { const [type] = val.split("--"); return stixTypeSchema.safeParse(type).success; }, { error: (issue) => { const val = issue.input; const [type] = val.split("--"); const typeName = type in stixTypeToTypeName ? stixTypeToTypeName[type] : "STIX"; return { code: "custom", message: `Invalid STIX Identifier for ${typeName} object: contains invalid STIX type '${type}'`, input: issue.input, path: [] }; } } ).refine( (val) => { const [, uuid] = val.split("--"); return import_v42.z.uuid().safeParse(uuid).success; }, { error: (issue) => { const val = issue.input; const [type] = val.split("--"); const typeName = type in stixTypeToTypeName ? stixTypeToTypeName[type] : "STIX"; return { code: "custom", message: `Invalid STIX Identifier for ${typeName} object: contains invalid UUIDv4 format`, input: issue.input, path: [] }; } } ).meta({ description: "Represents identifiers across the CTI specifications. The format consists of the name of the top-level object being identified, followed by two dashes (--), followed by a UUIDv4." }); function createStixIdValidator(expectedType) { return stixIdentifierSchema.refine( (val) => val.startsWith(`${expectedType}--`), { error: () => ({ code: "custom", message: `Invalid STIX Identifier: must start with '${expectedType}--'`, input: expectedType, path: [] }) } ); } // src/schemas/common/property-schemas/attack-attribution.ts var xMitreIdentity = "identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5"; var xMitreIdentitySchema = import_v43.z.literal(xMitreIdentity).meta({ description: "STIX Identity for The MITRE Corporation" }); var xMitreModifiedByRefSchema = xMitreIdentitySchema.meta({ description: "The STIX ID of the MITRE identity object. Used to track the identity of the MITRE organization, which created the current version of the object. Previous versions of the object may have been created by other individuals or organizations." }); var xMitreContributorsSchema = stixListOfString.meta({ description: "People and organizations who have contributed to the object. Not found on objects of type `relationship`." }); // src/schemas/common/property-schemas/attack-domains.ts var import_v44 = require("zod/v4"); var attackDomainSchema = import_v44.z.enum(["enterprise-attack", "mobile-attack", "ics-attack"]).meta({ description: "ATT&CK is organized in a series of \u201Ctechnology domains\u201D - the ecosystem an adversary operates within that provides a set of constraints the adversary must circumvent or take advantage of to accomplish a set of objectives. To date MITRE has defined three technology domains." }); var xMitreDomainsSchema = import_v44.z.array(attackDomainSchema).min(1, { message: "At least one MITRE ATT&CK domain must be specified." }).meta({ description: "The technology domains to which the ATT&CK object belongs." }); // src/schemas/common/property-schemas/attack-id.ts var import_v45 = require("zod/v4"); 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 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" }); // src/schemas/common/property-schemas/attack-platforms.ts var import_zod2 = require("zod"); var supportedMitrePlatforms = [ "Field Controller/RTU/PLC/IED", "Network Devices", "Data Historian", "Google Workspace", "Office Suite", "ESXi", "Identity Provider", "Containers", "Azure AD", "Engineering Workstation", "Control Server", "Human-Machine Interface", "Windows", "Linux", "IaaS", "None", "iOS", "PRE", "SaaS", "Input/Output Server", "macOS", "Android", "Safety Instrumented System/Protection Relay", "Embedded" ]; var xMitrePlatformSchema = import_zod2.z.enum(supportedMitrePlatforms, { error: () => `Platform must be one of: ${supportedMitrePlatforms.join(", ")}` }).meta({ description: "A technology environments and/or operating system that ATT&CK techniques are applicable within." }); var xMitrePlatformsSchema = import_zod2.z.array(xMitrePlatformSchema, { error: (issue) => issue.code === "invalid_type" ? "x_mitre_platforms must be an array of strings" : "Invalid platforms array" }).min(1, "At least one platform is required").refine((items) => new Set(items).size === items.length, { message: "Platforms must be unique (no duplicates allowed)." }).meta({ description: "List of platforms that apply to the object." }); // src/schemas/common/property-schemas/attack-statuses.ts var import_zod3 = require("zod"); var xMitreDeprecatedSchema = import_zod3.z.boolean({ error: "x_mitre_deprecated must be a boolean." }).meta({ description: "Indicates whether the object has been deprecated." }); // src/schemas/common/property-schemas/attack-versioning.ts var import_v46 = require("zod/v4"); var xMitreVersionSchema = nonEmptyRequiredString.regex(/^(\d{1,2})\.(\d{1,2})$/, "Version must be in format 'M.N' where M and N are 0-99").meta({ description: "Represents the version of the object in a 'major.minor' format, where both 'major' and 'minor' are integers between 0 and 99. This versioning follows semantic versioning principles but excludes the patch number. The version number is incremented by ATT&CK when the content of the object is updated. This property does not apply to relationship objects." }); var semverRegex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/; var xMitreAttackSpecVersionSchema = nonEmptyRequiredString.regex(semverRegex, "Must be valid semantic version (MAJOR.MINOR.PATCH)").meta({ description: "The version of the ATT&CK spec used by the object. This field helps consuming software determine if the data format is supported. If the field is not present on an object, the spec version will be assumed to be 2.0.0. Refer to the ATT&CK CHANGELOG for all supported versions." }); // src/schemas/common/property-schemas/stix-attribution.ts var import_v47 = require("zod/v4"); var objectMarkingRefsSchema = import_v47.z.array( stixIdentifierSchema.startsWith( "marking-definition--", 'Identifier must start with "marking-definition--"' ) ).meta({ description: "The list of marking-definition objects to be applied to this object." }); var stixCreatedByRefSchema = createStixIdValidator("identity").meta({ description: "The created_by_ref property specifies the id property of the identity object that describes the entity that created this object. If this attribute is omitted, the source of this information is undefined. This may be used by object creators who wish to remain anonymous." }); // src/schemas/common/property-schemas/stix-common-properties.ts var import_v48 = require("zod/v4"); var descriptionSchema = nonEmptyRequiredString.meta({ description: "A description of the object." }); var nameSchema = nonEmptyRequiredString.meta({ description: "The name of the object." }); var aliasesSchema = stixListOfString.meta({ description: "Alternative names used to identify this object. The first alias must match the object's name." }); // src/schemas/common/property-schemas/stix-extensions.ts var import_v410 = require("zod/v4"); // src/schemas/common/property-schemas/stix-external-references.ts var import_zod4 = __toESM(require("zod"), 1); var externalReferenceSchema = import_zod4.default.object({ source_name: nonEmptyRequiredString, description: nonEmptyRequiredString.optional(), url: import_zod4.default.url({ error: (issue) => issue.input === null ? "URL cannot be null" : "Invalid URL format. Please provide a valid URL" }).optional(), external_id: nonEmptyRequiredString.optional() }); var externalReferencesSchema = import_zod4.default.array(externalReferenceSchema).min(1).meta({ description: "A list of external references which refers to non-STIX information" }); var createAttackExternalReferencesSchema = (stixType) => { return import_zod4.default.array(externalReferenceSchema).min(1, "At least one external reference is required").refine((refs) => !!refs[0]?.external_id, { message: "ATT&CK ID must be defined in the first external_references entry.", path: [0, "external_id"] }).refine( (refs) => { if (!refs[0]?.external_id) return true; const attackIdType = stixTypeToAttackIdMapping[stixType]; if (attackIdType === "technique") { return attackIdPatterns["technique"].test(refs[0].external_id) || attackIdPatterns["subtechnique"].test(refs[0].external_id); } return attackIdPatterns[attackIdType].test(refs[0].external_id); }, { message: `The first external_reference must match the ATT&CK ID format ${getAttackIdExample(stixType)}.`, path: [0, "external_id"] } ).meta({ description: "A list of external references with the first containing a valid ATT&CK ID" }); }; // src/schemas/common/property-schemas/stix-granular-marking.ts var import_zod5 = require("zod"); var granularMarkingSchema = import_zod5.z.object({ lang: nonEmptyRequiredString.optional().meta({ description: "The lang property identifies the language of the text identified by this marking. The value of the lang property, if present, MUST be an [RFC5646] language code. If the marking_ref property is not present, this property MUST be present. If the marking_ref property is present, this property MUST NOT be present." }), marking_ref: stixIdentifierSchema.optional().meta({ description: "The marking_ref property specifies the ID of the marking-definition object that describes the marking. If the lang property is not present, this property MUST be present. If the lang property is present, this property MUST NOT be present." }), selectors: stixListOfString.meta({ description: "The selectors property specifies a list of selectors for content contained within the STIX Object in which this property appears." }) }).check((ctx) => { const { lang, marking_ref } = ctx.value; const hasLang = lang !== void 0; const hasMarkingRef = marking_ref !== void 0; if (hasLang && hasMarkingRef) { ctx.issues.push({ path: ["lang"], message: "If the marking_ref property is present, the lang property MUST NOT be present.", code: "custom", input: { lang: ctx.value.lang, marking_ref: ctx.value.marking_ref } }); ctx.issues.push({ path: ["marking_ref"], message: "If the lang property is present, the marking_ref property MUST NOT be present.", code: "custom", input: { lang: ctx.value.lang, marking_ref: ctx.value.marking_ref } }); } else if (!hasLang && !hasMarkingRef) { ctx.issues.push({ path: ["lang"], message: "If the marking_ref property is not present, the lang property MUST be present.", code: "custom", input: { lang: ctx.value.lang, marking_ref: ctx.value.marking_ref } }); ctx.issues.push({ path: ["marking_ref"], message: "If the lang property is not present, the marking_ref property MUST be present.", code: "custom", input: { lang: ctx.value.lang, marking_ref: ctx.value.marking_ref } }); } }).meta({ description: "The `granular-marking` type defines how the `marking-definition` object referenced by the **marking_ref** property or a language specified by the **lang** property applies to a set of content identified by the list of selectors in the selectors property." }); // src/schemas/common/property-schemas/stix-versioning.ts var import_v49 = require("zod/v4"); var specVersionDescription = [ "The version of the STIX specification used to represent this object.", "The value of this property MUST be 2.1 for STIX Objects defined according to this specification.", "If objects are found where this property is not present, the implicit value for all STIX Objects other than SCOs is 2.0.", "Since SCOs are now top-level objects in STIX 2.1, the default value for SCOs is 2.1." ].join(" "); var stixSpecVersionSchema = import_v49.z.literal("2.1").meta({ description: specVersionDescription }); // src/schemas/common/property-schemas/stix-extensions.ts var extensionTypeSchema = import_v410.z.enum([ "new-sdo", "new-sco", "new-sro", "property-extension", "toplevel-property-extension" ]); var extensionSchema = import_v410.z.object({ extension_type: extensionTypeSchema // Additional properties depend on extension type - using record for flexibility }).catchall(import_v410.z.unknown()); var extensionsSchema = import_v410.z.record( nonEmptyRequiredString, import_v410.z.union([extensionSchema, import_v410.z.record(nonEmptyRequiredString, import_v410.z.unknown())]) ).meta({ description: "Specifies any extensions of the object, as a dictionary where keys are extension definition UUIDs" }); var extensionPropertyNameSchema = import_v410.z.string().trim().min(3, "Extension property names must be at least 3 characters").max(250, "Extension property names must be no longer than 250 characters").regex( /^[a-z0-9_]+$/, "Extension property names must only contain lowercase letters, digits, and underscores" ); var extensionObjectTypeSchema = import_v410.z.string().trim().min(3, "Extension object type must be at least 3 characters").max(250, "Extension object type must be no longer than 250 characters").regex( /^[a-z0-9-]+$/, "Extension object type must only contain lowercase letters, digits, and hyphens" ).refine( (value) => !value.includes("--"), "Extension object type must not contain consecutive hyphens" ); var extensionDefinitionSchema = import_v410.z.object({ // Required common properties id: createStixIdValidator("extension-definition"), type: createStixTypeValidator("extension-definition"), spec_version: stixSpecVersionSchema, created: import_v410.z.iso.datetime(), modified: import_v410.z.iso.datetime(), created_by_ref: stixCreatedByRefSchema, // Optional common properties revoked: import_v410.z.boolean().optional(), labels: stixListOfString.optional(), external_references: externalReferencesSchema.optional(), object_marking_refs: objectMarkingRefsSchema.optional(), granular_markings: import_v410.z.array(granularMarkingSchema).optional(), // Extension definition specific properties name: nameSchema, description: nonEmptyRequiredString.optional(), schema: nonEmptyRequiredString, version: nonEmptyRequiredString.regex( /^\d+\.\d+\.\d+$/, "Version must follow semantic versioning (MAJOR.MINOR.PATCH)" ), extension_types: import_v410.z.array(extensionTypeSchema).min(1, "At least one extension type is required"), extension_properties: import_v410.z.array(extensionPropertyNameSchema).optional() }).strict().refine( (data) => { if (data.extension_types.includes("toplevel-property-extension")) { return data.extension_properties && data.extension_properties.length > 0; } return true; }, { message: "extension_properties must be provided when extension_types includes toplevel-property-extension" } ).meta({ description: "Extension Definition object allows producers to extend existing STIX objects or create new STIX objects" }); // src/schemas/common/property-schemas/stix-kill-chains.ts var import_zod6 = require("zod"); var killChainNameSchema = import_zod6.z.enum([ "mitre-attack", "mitre-mobile-attack", "mitre-ics-attack" ]); var killChainPhaseSchema = import_zod6.z.object({ phase_name: nonEmptyRequiredString.refine( (value) => { const isLowercase = value === value.toLowerCase(); const usesHyphens = !value.includes(" ") && !value.includes("_"); return isLowercase && usesHyphens; }, { message: "Phase name should be all lowercase and use hyphens instead of spaces or underscores." } ).meta({ description: "The name of the phase in the kill chain. The value of this property SHOULD be all lowercase and SHOULD use hyphens instead of spaces or underscores as word separators." }), kill_chain_name: killChainNameSchema }).strict(); // src/schemas/common/property-schemas/stix-open-vocabulary.ts var import_v411 = require("zod/v4"); var MalwareTypeOV = import_v411.z.enum([ "adware", "backdoor", "bot", "bootkit", "ddos", "downloader", "dropper", "exploit-kit", "keylogger", "ransomware", "remote-access-trojan", "resource-exploitation", "rogue-security-software", "rootkit", "screen-capture", "spyware", "trojan", "virus", "webshell", "wiper", "worm", "unknown" ]); var ProcessorArchitectureOV = import_v411.z.enum([ "alpha", "arm", "ia-64", "mips", "powerpc", "sparc", "x86", "x86-64" ]); var ImplementationLanguageOV = import_v411.z.enum([ "applescript", "bash", "c", "c++", "c#", "go", "java", "javascript", "lua", "objective-c", "perl", "php", "powershell", "python", "ruby", "scala", "swift", "typescript", "visual-basic", "x86-32", "x86-64" ]); var MalwareCapabilityOV = import_v411.z.enum([ "accesses-remote-machines", "anti-debugging", "anti-disassembly", "anti-emulation", "anti-memory-forensics", "anti-sandbox", "anti-vm", "captures-input-peripherals", "captures-output-peripherals", "captures-system-state-data", "cleans-traces-of-infection", "commits-fraud", "communicates-with-c2", "compromises-data-integrity", "compromises-data-availability", "compromises-system-availability", "controls-local-machine", "degrades-security-software", "degrades-system-updates", "determines-c2-server", "emails-spam", "escalates-privileges", "evades-av", "exfiltrates-data", "fingerprints-host", "hides-artifacts", "hides-executing-code", "infects-files", "infects-remote-machines", "installs-other-components", "persists-after-system-reboot", "prevents-artifact-access", "prevents-artifact-deletion", "probes-network-environment", "self-modifies", "steals-authentication-credentials", "violates-system-operational-integrity" ]); var ToolTypeOV = import_v411.z.enum([ "denial-of-service", "exploitation", "information-gathering", "network-capture", "credential-exploitation", "remote-access", "vulnerability-scanning", "unknown" ]); var IdentityClassOV = import_v411.z.enum([ "individual", "group", "system", "organization", "class", "unspecified" ]); var AttackMotivationOV = import_v411.z.enum([ "accidental", "coercion", "dominance", "ideology", "notoriety", "organizational-gain", "personal-gain", "personal-satisfaction", "revenge", "unpredictable" ]); var AttackResourceLevelOV = import_v411.z.enum([ "individual", "club", "contest", "team", "organization", "government" ]); var IndustrySectorOV = import_v411.z.enum([ "agriculture", "aerospace", "automotive", "chemical", "commercial", "communications", "construction", "defense", "education", "energy", "entertainment", "financial-services", "government", "government-emergency-services", "government-local", "government-national", "government-public-services", "government-regional", "healthcare", "hospitality-leisure", "infrastructure", "infrastructure-dams", "infrastructure-nuclear", "infrastructure-water", "insurance", "manufacturing", "mining", "non-profit", "pharmaceuticals", "retail", "technology", "telecommunications", "transportation", "utilities" ]); var MitreCollectionLayerOV = import_v411.z.enum([ "Cloud Control Plane", "Host", "Report", "Container", "Device", "OSINT", "Network" ]); var PatternTypeOV = import_v411.z.enum(["spl", "stix", "pcre", "sigma", "snort", "suricata", "yara"]).meta({ description: "This is a non-exhaustive, open vocabulary that covers common pattern languages and is intended to characterize the pattern language that the indicator pattern is expressed in." }); var IndicatorTypeOV = import_v411.z.enum([ "anomalous-activity", "anonymization", "benign", "compromised", "malicious-activity", "attribution", "unknown" ]).meta({ description: "Indicator type is an open vocabulary used to categorize Indicators. It is intended to be high-level to promote consistent practices. Indicator types should not be used to capture information that can be better captured via related Malware or Attack Pattern objects. It is better to link an Indicator to a Malware object describing Poison Ivy rather than simply providing a type or label of 'poison-ivy.'" }); // src/schemas/common/property-schemas/stix-timestamp.ts var import_v412 = require("zod/v4"); var stixTimestampSchema = import_v412.z.iso.datetime({ error: "Invalid STIX timestamp format: must be an RFC3339 timestamp with a timezone specification of 'Z'." }).refine((val) => val.endsWith("Z"), { message: "STIX timestamps must use 'Z' timezone specification" }).meta({ description: "Represents timestamps across the CTI specifications. The format is an RFC3339 timestamp, with a required timezone specification of 'Z'." }); var stixCreatedTimestampSchema = stixTimestampSchema; var stixModifiedTimestampSchema = stixTimestampSchema; // src/schemas/common/stix-core.ts var import_v413 = require("zod/v4"); var stixBaseObjectSchema = import_v413.z.object({ id: stixIdentifierSchema.meta({ description: "The id property universally and uniquely identifies this object." }), type: stixTypeSchema, spec_version: stixSpecVersionSchema.meta({ description: "The version of the STIX specification used to represent this object." }), created: stixCreatedTimestampSchema.meta({ description: "The created property represents the time at which the first version of this object was created. The timstamp value MUST be precise to the nearest millisecond." }), modified: stixModifiedTimestampSchema.meta({ description: "The modified property represents the time that this particular version of the object was modified. The timstamp value MUST be precise to the nearest millisecond." }), created_by_ref: stixCreatedByRefSchema.optional(), labels: stixListOfString.optional().meta({ description: "The labels property specifies a set of terms used to meta this object." }), revoked: import_v413.z.boolean().optional().meta({ description: "The revoked property indicates whether the object has been revoked." }), confidence: import_v413.z.number().int().min(1).max(99).optional().refine((val) => val === void 0 || val > 0 && val < 100, { message: "Confidence must be between 1 and 99 inclusive." }).optional().meta({ description: "Identifies the confidence that the creator has in the correctness of their data." }), lang: nonEmptyRequiredString.optional().meta({ description: "Identifies the language of the text content in this object." }), external_references: externalReferencesSchema.optional(), object_marking_refs: objectMarkingRefsSchema.optional(), granular_markings: import_v413.z.array(granularMarkingSchema).optional().meta({ description: "The set of granular markings that apply to this object." }), extensions: extensionsSchema.optional() }).strict(); var stixDomainObjectSchema = stixBaseObjectSchema.extend({}); var stixRelationshipObjectSchema = stixBaseObjectSchema.extend({}); // src/schemas/common/attack-core.ts var attackBaseObjectSchema = stixDomainObjectSchema.extend({ name: nameSchema, /** * Required on all ATT&CK schemas except: * - Marking Definition */ x_mitre_attack_spec_version: xMitreAttackSpecVersionSchema, /** * Required on all ATT&CK schemas except: * - Marking Definition * - Identity * - Relationship */ x_mitre_version: xMitreVersionSchema, x_mitre_old_attack_id: xMitreOldAttackIdSchema.optional(), x_mitre_deprecated: xMitreDeprecatedSchema.optional() }); var attackBaseDomainObjectSchema = attackBaseObjectSchema.extend({}); var attackBaseRelationshipObjectSchema = attackBaseObjectSchema.extend({}); var attackBaseMetaObjectSchema = attackBaseObjectSchema.extend({}).omit({ modified: true }); // src/schemas/sdo/analytic.schema.ts var import_v415 = require("zod/v4"); var xMitreLogSourceReferenceSchema = import_v415.z.object({ x_mitre_data_component_ref: createStixIdValidator("x-mitre-data-component"), name: nonEmptyRequiredString.meta({ description: "Log source name from the associated data component's `x_mitre_log_sources` array" }), channel: nonEmptyRequiredString.meta({ description: "Log source channel from the data component's `x_mitre_log_sources` array" }) }).meta({ description: "The `log_source_reference` object links analytics to specific data components with log source details" }); var xMitreLogSourceReferencesSchema = import_v415.z.array(xMitreLogSourceReferenceSchema).min(1).check((ctx) => { validateNoDuplicates( [], ["x_mitre_data_component_ref", "name", "channel"], "Duplicate log source reference found: each (x_mitre_data_component_ref, name, channel) tuple must be unique" )(ctx); }).meta({ description: "A list of log source references, which are delineated by a Data Component STIX ID and the (`name`, `channel`) that is being targeted." }); var xMitreMutableElementSchema = import_v415.z.object({ field: nonEmptyRequiredString.meta({ description: "Name of the detection field that can be tuned" }), description: nonEmptyRequiredString.meta({ description: "Rationale for tunability and environment-specific considerations" }) }).meta({ description: "The `mutable_element` object defines tunable parameters within analytics" }); var xMitreMutableElementsSchema = import_v415.z.array(xMitreMutableElementSchema).min(1).meta({ description: "Environment-specific tuning knobs like TimeWindow, UserContext, or PortRange, so defenders can adapt without changing core behavior." }); var analyticSchema = attackBaseDomainObjectSchema.extend({ id: createStixIdValidator("x-mitre-analytic"), type: createStixTypeValidator("x-mitre-analytic"), description: descriptionSchema, x_mitre_platforms: xMitrePlatformsSchema.max(1).meta({ description: "Target platform for this Analytic." }), // 0 or 1 external_references: createAttackExternalReferencesSchema("x-mitre-analytic"), x_mitre_log_source_references: xMitreLogSourceReferencesSchema.optional(), x_mitre_mutable_elements: xMitreMutableElementsSchema.optional(), x_mitre_domains: xMitreDomainsSchema, x_mitre_modified_by_ref: xMitreModifiedByRefSchema.optional() }).required({ created_by_ref: true, object_marking_refs: true }).strict().meta({ description: ` Analytics contain platform-specific detection logic and represent the implementation details of a detection strategy. They are defined as \`x-mitre-analytic\` objects extending the generic [STIX Domain Object pattern](https://docs.oasis-open.org/cti/stix/v2.0/csprd01/part2-stix-objects/stix-v2.0-csprd01-part2-stix-objects.html#_Toc476230920). `.trim() }); // src/schemas/sdo/asset.schema.ts var import_v416 = require("zod/v4"); var supportedAssetSectors = [ "Electric", "Water and Wastewater", "Manufacturing", "Rail", "Maritime", "General" ]; var xMitreSectorsSchema = import_v416.z.array( import_v416.z.enum(supportedAssetSectors, { error: () => `Sector must be one of: ${supportedAssetSectors.join(", ")}` }), { error: (issue) => issue.code === "invalid_type" ? "related_asset_sectors must be an array" : "Invalid asset sectors array" } ).min(1).meta({ description: "List of industry sector(s) where this asset is commonly observed." }); var relatedAssetSchema = import_v416.z.object({ name: nameSchema.meta({ description: "Sector-specific name or alias for the related asset" }), related_asset_sectors: xMitreSectorsSchema.optional(), description: descriptionSchema.optional().meta({ description: "How the related asset connects to the primary asset definition" }) }).meta({ description: "The `related_asset` object provides sector-specific asset variations and aliases" }); var relatedAssetsSchema = import_v416.z.array(relatedAssetSchema).min(1).meta({ description: "Related assets describe sector specific device names or alias that may be commonly associated with the primary asset page name or functional description. Related asset objects include a description of how the related asset is associated with the page definition" }); var assetSchema = attackBaseDomainObjectSchema.extend({ id: createStixIdValidator("x-mitre-asset"), type: createStixTypeValidator("x-mitre-asset"), description: descriptionSchema.optional(), // Optional in STIX but required in ATT&CK external_references: createAttackExternalReferencesSchema("x-mitre-asset"), x_mitre_platforms: xMitrePlatformsSchema.optional(), x_mitre_domains: xMitreDomainsSchema, x_mitre_contributors: xMitreContributorsSchema.optional(), x_mitre_sectors: xMitreSectorsSchema.optional(), x_mitre_related_assets: relatedAssetsSchema.optional(), x_mitre_modified_by_ref: xMitreModifiedByRefSchema.optional() }).required({ object_marking_refs: true, // Optional in STIX but required in ATT&CK created_by_ref: true // Optional in STIX but required in ATT&CK }).strict().meta({ description: ` Assets represent systems, devices, or technologies that adversaries may target within organizational environments. They are defined as \`x-mitre-asset\` objects extending the generic [STIX Domain Object pattern](https://docs.oasis-open.org/cti/stix/v2.0/csprd01/part2-stix-objects/stix-v2.0-csprd01-part2-stix-objects.html#_Toc476230920). `.trim() }); // src/schemas/sdo/campaign.schema.ts var import_v417 = require("zod/v4"); var baseCitationSchema = import_v417.z.custom( (value) => { if (typeof value !== "string") return false; if (!value.startsWith("(") || !value.endsWith(")")) return false; const content = value.slice(1, -1); const parts = content.split(":"); if (parts.length !== 2) return false; if (parts[0].trim() !== "Citation") return false; if (parts[1].trim() === "") return false; return true; }, { message: "Each citation must conform to the pattern '(Citation: [citation name])'" } ); var multipleCitationsSchema = import_v417.z.custom( (value) => { if (typeof value !== "string") return false; const citations = value.match(/\(Citation:[^)]+\)/g); if (!citations) return false; return citations.join("") === value && citations.every((citation) => baseCitationSchema.safeParse(citation).success); }, { message: "Must be one or more citations in the form '(Citation: [citation name])' without any separators" } ); var xMitreFirstSeenCitationSchema = multipleCitationsSchema.meta({ description: "One or more citations for when the object was first seen, in the form '(Citation: [citation name])(Citation: [citation name])...', where each `[citation name]` can be found as one of the `source_name` values in the `external_references`." }); var xMitreLastSeenCitationSchema = multipleCitationsSchema.meta({ description: "One or more citations for when the object was last seen, in the form '(Citation: [citation name])(Citation: [citation name])...', where each `[citation name]` can be found as one of the `source_name` values in the `external_references`." }); var campaignBaseSchema = attackBaseDomainObjectSchema.extend({ id: createStixIdValidator("campaign"), type: createStixTypeValidator("campaign"), description: descriptionSchema, external_references: createAttackExternalReferencesSchema("campaign"), x_mitre_domains: xMitreDomainsSchema, x_mitre_modified_by_ref: xMitreModifiedByRefSchema, x_mitre_contributors: xMitreContributorsSchema.optional(), aliases: aliasesSchema, // Optional in STIX but required in ATT&CK first_seen: stixTimestampSchema.meta({ description: "The time that this Campaign was first seen." }), // Optional in STIX but required in ATT&CK last_seen: stixTimestampSchema.meta({ description: "The time that this Campaign was last seen." }), x_mitre_first_seen_citation: xMitreFirstSeenCitationSchema, x_mitre_last_seen_citation: xMitreLastSeenCitationSchema }).required({ created_by_ref: true, // Optional in STIX but required in ATT&CK object_marking_refs: true, // Optional in STIX but required in ATT&CK revoked: true // Optional in STIX but required in ATT&CK }).strict().meta({ description: ` Campaigns represent sets of adversary activities occurring over a specific time period with shared characteristics and objectives. They are defined as [campaign](http://docs.oasis-open.org/cti/stix/v2.0/csprd01/part2-stix-objects/stix-v2.0-csprd01-part2-stix-objects.html#_Toc476230925) objects with additional temporal tracking fields. `.trim() }); var campaignChecks = (ctx) => { createFirstAliasRefinement()(ctx); createCitationsRefinement()(ctx); }; var campaignSchema = campaignBaseSchema.check(campaignChecks); var campaignPartialSchema = campaignBaseSchema.partial().check(campaignChecks); // src/schemas/sdo/collection.schema.ts var import_v418 = require("zod/v4"); var objectVersionReferenceSchema = import_v418.z.object({ object_ref: stixIdentifierSchema.meta({ description: "The ID of the referenced object." }), object_modified: stixModifiedTimestampSchema.meta({ description: "The modified time of the referenced object. It MUST be an exact match for the modified time of the STIX object being referenced." }) }); var xMitreContentsSchema = import_v418.z.array(objectVersionReferenceSchema).min(1, "At least one STIX object reference is required.").meta({ description: "Specifies the objects contained within the collection." }); var collectionSchema = attackBaseDomainObjectSchema.extend({ id: createStixIdValidator("x-mitre-collection"), type: createStixTypeValidator("x-mitre-collection"), // Optional in STIX but required in ATT&CK created_by_ref: stixCreatedByRefSchema, // Optional in STIX but required in ATT&CK object_marking_refs: objectMarkingRefsSchema, description: descriptionSchema.meta({ description: "Details, context, and explanation about the purpose or contents of the collection." }), x_mitre_contents: xMitreContentsSchema.min(1, "At least one STIX object reference is required"), x_mitre_modified_by_ref: xMitreModifiedByRefSchema.optional() }).strict().meta({ description: ` See our [collections document](https://github.com/center-for-threat-informed-defense/attack-workbench-frontend/blob/main/docs/collections.md) for more information about the design and intention of collection objects. `.trim() }); // src/schemas/sdo/data-component.schema.ts var import_v419 = require("zod/v4"); var xMitreDataSourceRefSchema = createStixIdValidator("x-mitre-data-source").meta({ description: "**DEPRECATED in v3.3.0. Will be removed in v4.0.0.** STIX ID of the data source this component is a part of." }); var xMitreLogSourcesSchema = import_v419.z.array( import_v419.z.object({ name: nonEmptyRequiredString.meta({ description: 'Log source identifier (e.g., "sysmon", "auditd")' }), channel: nonEmptyRequiredString.meta({ description: 'Specific log channel or event type (e.g., "1" for Sysmon Process Creation)' }) }).strict() ).min(1).check((ctx) => { validateNoDuplicates( [], ["name", "channel"], "Duplicate log source found: each (name, channel) pair must be unique" )(ctx); }).meta({ description: ` The \`log_source\` object defines platform-specific collection configurations embedded within data components: **Uniqueness constraints:** - Each \`(name, channel)\` tuple must be unique within a data component's \`x_mitre_log_sources\` array - Log sources are scoped to their containing data component **Example:** A data component for 'Process Creation' might contain log sources for: - Windows: (name: "sysmon", channel: "1") - Linux: (name: "auditd", channel: "SYSCALL") - macOS: (name: "unified_logs", channel: "process") `.trim() }); var dataComponentSchema = attackBaseDomainObjectSchema.extend({ id: createStixIdValidator("x-mitre-data-component"), type: createStixTypeValidator("x-mitre-data-component"), description: descriptionSchema, // Optional in STIX but required in ATT&CK created_by_ref: stixCreatedByRefSchema, // Optional in STIX but required in ATT&CK object_marking_refs: objectMarkingRefsSchema, x_mitre_domains: xMitreDomainsSchema, x_mitre_modified_by_ref: xMitreModifiedByRefSchema, x_mitre_data_source_ref: xMitreDataSourceRefSchema.optional(), // TODO remove in attack spec 4.0.0 / adm release 5.x // TODO change to required in spec release 4.x x_mitre_log_sources: xMitreLogSourcesSchema.optional() }).strict().meta({ description: ` Data components represent specific types of information within a data source that can be used for detection. They are defined as \`x-mitre-data-component\` objects extending the generic [STIX Domain Object pattern](https://docs.oasis-open.org/cti/stix/v2.0/csprd01/part2-stix-objects/stix-v2.0-csprd01-part2-stix-objects.html#_Toc476230920). `.trim() }); // src/schemas/sdo/detection-strategy.schema.ts var import_v420 = require("zod/v4"); var detectionStrategySchema = attackBaseDomainObjectSchema.extend({ id: createStixIdValidator("x-mitre-detection-strategy"), type: createStixTypeValidator("x-mitre-detection-strategy"), external_references: createAttackExternalReferencesSchema("x-mitre-detection-strategy"), x_mitre_modified_by_ref: xMitreModifiedByRefSchema, x_mitre_contributors: xMitreContributorsSchema, x_mitre_analytic_refs: import_v420.z.array(createStixIdValidator("x-mitre-analytic")).nonempty({ error: "At least one analytic ref is required" }).check((ctx) => { validateNoDuplicates( [], [], 'Duplicate reference "{value}" found. Each embedded relationship referenced in x_mitre_analytic_refs must be unique.' )(ctx); }).meta({ description: "Array of STIX IDs referencing `x-mitre-analytic` objects that implement this detection strategy." }), x_mitre_domains: xMitreDomainsSchema }).required({ created_by_ref: true, object_marking_refs: true }).meta({ description: ` Detection strategies define high-level approaches for detecting specific adversary techniques. They serve as containers that organize multiple platform-specific analytics into cohesive detection methodologies. Detection strategies are defined as \`x-mitre-detection-strategy\` objects extending the generic [STIX Domain Object pattern](https://docs.oasis-open.org/cti/stix/v2.0/csprd01/part2-stix-objects/stix-v2.0-csprd01-part2-stix-objects.html#_Toc476230920). `.trim() }); // src/schemas/sdo/group.schema.ts var import_v421 = require("zod/v4"); var groupBaseSchema = attackBaseDomainObjectSchema.extend({ id: createStixIdValidator("intrusion-set"), type: createStixTypeValidator("intrusion-set"), // Not used in ATT&CK Group but defined in STIX description: nonEmptyRequiredString.optional().meta({ description: "A description that provides more details and context about the Intrusion Set, potentially including its purpose and its key characteristics" }), // Optional in STIX but required in ATT&CK external_