4-phase defense evolution (Bio-Immune, Adversarial, Ensemble, ATLAS) with ~200 new detection rules across 20 languages. TPR 32.9% → 70.8%, FPR 12.2% → 0.0% New modules: DefenseEnsemble, AtlasTechniqueMapper, EvolutionEngine, ImmuneMemory, FeverResponse, MELONGuard, AdversarialTrainer, DecompositionDetector, IndirectInjectionDetector, OutputPayloadGuard, ToolCallSafetyGuard, AuthContextGuard, ResourceExhaustionDetector, TokenizerDeobfuscation, Binary/Hex decoder, OverDefenseCalibrator
164 lines
5.9 KiB
TypeScript
164 lines
5.9 KiB
TypeScript
import { describe, it, expect, beforeEach } from 'vitest'
|
|
import { ATLASMapper } from '../../../src/compliance/ATLASMapper.js'
|
|
|
|
describe('ATLASMapper', () => {
|
|
let mapper: ATLASMapper
|
|
|
|
beforeEach(() => {
|
|
mapper = new ATLASMapper()
|
|
})
|
|
|
|
describe('mapRule()', () => {
|
|
it('should map prompt-injection rule to AML.T0051', () => {
|
|
const mapping = mapper.mapRule('rule:prompt-injection')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0051')
|
|
expect(mapping!.techniqueName).toContain('Prompt Injection')
|
|
expect(mapping!.tacticName).toBe('Initial Access')
|
|
})
|
|
|
|
it('should map indirect prompt injection to AML.T0051.001', () => {
|
|
const mapping = mapper.mapRule('rule:prompt-injection-indirect')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0051.001')
|
|
})
|
|
|
|
it('should map jailbreak rule to AML.T0054', () => {
|
|
const mapping = mapper.mapRule('rule:jailbreak')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0054')
|
|
expect(mapping!.relatedKillChainPhase).toBe('privilege_escalation')
|
|
})
|
|
|
|
it('should map model-extraction rule to AML.T0024', () => {
|
|
const mapping = mapper.mapRule('rule:model-extraction')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0024')
|
|
})
|
|
|
|
it('should map system-prompt-extraction rule', () => {
|
|
const mapping = mapper.mapRule('rule:system-prompt-extraction')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0051.002')
|
|
expect(mapping!.relatedKillChainPhase).toBe('reconnaissance')
|
|
})
|
|
|
|
it('should map data-poisoning rule to AML.T0020', () => {
|
|
const mapping = mapper.mapRule('rule:data-poisoning')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0020')
|
|
expect(mapping!.relatedKillChainPhase).toBe('persistence')
|
|
})
|
|
|
|
it('should map supply-chain rule to AML.T0010', () => {
|
|
const mapping = mapper.mapRule('rule:supply-chain')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0010')
|
|
})
|
|
|
|
it('should map encoding-evasion rule to AML.T0015', () => {
|
|
const mapping = mapper.mapRule('rule:encoding-evasion')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0015')
|
|
})
|
|
|
|
it('should map tool-abuse rule to AML.T0040', () => {
|
|
const mapping = mapper.mapRule('rule:tool-abuse')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0040')
|
|
expect(mapping!.relatedKillChainPhase).toBe('command_and_control')
|
|
})
|
|
|
|
it('should map data-exfiltration rule to AML.T0025', () => {
|
|
const mapping = mapper.mapRule('rule:data-exfiltration')
|
|
expect(mapping).toBeDefined()
|
|
expect(mapping!.techniqueId).toBe('AML.T0025')
|
|
expect(mapping!.relatedKillChainPhase).toBe('actions_on_objective')
|
|
})
|
|
|
|
it('should return undefined for unknown rule', () => {
|
|
const mapping = mapper.mapRule('rule:nonexistent')
|
|
expect(mapping).toBeUndefined()
|
|
})
|
|
|
|
it('should include mitigation IDs in mappings', () => {
|
|
const mapping = mapper.mapRule('rule:prompt-injection')!
|
|
expect(mapping.mitigationIds.length).toBeGreaterThan(0)
|
|
expect(mapping.mitigationIds[0]).toMatch(/^AML\.M\d+/)
|
|
})
|
|
})
|
|
|
|
describe('getMappedRules()', () => {
|
|
it('should return all mapped rule IDs', () => {
|
|
const rules = mapper.getMappedRules()
|
|
expect(rules.length).toBeGreaterThan(0)
|
|
expect(rules).toContain('rule:prompt-injection')
|
|
expect(rules).toContain('rule:jailbreak')
|
|
expect(rules).toContain('rule:data-exfiltration')
|
|
})
|
|
|
|
it('should return frozen array', () => {
|
|
const rules = mapper.getMappedRules()
|
|
expect(Object.isFrozen(rules)).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('getCoverage()', () => {
|
|
it('should return coverage statistics', () => {
|
|
const coverage = mapper.getCoverage()
|
|
expect(coverage.covered).toBeGreaterThan(0)
|
|
expect(coverage.total).toBe(29)
|
|
expect(coverage.covered).toBeLessThanOrEqual(coverage.total)
|
|
})
|
|
|
|
it('should identify coverage gaps', () => {
|
|
const coverage = mapper.getCoverage()
|
|
expect(coverage.gaps.length).toBeGreaterThan(0)
|
|
// Gaps should be technique IDs not covered
|
|
for (const gap of coverage.gaps) {
|
|
expect(gap).toMatch(/^AML\.T(A)?\d+/)
|
|
}
|
|
})
|
|
|
|
it('should have covered + gaps = total known techniques', () => {
|
|
const coverage = mapper.getCoverage()
|
|
// All techniques are either covered or in gaps
|
|
const allKnownCount = coverage.covered + coverage.gaps.length
|
|
// May not equal total exactly since some rules map to same technique
|
|
expect(allKnownCount).toBeLessThanOrEqual(coverage.total)
|
|
})
|
|
|
|
it('should return frozen result', () => {
|
|
const coverage = mapper.getCoverage()
|
|
expect(Object.isFrozen(coverage)).toBe(true)
|
|
expect(Object.isFrozen(coverage.gaps)).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('getAllMappings()', () => {
|
|
it('should return all ATLAS mappings', () => {
|
|
const mappings = mapper.getAllMappings()
|
|
expect(mappings.length).toBeGreaterThan(0)
|
|
})
|
|
|
|
it('should include required fields in each mapping', () => {
|
|
const mappings = mapper.getAllMappings()
|
|
for (const mapping of mappings) {
|
|
expect(mapping.techniqueId).toBeTruthy()
|
|
expect(mapping.tacticId).toBeTruthy()
|
|
expect(mapping.techniqueName).toBeTruthy()
|
|
expect(mapping.tacticName).toBeTruthy()
|
|
expect(mapping.description).toBeTruthy()
|
|
expect(mapping.relatedKillChainPhase).toBeTruthy()
|
|
expect(Array.isArray(mapping.mitigationIds)).toBe(true)
|
|
expect(Array.isArray(mapping.caseStudyIds)).toBe(true)
|
|
}
|
|
})
|
|
|
|
it('should return frozen array', () => {
|
|
const mappings = mapper.getAllMappings()
|
|
expect(Object.isFrozen(mappings)).toBe(true)
|
|
})
|
|
})
|
|
})
|