Skip to content

Multi round debat#35

Merged
ellipse2v merged 8 commits into
mainfrom
multiRoundDebat
Jul 14, 2026
Merged

Multi round debat#35
ellipse2v merged 8 commits into
mainfrom
multiRoundDebat

Conversation

@ellipse2v

Copy link
Copy Markdown
Owner
  • Add RedBlueDebateEngine: multi-round Red (attack) vs Blue (defence) LLM
    debate over the top-N GDAF attack scenarios, adjusting path_score/risk_level
    in place and surfacing a new HTML report section. Opt-in via
    config/ai_config.yaml (debate.enabled: false by default), degrades
    silently when AI is offline or no GDAF scenarios exist.
  • Gate the Graphical Editor behind a new --graphical-editor CLI flag,
    disabled by default. The /graphical route and its API now 404 and the
    menu link is hidden unless explicitly enabled.
  • Rename the DSL title convention from "# Threat Model: {Name}" to
    "# System Model: {Name}" across docs, prompts, and generated content —
    the DSL describes the system; SecOpsTM generates the threat model from
    it. The legacy tag is still parsed with a deprecation warning
    (get_model_name). Migrate all 30 threatModel_Template/*.md files to the
    new tag.
  • Fix two broken "Maintenance" badge URLs and the stale version string in
    README.md / CLAUDE.md.

ellipse2v added 8 commits July 7, 2026 23:06
…m-model vs threat-model terminology

 - Add RedBlueDebateEngine: multi-round Red (attack) vs Blue (defence) LLM
    debate over the top-N GDAF attack scenarios, adjusting path_score/risk_level
    in place and surfacing a new HTML report section. Opt-in via
    config/ai_config.yaml (debate.enabled: false by default), degrades
    silently when AI is offline or no GDAF scenarios exist.
  - Gate the Graphical Editor behind a new --graphical-editor CLI flag,
    disabled by default. The /graphical route and its API now 404 and the
    menu link is hidden unless explicitly enabled.
  - Rename the DSL title convention from "# Threat Model: {Name}" to
    "# System Model: {Name}" across docs, prompts, and generated content —
    the DSL describes the system; SecOpsTM generates the threat model from
    it. The legacy tag is still parsed with a deprecation warning
    (get_model_name). Migrate all 30 threatModel_Template/*.md files to the
    new tag.
  - Fix two broken "Maintenance" badge URLs and the stale version string in
    README.md / CLAUDE.md.
test blue / red debate
 Root cause across most of these: several report sections and export formats
   were computed from a stale or wrong data source instead of the final
   AI-enriched, debate-aware threat list, or read config keys that were never
   actually wired to any code.

   AI enrichment pipeline
   - ReportGenerator now delegates to AIService._enrich_with_ai_threats()
     instead of its own thinner duplicate. This restores the per-component
     AIThreatCache (previously never invoked, so every run re-queried the LLM)
     and the SOC analysis pass (previously always empty in the HTML report).
   - threat_generation.confidence_threshold and max_threats_per_component,
     previously unread, now filter/cap AI-generated threats per component.
   - rag.top_k_examples, previously unread, now controls RAG retrieval k.
   - CLI --project mode now builds and passes an AIService to
     generate_project_reports(), so cross-model RAG threat generation runs in
     CLI mode too (previously web-UI only).

   Post-debate consistency (GDAF)
   - .afb Attack Flow files are re-written after the Red/Blue debate mutates
     scenario scores, instead of staying frozen at pre-debate values.
   - Threat IDs (T-0001 style) are assigned before CISO triage/threat-graph/
     debate run, so all of them reference the same IDs as the final report
     instead of the LLM inventing its own scheme.
   - CISO triage and the interactive threat graph now run after the debate and
     can reference GDAF scenarios and debate outcomes (new "Automatically
     Discovered Attack Paths" section mirrors this for the GDAF-independent
     AttackFlowGenerator).
   - JSON/STIX/Navigator/AttackFlowGenerator exports reuse the AI-enriched
     threat list cached by generate_html_report() via a new get_enriched_threats()
     helper, instead of recomputing a pytm-only list.

   Other correctness fixes
   - Severity multipliers (## Severity Multipliers DSL section) are now synced
     from the parsed model instead of read from the bundled example template —
     previously affected CLI single-file runs and the entire server/web UI.
   - MitreMapping no longer dumps the full ~150-entry STRIDE-category CAPEC
     bucket onto every threat lacking explicit capec_ids; ranks by description
     keyword overlap and caps at 10.
   - Diagram severity heat map (export_service.py) is now computed after AI
     enrichment instead of before, so it can reflect AI-derived severities.

   Cleanup
   - Removed _expand_class_targets(), dead since process_threats() switched to
     tm.findings; corrected architecture.md/decisions.md which still documented
     it as active.
   - Removed dead ai_config.yaml keys (attack_flows.format/max_depth/
     include_detection_points, threat_generation.include_attack_flows) that had
     no implementation; wired attack_flows.enabled/generate_for_categories into
     AttackFlowGenerator instead.

   Regression tests added throughout for every behavior change.
…ion, concurrency)

  - ai_service.py: skip system-level RAG below rag.min_components (default 3) —
    tiny models mostly got restated single-component threats instead of genuine
    cross-boundary chaining; applies to both live enrichment and project-mode
    cross-model RAG.
  - attack_id_validator.py: extend AttackIdValidator to also validate
    capecs[].capec_id and defend_mitigations[].id against the committed CAPEC
    catalog CSV and d3fend.csv, not just ATT&CK technique IDs — LLM-cited CAPEC
    IDs were previously only format-checked ("CAPEC-" prefix), never verified
    against real data before appearing in a report with a stable T-000N ID or
    in STIX export. CWE intentionally excluded: the pipeline never reads the
    LLM's raw cwe_ids field, so there's nothing to ground-truth.
  - diagram_generator.py: replace hardcoded /tmp/graphviz_error.log with
    tempfile.mkstemp() — avoids concurrent requests clobbering each other's
    log and symlink-attack risk on a shared host.
  - diagram_generator.py / svg_generator.py: replace bare `except:` (which
    swallows KeyboardInterrupt) with `except Exception` + logging.
  - server.py: move initial_model_file_path/initial_project_path from
    process-wide globals to Flask session state (threaded=True means two
    concurrent tabs/users could otherwise redirect each other's exports to the
    wrong model); log and continue instead of silently dropping SSE queue
    push failures; warn at startup when binding to a non-loopback host, since
    no route has authentication.
  - README.md / DOCKER_HUB.md: default `docker run` examples to
    `-p 127.0.0.1:5000:5000` with a short security note, since the Docker
    image sets FLASK_HOST=0.0.0.0 by default.
  - data_loader.py: add load_capec_catalog_ids(), parsing the full CAPEC ID
    set from the committed CSV.
  - Tests: cover all of the above (RAG threshold, CAPEC/D3FEND validation,
    tempfile log path, except-clause logging, session isolation, startup
    warning) plus new coverage for previously-untested core/model_factory.py,
    core/stride_constants.py, and generation/tactic_logic.py.

  Full suite: 1417 passed.
  Adds a short, grounded narrative and business-impact summary to each automatically discovered attack path in the HTML report.

  Context: AttackFlowGenerator.get_paths_summary() finds the best (highest-severity) attack path per STRIDE category by following each threat's MITRE ATT&CK tactic progression
  through the architecture — pure graph traversal over the fully consolidated threat list (pytm + AI + LLM sources), no GDAF context required, capped at one path per STRIDE category
  (≤6 total).

  What's new: each of those paths now gets a short narrative explaining how an attacker would realistically move through it, plus a business-impact paragraph — generated by a
  dedicated LLM persona (attack_path_narrative in config/prompts.yaml), rendered as an expandable row under the path in the "Automatically Discovered Attack Paths" report section.

  Hallucination guard (two layers):
  1. Minimal attack surface — the prompt only gives the model technique names (e.g. "Exploit Public-Facing Application"), never IDs. Nothing to copy incorrectly.
  2. Code-level rejection, not just a prompt instruction — _narrative_has_id_leakage() regex-scans the response for anything shaped like an ATT&CK (T####), CVE, CAPEC, or D3FEND ID.
  A single match discards the entire response — fail closed, no partial trust, since one fabricated ID means the rest of the prose can't be trusted either.

  Config: attack_flows.include_narrative in ai_config.yaml (default true) — skips silently when AI is offline or disabled.

  Docs updated: README (AI Roles table), decisions.md (design rationale — reject-on-any-match vs. corpus validation, why no top_n gate needed), architecture.md (new pipeline section
  5d), docs/features.md.

  Tests: 24 new tests in tests/test_attack_path_narrative.py (regex unit tests, gating, grounding-violation rejection on both narrative and business_impact, multi-path handling,
  non-fatal provider errors) + 1 in test_attack_flow_generator.py. Full suite: 1438 passed.
update report template
add groq and xai provider
fix pytm version
@ellipse2v
ellipse2v merged commit 94ff6d6 into main Jul 14, 2026
1 check passed
@ellipse2v
ellipse2v deleted the multiRoundDebat branch July 14, 2026 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant