diff --git a/src/attack_flow_builder/src/assets/builder.config.ts b/src/attack_flow_builder/src/assets/builder.config.ts index 9ab01e90..d3404ec0 100644 --- a/src/attack_flow_builder/src/assets/builder.config.ts +++ b/src/attack_flow_builder/src/assets/builder.config.ts @@ -612,7 +612,19 @@ const config: AppConfiguration = { } } }, - encryption_algorithm : { type: PropertyType.String }, + encryption_algorithm : { + type: PropertyType.Enum, + options: { + type: PropertyType.List, + form: { type: PropertyType.String }, + value: [ + ["AES-256-GCM", "AES-256-GCM"], + ["ChaCha20-Poly1305", "ChaCha20-Poly1305"], + ["mime-type-indicated", "Mime Type Indicated"], + ] + }, + value: null + }, decryption_key : { type: PropertyType.String }, }, anchor_template: "@__builtin__anchor", diff --git a/src/attack_flow_builder/src/assets/builder.config.validator.ts b/src/attack_flow_builder/src/assets/builder.config.validator.ts index e24d8d80..7f75fad0 100644 --- a/src/attack_flow_builder/src/assets/builder.config.validator.ts +++ b/src/attack_flow_builder/src/assets/builder.config.validator.ts @@ -155,10 +155,49 @@ class AttackFlowValidator extends DiagramValidator { // Validate links switch(node.template.id) { case "artifact": { + const payloadBin = node.props.value.get("payload_bin"); + const url = node.props.value.get("url"); const hashes = node.props.value.get("hashes"); + const mimeType = node.props.value.get("mime_type"); + const decryptionKey = node.props.value.get("decryption_key"); + const encryptionAlg = node.props.value.get("encryption_algorithm") + + const payloadRegex = /^([a-z0-9+/]{4})*([a-z0-9+/]{4}|[a-z0-9+/]{3}=|[a-z0-9+/]{2}==)$/i; + const MIME_Regex = /^(application|audio|font|image|message|model|multipart|text|video)\/[a-zA-Z0-9.+_-]+/; + + // Check regex + if(payloadBin?.isDefined()) { + if(!payloadRegex.test(payloadBin.toString())) { + this.addError(id, "Invalid Payload Bin."); + } + } + if(mimeType?.isDefined()) { + if(!MIME_Regex.test(mimeType.toString())) { + this.addError(id, "Invalid MIME Type."); + } + } + + // Validate Payload Bin, URL, and Hashes + if(payloadBin?.isDefined() && url?.isDefined()) { + this.addError(id, "Artifact must have either have a Payload Bin or URL, not both."); + } + if(url?.isDefined() && !hashes?.isDefined()) { + this.addError(id, "Artifact URL must also have a Hash."); + } + + // Check hashes if(hashes?.isDefined()) { this.validateHash(id, hashes as ListProperty); } + + // Validate encryption and decryption algorithms + if(encryptionAlg?.isDefined()) { + if(encryptionAlg.toRawValue()?.toString() == "mime-type-indicated" && !mimeType?.isDefined()) { + this.addError(id, "For Encryption Algorithm to be 'Mime Type Indicated', the field 'Mime Type' cannot be empty."); + } + } else if(decryptionKey?.isDefined()) { + this.addError(id, "An Artifact with a Decryption Key must also have an Encryption Algorithm."); + } break; } case "email_address": // Additional validation for email addresses @@ -166,7 +205,7 @@ class AttackFlowValidator extends DiagramValidator { this.addError(id, "Invalid email address.") } break; - case "file": + case "file": { const hashes = node.props.value.get("hashes"); const name = node.props.value.get("name"); if(!hashes?.isDefined() && !name?.isDefined()) { @@ -176,6 +215,7 @@ class AttackFlowValidator extends DiagramValidator { this.validateHash(id, hashes as ListProperty); } break; + } case "grouping": if(node.next.length === 0) { this.addError(id, "A Grouping must point to at least one object.");