Version: 2.9.0
Scope: Documents the current inline JavaScript implementation inindex.htmland companionconfig.js+stix-config.js(plus embedded iframe IPC surface used byexplorer.htmlandstix-builder.html).
Purpose: Definitive implementation reference for ongoing hardening and v3 modularization planning.
- Architecture Overview
- File Map
- What Changed Since v2.7.0
- config.js — Configuration & Theme Engine
- stix-config.js — STIX 2.1 Object Definitions
- Inline JS Sections (index.html)
- 6.1 VERSION + INPUT SECURITY
- 6.2 METADATA + TYPE MAPPING + ASSIGNMENT/GROUP LOGIC
- 6.3 STATE + PHASE MODEL + CORE HELPERS
- 6.4 DATA LOADING (SHARED CACHE + OFFLINE MODE)
- 6.5 LOCAL IFRAME IPC BRIDGE
- 6.6 NAVIGATOR / TECHNIQUE IMPORTS
- 6.7 VIEWS + THEME + COMPACT + COMMENTS
- 6.8 GLOBAL SEARCH + TAB/FILTER CONTROLS
- 6.9 ENTITY LIST, STIX LIBRARY, STIX EDITOR
- 6.10 DETAIL VIEWS, DND, KILL CHAIN, RELATIONSHIPS
- 6.11 PHASE DETAILS MODAL + STATS
- 6.12 EXPORT / IMPORT (JSON, CSV, STIX)
- 6.13 METADATA EDITOR + MODALS + INIT
- Data Types & Shapes
- Security Model
- Global Event Listeners
- Module Mapping (Current → v3.0)
AttackFlow is a zero-build browser SPA with all core runtime logic inside inline JavaScript in index.html.
- No bundler, no module system, global-scope runtime.
- Mutable app state lives in a single
stateobject. - Rendering is template-string +
innerHTMLdriven, protected by strict sanitization and validator guards. - Companion scripts:
config.js(theme/config/import behavior/debug toggles)stix-config.js(STIX SDO schemas + vocabularies + helpers)
- Embedded views:
explorer.htmlstix-builder.html
- Local
file://mode supports a hardened MessageChannel-based iframe bridge and shared-data broadcast path.
| File | Role |
|---|---|
index.html |
Main UI, CSS, and inline runtime (monolith, ~10.5k lines total) |
config.js |
App config, theme presets, feature flags, IPC debug/rate/bootstrap tuning |
stix-config.js |
STIX common fields, vocabularies, 19 SDO type definitions, helper APIs |
explorer.html |
Relationship Explorer iframe view |
stix-builder.html |
STIX Composer iframe view (theme + local IPC aware) |
resources/*.json |
Generated runtime datasets (ATT&CK/CAPEC/CWE + mappings + Navigator layers) |
Major additions reflected in v2.9.0 runtime:
- Local iframe IPC hardening
- Channel-only bootstrap (
AF_IPC_PORT_INIT) with per-frame nonce binding. - Allowlisted message types and payload keys.
- Request rate-limiting (token bucket) and bounded bootstrap retry/backoff.
- Channel-only bootstrap (
- Shared dataset runtime cache
window.getAttackFlowSharedData()snapshot API with deep-frozen payload.- Dataset shape + count + byte-size enforcement before cross-frame sharing.
- Offline
file://data path- Local folder/file selector flow for required
resources/*.jsonfiles. - Graceful bypass path if user continues without data.
- Local folder/file selector flow for required
- Prototype pollution defenses expanded
DANGEROUS_OBJECT_KEYS, safe reviver parsing (parseJsonSafe), null-prototype object creation.
- UI/runtime features
- Global search subsystem with ranking and sticky/expanded modes.
- Kill-chain comment visibility controls (
showComments, toggles). - Rich phase details modal with averages/CVE rollups/mitigation aggregation.
- Optional STIX Builder navigation toggle (
CONFIG.navigation.showStixBuilder).
- STIX export evolution
- Deterministic UUIDv5 IDs for ATT&CK techniques and mitigations in STIX bundle export.
version: '2.9.0'sources.attack.version: '18.1'imports.clearStixOnBundleImport,imports.clearStixOnKillChainImportnavigation.confirmOnLeave,navigation.showStixBuildervisualizer.enabledConfigIframeIPC.enableLocalIframeIPCdebugging.traceLocalIframeIPCLogsdebugging.localIframeIPCRateLimit.{enabled,refillPerSecond,burst}debugging.localIframeIPCBootstrap.{timeoutMs,maxRetries,retryBaseDelayMs,retryBackoffMultiplier,maxRetryDelayMs,graceMs}
resolveTheme(mode?, scheme?)- Merges scheme overrides into configured defaults (
phases,frameworks,ui,metaIcons).
- Merges scheme overrides into configured defaults (
applyConfigColors(theme?)- Applies resolved colors to CSS custom properties on
document.documentElement.
- Applies resolved colors to CSS custom properties on
STIX_COMMON_PROPERTIESSTIX_VOCABULARIESSTIX_OBJECTS(19 SDO types)STIX_RELATIONSHIP_DEFAULTS
getStixFieldsForType(stixType)getStixTypeKeys()getStixTypeLabel(stixType)getStixVocabulary(vocabKey)
- Field descriptor model is used dynamically by the inline STIX editor.
- Supported field kinds include primitive, list/open-vocab, timestamp/identifier, and complex JSON-backed structures (
kill-chain-phases,external-references,dictionary).
APP_VERSIONinitialized fallback, updated byloadVersion()fromCHANGELOG.md.InputSecurityobject provides:- output encoding (
escapeHtml,sanitizeAttr) - normalization/sanitize helpers
- validators (CVE/CVSS/hash/IP/domain/url/filename)
validateObservable(type, value)dispatch
- output encoding (
- Input guard stack (
applyInputGuards) covers:keydown,beforeinput,paste,drop,input
- Added sanitizer primitives:
normalizeUserInput(text, maxLength, allowNewlines)sanitizeUserInputText(text, allowNewlines)sanitizeForStorage(text, maxLength)
- Prototype pollution defenses:
DANGEROUS_OBJECT_KEYSisDangerousObjectKey,createSafeObject,hasOwn,parseJsonSafe- recursive loader sanitizer
stripAngleBracketsFromJson
- Metadata normalization now handles
cveEntries, legacycveId/cveIds, and optionalcvespayloads. - Confidence buckets changed to:
- labels:
Unknown / Low / Medium / High - classes:
unknown / low / medium / high
- labels:
- Assignment instance IDs now use
itm-...format (createAssignmentInstanceId). - Type constants:
TYPE_KEYS,TAG_CLASSES,TYPE_LABELS,ALL_ENTITY_TYPESSTIX_ID_PATTERN,VALID_STIX_TYPES
- STIX ID helpers:
generateUUID,generateStixId- deterministic UUIDv5 stack:
uuidv5,sha1Bytes,mitigationStixId,techniqueStixId
- Group/assignment utilities:
ensurePhaseLayout,extractAssignmentInstance,moveGroupBetweenPhases,findAssignment,updateAssignmentMetadata
state now includes:
showCommentsrelationshipExpanded: Set- global search flags:
globalSearch,globalSearchOpen,globalSearchExpanded,globalSearchSticky
Kill chain model updates:
- IN super-phase uses
resource-development(not weaponization). - IN command phase key is
command-control. KILL_CHAINtotals remain 18 phases.
Title/description helpers:
commitKillChainTitle,syncTitleToDOMcommitKillChainDescription,syncDescriptionToDOMtoggleDescriptionPanel,updateDescriptionHint,updateDescriptionCounter
Core datasets are centralized via SHARED_DATA_ENDPOINTS and loadSharedLibraryData(forceReload?).
Key APIs:
getSharedDataCache()fetchJsonResource(resourcePath)promptOfflineResourceFiles(requiredFileNames)enableOfflineResourceSelectionUI(message)hideLoadingOverlay()window.getAttackFlowSharedData(options)
Behavior:
- HTTP context: standard
fetchpath. file://context: local file selection and cloned JSON store.- shared dataset validated for schema + limits before reuse/broadcast.
IPC constants and constraints:
- inbound request types:
AF_REQUEST_THEME,AF_REQUEST_SHARED_DATA - bootstrap type:
AF_IPC_PORT_INIT - response types:
AF_THEME_SYNC,AF_SHARED_DATA - allowlisted payload keys and per-frame nonce checks
Main bridge functions:
- enable/trace/config:
isLocalIframeIPCEnabled,isLocalIframeIPCTraceEnabledgetLocalIframeIPCRateLimitConfig,getLocalIframeIPCBootstrapConfig
- channel management:
createLocalIPCNonce,setupIPCChannelForFrame,clearIPCFrameChannelscheduleIPCChannelBootstrapRetry,sendIPCMessageViaChannel
- data safety:
buildImmutableSharedDataPayload,validateSharedDatasetShapeenforceSharedDatasetLimits,estimateJsonByteSize,deepFreeze
- broadcasting:
broadcastThemeToEmbeddedViewsbroadcastSharedDataToExplorerinitEmbeddedMessageBridge
IMPORT_LIMITS(25MB max, max techniques, strict ATT&CK ID regex)- Manual list and CSV-like quick import path:
parseTechniqueIdInput,applyTechniqueList,submitCsvImport- modal helpers
openCsvImportModal,closeCsvImportModal
- Navigator file import:
importNavigator(event)with schema/ID validation- base-library restoration helpers:
ensureBaseTechniquesLoaded,resetAttackTechniques
- View switching supports:
killchain,relationship,explorer,stix-builder - STIX Builder visibility is config-gated via
isStixBuilderEnabled+applyNavigationConfig. - Theme runtime:
getPreferredThemeMode,normalizeThemeMode,normalizeThemeSchemeapplyTheme,updateThemeControls,toggleThemeMode,initThemeControls,syncThemeFromStorage
- Compact/runtime controls:
setCompactMode,toggleCompactMode,toggleHideEmpty,applyCompactLayout
- Comment controls:
updateCommentsControls,toggleItemComment,toggleAllComments
Global search subsystem:
setGlobalSearch,openGlobalSearch,closeGlobalSearchtoggleGlobalSearchExpanded,setGlobalSearchSticky,updateGlobalSearchUI,initGlobalSearch- ranking and results:
rankGlobalEntity,buildGlobalSearchResults,renderGlobalSearchResultsopenGlobalSearchResult,matchesGlobalSearch
Tab/filter helpers:
switchTab(tab)setFilter(type, filter)parseCommaIdList(raw, pattern, prefix)
Entity listing:
filterEntities(type)now integrates local search + global search + ID-list parsing.isEntityAssigned(type, id)scans grouped and ungrouped phase allocations.
STIX bundle import/library:
STIX_BUNDLE_IMPORT_LIMITSimportStixBundle(event)sanitizeStixBundleObject(obj, stixType, stixId)clearStixLibrary()
STIX create/edit flows:
populateStixTypeDropdown,toggleCustomTypeNameopenCreateCustomModal,closeCreateCustomModal,createCustomItem,deleteCustomItem- editor modal:
openStixEditor,closeStixEditor,saveStixEditor- field builders:
buildStixReadonlyField,buildStixTextField,buildStixTextareaField,buildStixFieldFromSpec
Detail and explorer integration:
renderDescriptionWithBadgesconverts ATT&CK markdown links to explorer badges.selectEntity,buildEntityDetail,buildStixPropertySummary,buildMetadataSummaryopenEntityModal,closeEntityModal,showDetail,closeDetailopenMitigationExplorer,openEntityExplorer
DND:
dragDatatracks source/type/instance/group context.handleDragStart,handleDragEnd,handleDragOver,handleDragLeave,handleDrophandleAssignmentDragStart,handleGroupDragStart,handleGroupDrop
Kill chain renderer:
renderKillChainusesphaseData.layoutfor stable ordering.renderEntityTagincludes score + metadata icon cluster + optional inline comments panel.
Relationship renderer:
renderRelationshipViewbuilds CAPEC↔CWE↔ATT&CK↔Phase↔Mitigation rows.expandRelationshipMitigations(chainId)supports incremental expansion.
Phase details pipeline:
buildPhaseDetails(phaseKey)getPhaseItemRelationships(type, id)getPhaseAverages(itemsByType)buildPhaseCveEntries(itemsByType)buildPhaseMitigations(itemsByType)- rendering helpers:
renderPhaseMitigationSectionrenderPhaseCveSectionrenderPhaseDetailsSection
- modal controls:
openPhaseDetails(phaseKey)closePhaseDetails(event)
Stats and utility:
renderStatstogglePhaseremoveAssignmentexpandAll,collapseAll,clearAssignments
Export:
exportJSON()emitskillchain-export-lite+ embeddedstixBundlewhen present.buildSTIXBundle()now includes:- custom SDOs
- deterministic ATT&CK
attack-patternSDOs - deterministic mitigation
course-of-actionSDOs - generated
relationshipSROs (mitigates+ co-location relations)
addRelationship(...)exportSTIXBundle()exportCSV()with formula-injection hardening (sanitizeForCsvprefix guard)
Import:
KILLCHAIN_IMPORT_LIMITSvalidateKillChainImport(data)sanitizeImportedString,sanitizeAssignmentMetadatasanitizeImportedAssignment,sanitizeImportedCustomAssignmentsanitizeImportedData(data)ensureAssignmentShape,ensureLibraryFallbacksimportKillChain(event)
Metadata editor:
openMetadataEditor,closeMetadataEditorselectScore,updateConfidenceLabeladdCveRow,addHyperlinkRow,addObservableRowsaveMetadata()validates CVE/CVSS/URL/observable formats before update
Modals + app shell:
- usage/changelog:
showUsageGuide,closeUsageGuide,showChangelog,closeChangelog - dropdown helpers:
toggleDropdown,closeDropdowns showToast,renderAll,enableLeaveSiteConfirmation
Initialization order:
initThemeControls()logLocalIframeIPCSplash('index')updateLoadingContextInfo()- storage listener for theme sync
- leave-site confirmation (config-gated)
initEmbeddedMessageBridge()applyNavigationConfig()initAssignments()initCompactMode()- resize listener for compact layout
applyInputGuards()initGlobalSearch()populateStixTypeDropdown()loadVersion()loadData()
{
id: 'T1566',
metadata: Metadata,
instanceId: 'itm-lk5u0h-12'
}{
score: 'unclassified', // unclassified|low|medium|high|critical
confidence: null, // null or 1..100
comments: '',
cveEntries: [{ id, score, vector }],
cveId: '',
cveIds: [],
hyperlinks: [{ label, url }],
observables: [{ type, value }]
}{
techniques: Assignment[],
capecs: Assignment[],
cwes: Assignment[],
customItems: Assignment[],
groups: Group[],
layout: LayoutEntry[]
}{
groupId: 'grp-lk5u0h-abc12',
label: 'Initial Access',
collapsed: false,
items: GroupItem[]
}
// GroupItem = Assignment + type
{ id, metadata, instanceId, type: 'attack'|'capec'|'cwe'|'custom' }
// Layout entries
{ kind: 'item', type: 'attack', instanceId: 'itm-...' }
{ kind: 'group', groupId: 'grp-...' }{
attack: { [techId]: Technique },
capecPatterns: { [capecId]: Capec },
cweWeaknesses: { [cweId]: Cwe },
techniqueToCapec: { [techId]: string[] },
capecToTechnique: { [capecId]: string[] },
cweToCapec: { [cweId]: string[] }
}{
version: '2.9.0',
schema: 'killchain-export-lite',
exportedAt: 'ISO-8601',
title: '',
description: '',
view: 'killchain'|'relationship'|'explorer'|'stix-builder',
activeTab: 'attack'|'capec'|'cwe'|'custom',
filters: { attack, capec, cwe, custom },
layers: { attack, capec, cwe, custom },
hideEmpty: boolean,
assignments: { [phaseKey]: PhaseData },
selection: { type, id },
customLibrary: { [stixId]: StixLibraryEntry },
stixBundle?: StixBundle
}Defense-in-depth implementation in v2.9.0:
- Input blocking + normalization on all text-entry paths.
- Output encoding before template insertion (
esc,escAttr, entity encoding). - Safe JSON parsing using reviver to strip
__proto__/constructor/prototype. - Null-prototype object construction for untrusted accumulator objects.
- Import validation + limit enforcement (file size/count/shape/ID formats).
- IPC allowlisting + nonce checks + channel-only messaging + throttling.
- Shared payload immutability via deep clone + deep freeze before iframe handoff.
- URL protocol allowlist (
http/https) for rendered external links. - CSV formula injection prevention by prefixing risky leading characters.
Primary listeners include:
window.storage(theme sync)window.beforeunload(optional leave confirmation)window.message(channel bootstrap guard)window.resize(compact layout)document.click(dropdown close + global search close)document.keydown(escape handling + input guard)document.beforeinput/paste/drop/input(input hardening)- iframe
loadhandlers for explorer and STIX builder channel setup
Suggested split of current monolith:
af-security.js- InputSecurity validators/sanitizers, parse-safe JSON, import sanitizer helpers.
af-core.js- State model, phase model, assignment/group helpers, metadata helpers.
af-data.js- Shared-data loader/cache, offline file-mode loader, dataset limit enforcement.
af-ipc.js- Local iframe bridge, channel bootstrap, nonce/rate-limit logic, broadcast helpers.
af-ui.js- Rendering pipelines (killchain/relationships/details), DnD, global search, modals.
af-io.js- JSON/CSV/STIX export+import, schema migration and sanitization.
For a comprehensive, maintainable function inventory (grouped by file and subsystem), see:
docs/FUNCTION_INDEX.mddocs/FUNCTION_INDEX.generated.md(auto-generated inventory)
This index is intentionally line-agnostic to reduce churn while remaining onboarding-friendly for maintainers.
Refresh generated index with:
python3 scripts/generate-function-index.pyGenerated for AttackFlow v2.9.0 from current workspace sources (index.html, config.js, stix-config.js, docs/IPC_API-DOCS.md).