🆕 New Features
Analyst Workflow
- Threat ranking & volume control — New
ThreatRanker module: composite score
(severity 40% + confidence 30% + VOC risk signals 30%), configurable max threat
count and minimum STRIDE category coverage. Guarantees at least one threat per
STRIDE category is always preserved.
- Accepted risks management —
accepted_risks.yaml auto-discovered next to the
model file. Two matching modes: stable TK- content-hash key or pattern-based
(STRIDE category + target + description wildcard). Expired entries automatically
ignored. Accepted threats are dimmed in the HTML report with decision badge
(ACCEPTED / FALSE POSITIVE / MITIGATED) and rationale inline.
- CI/CD gate mode — New
--gate REPORT_JSON flag: exits 1 when unaccepted
threats meet or exceed --fail-on severity (default: CRITICAL). --baseline
mode restricts failures to new threats only — ideal for PR gates.
- ATT&CK ID validation —
AttackIdValidator checks every MITRE technique ID
in the threat list against the local STIX corpus; detects hallucinated, revoked,
and deprecated IDs. Fully offline, silently disabled when the corpus is absent.
AI & Reporting
- CISO triage AI pass — After threat ranking, an optional LLM call generates
an executive risk briefing: posture score, colour-coded label, top findings,
quick-wins table, and narrative. Cached on threat_model._ciso_triage and
included in JSON export.
- Interactive threat graph — Force-directed Canvas visualization in the HTML
report: nodes (actors/servers) sized by threat count and coloured by severity,
edges carrying protocol/encryption/auth flags, hover tooltips, severity filter.
Zero JS dependencies, fully offline.
- SOC Analyst persona + context compression — Threat prompts now include a
SOC analyst persona with context compression for more operationally relevant
output. Terraform plugin extended: security group ingress/egress rules preserved,
internet_facing, credentials_stored, and traversal_difficulty inferred
from tfstate; BOM files generated automatically per resource.
- Batch LLM enrichment — Components grouped into configurable batches
(batch_size=5, max_concurrent=3); batches run concurrently under
asyncio.Semaphore. For 20 components: ~20 serial calls → ~4 concurrent
round-trips. Redundant check_connection() calls eliminated; uses cached
ai_online flag instead.
Editor & DSL
- Custom asset types (community YAML) — 22 asset types and 17 protocols
migrated from hardcoded Python dicts to config/asset_types_community.yaml
and config/protocols_community.yaml. Community-editable without code changes.
- Component Panel (DSL helper) — Schema-driven slide-in panel in the editor:
Add/Edit modes, boundary/node dropdowns, dark-mode compatible.
- DSL autocomplete + autosave — Context-aware completion in the Monaco editor;
draft autosaved to localStorage with restore banner on next open.
- Executive View + Copy-as-ticket — Toggle in HTML report for management
presentations; one-click copy of top-5 threats as GitHub Issue markdown.
- Sub-model drill-down — Server nodes become hyperlinks to child model
diagrams; child diagrams render ghost clusters for external connections.
Infrastructure & Distribution
- Docker image — Multi-stage build:
secopstm:latest (core, ~slim) and
secopstm:ai (full AI stack with vector store volume). Available on Docker Hub.
- PyPI packaging —
pip install secopstm (TestPyPI → PyPI). pip install "secopstm[ai]" for full AI/RAG dependencies.
secopstm init-rag — Downloads the pre-built RAG vector store (~1.3 GB)
from GitHub Releases into ~/.secopstm/vector_store/. Override with
SECOPSTM_VECTOR_STORE_DIR.
secopstm download-data — Downloads and verifies external_data.tar.gz
from GitHub Releases (SHA-256 checked).
analysis in CI workflows.
New Threat Model Templates
- Kubernetes/Helm Cluster — 14 servers, 8 boundaries, 22 dataflows, 78 pytm
threats, full GDAF context YAML.
- AWS Lambda Event-Driven — 21 servers, 8 boundaries, 23 dataflows, 106 pytm
threats, full GDAF context YAML.
⚡ Performance
- RAG initialisation parallelised with AI connection check (
run_in_executor) —
saves ~26 s on cold start when RAG is enabled.
- LangChain removed from RAG pipeline — direct ChromaDB + LiteLLM calls reduce
cold-import time by ~300 s.
- CVEService pre-warmed in a daemon thread at server startup.
🐛 Bug Fixes
- GDAF not triggered in
--model-file CLI mode (fixed path resolution).
- GDAF context not loaded when using server-managed projects.
- Sub-model tab navigation matched by filename instead of full path.
- Custom MITRE DSL parsing:
[\s=:]+ regex fix (value no longer included =).
credentialsLife integer crash: hardened to fallback Lifetime.NONE + warning.
CONFIDENTIAL/INTERNAL classification aliases added to classification map.
- RAG crash on non-dict items in LLM response (guard + per-item try/except).
- AI threats absent from global project report (cached in
_report_all_detailed_threats, preferred by global report generator).
config.js permissions in Docker image (chown to appuser).
- lxml bumped 6.0.0 → 6.1.0.
📦 Installation
# Core (offline threat modeling, no AI)
pip install secopstm
# Full AI stack (RAG, LLM enrichment)
pip install "secopstm[ai]"
secopstm init-rag # download pre-built vector store (~1.3 GB)
# Docker
docker pull ellipse2v/secopstm:latest # core
docker pull ellipse2v/secopstm:ai # full AI stack
⬆️ Upgrading from 1.1.0
No breaking DSL changes. Run secopstm init-rag --force to refresh the vector
store if you use RAG features.