[{"data":1,"prerenderedAt":1931},["ShallowReactive",2],{"/de-de/blog/automated-detection-testing-framework":3,"navigation-de-de":1173,"banner-de-de":1609,"footer-de-de":1616,"blog-post-authors-de-de-Evan Baltman":1873,"blog-related-posts-de-de-automated-detection-testing-framework":1889,"blog-share-wrapper-de-de":1911,"next-steps-de-de":1921},{"id":4,"title":5,"authors":6,"body":8,"category":1153,"date":1154,"description":1155,"extension":1156,"externalUrl":1157,"faq":1157,"featured":1158,"heroImage":1159,"meta":1160,"navigation":263,"path":1161,"seo":1162,"slug":1165,"stem":1166,"tags":1167,"template":1171,"updatedDate":1157,"__hash__":1172},"blogPosts/de-de/blog/automated-detection-testing-framework.md","Detection-Tests mit GitLab CI/CD und Duo automatisieren",[7],"Evan Baltman",{"type":9,"value":10,"toc":1144},"minimark",[11,15,18,21,26,29,32,51,54,58,61,64,105,109,112,124,135,141,148,672,676,683,968,982,1003,1016,1024,1028,1035,1044,1060,1063,1072,1104,1108,1115,1118,1122,1131,1140],[12,13,14],"p",{},"Wer das Alerting eines Security Operations Center (SOC) gesund halten will, hat mit dem Tuning von False Positives nur die Hälfte der Arbeit erledigt. Oft übersehen: Kritische Detections, die selten auslösen, können längst kaputt sein, ohne dass es jemandem auffällt.",[12,16,17],{},"Bei GitLab prüft das Signals-Engineering-Team seine Detections, indem es echtes Angreiferverhalten auf eigener Infrastruktur simuliert. So lässt sich validieren, dass die Detections über die gesamte Kette auslösen: von der Log-Quelle über die Ingestion in das SIEM bis hin zum Alert-Routing durch unser System für Security Orchestration, Automation and Response (SOAR). Kommerzielle Werkzeuge für Breach and Attack Simulation (BAS) gehen denselben Weg, sind aber teuer, generisch und nicht auf unseren konkreten Detection-Stack zugeschnitten. Also haben wir ein eigenes, vollständig automatisiertes Framework gebaut: Weekly Attack Testing for Continuous Health, kurz WATCH.",[12,19,20],{},"Dieser Artikel zeigt, warum wir das Framework entwickelt haben, wie es funktioniert und wie es sich in der eigenen Umgebung einsetzen lässt.",[22,23,25],"h2",{"id":24},"eine-lücke-in-der-detection-validierung","Eine Lücke in der Detection-Validierung",[12,27,28],{},"Zwischen Änderungen am Log-Schema, SIEM-Updates und Fehlkonfigurationen in der Pipeline gibt es unzählige Wege, auf denen Detections stillschweigend versagen, und genau einen, auf dem sie wie vorgesehen auslösen. Bei diesem Verhältnis liegt ein Schluss nahe: Man muss alte Detections gezielt auslösen. Damit stellt sich die nächste Frage: Wie löst man Detections überhaupt aus, und wie oft?",[12,30,31],{},"Ein Weg ist der synthetische Ansatz: Logs, die schädliches Verhalten simulieren, wieder in das SIEM einspielen. Anschließend wartet man ab, ob die Detection-Regel den vorgetäuschten Vorfall erkennt und einen Alert auslöst. Dieser Ansatz belegt jedoch nicht, dass die Detection unter realen Bedingungen funktioniert, und er validiert eine der fehleranfälligsten Phasen im Alert-Lebenszyklus nicht: die Log-Ingestion, also den Weg von der Log-Quelle ins SIEM.",[12,33,34,35,41,42,46,47,50],{},"Über unser System ",[36,37,40],"a",{"href":38,"rel":39},"https://about.gitlab.com/de-de/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd/",[],"GitLab Universal Automated Response and Detection (GUARD)"," haben wir bereits geschrieben: Es automatisiert das Erstellen und Ausrollen von Detections über eine Detections-as-Code-Pipeline (DaC), und Alerts werden über unser SOAR geroutet und triagiert. Unsere DaC-Pipelines lösen das Problem, zu validieren, dass eine Detection ",[43,44,45],"em",{},"fehlerfrei ausgerollt werden kann",". Sie beantworten aber nicht die Frage, ob diese Detection auch tatsächlich ",[43,48,49],{},"auslöst",", wenn das Verhalten eintritt, auf das sie zielt.",[12,52,53],{},"WATCH schließt diese Lücke. Es ist die fortlaufende Validierung, die uns die Sicherheit gibt, dass unsere Detections funktionieren.",[22,55,57],{"id":56},"so-funktioniert-watch","So funktioniert WATCH",[12,59,60],{},"Im Grundsatz führt WATCH skriptgesteuerte Angriffssimulationen in unserer Staging-Umgebung aus. Anschließend prüft es, ob die erwarteten Alerts durch den gesamten Security-Monitoring-Stack laufen: durch das SIEM für die Detection-Regeln, durch das SOAR für das Alert-Routing und schließlich in die Dashboards, über die unser Team den Zustand der Detections beobachtet.",[12,62,63],{},"Der Lebenszyklus eines WATCH-Tests sieht so aus:",[65,66,67,75,81,87,93,99],"ol",{},[68,69,70,74],"li",{},[71,72,73],"strong",{},"Planung",": Wöchentlich ermittelt eine geplante GitLab-CI/CD-Pipeline alle aktiven Tests und verteilt sie auf zufällige Zeitfenster über die Woche. Diese Randomisierung ist wichtig. Tests sollen nicht zu vorhersehbaren Zeiten auslösen, weil sich Testaktivität dann zu leicht von echten Bedrohungen unterscheiden ließe und zeitkritische Probleme in unseren Detections verdeckt bleiben könnten.",[68,76,77,80],{},[71,78,79],{},"Vorabmeldung",": Bevor ein Test läuft, meldet WATCH ihn über eine eigene Story \"WATCH Heads Up\" an unser SOAR und registriert dort die Detections, die er auslösen soll. So entstehen nachvollziehbare Datensätze, und das SOAR weiß, was kommt.",[68,82,83,86],{},[71,84,85],{},"Ausführung",": Der Test führt das simulierte Angreiferverhalten aus. Er setzt zum Beispiel das Passwort eines Admin-Kontos zurück oder stellt verdächtige API-Aufrufe gegen die Staging-Umgebung.",[68,88,89,92],{},[71,90,91],{},"Detection",": Das SIEM verarbeitet die Aktivitätslogs aus Staging und löst (hoffentlich) die entsprechenden Detection-Regeln aus.",[68,94,95,98],{},[71,96,97],{},"Korrelation",": Sobald Alerts in unserem SOAR eintreffen, entscheidet eine Prüfung mit der Frage \"Ist das ein WATCH-Test?\", ob ein Alert zu einem registrierten Test gehört. Sie stützt sich auf drei Faktoren: das Zeitfenster zwischen Testlauf und Alert, die Identität des Akteurs (IP oder Benutzername) und die Regel-ID der ausgelösten Detection. Genau das verhindert, dass von WATCH erzeugte Alerts als echte Vorfälle an das SIRT eskaliert werden, während die vollständige Pipeline dennoch validiert wird.",[68,100,101,104],{},[71,102,103],{},"Verifizierung",": Eine nachgelagerte Pipeline-Stage prüft, ob alle erwarteten Detections ausgelöst haben, aktualisiert die Statusmetadaten der Detections und veröffentlicht die neuen Ergebnisse auf unserem GitLab-Pages-Dashboard. Löst eine Detection nicht aus, geht eine Benachrichtigung in den Slack-Kanal unseres Teams.",[22,106,108],{"id":107},"watch-mit-gitlab-cicd-nutzen","WATCH mit GitLab CI/CD nutzen",[12,110,111],{},"WATCH nutzt GitLab CI/CD als Rückgrat der Orchestrierung, über drei Pipeline-Stages hinweg.",[12,113,114,115,118,119,123],{},"Die Stage ",[71,116,117],{},"schedule_pipelines"," läuft wöchentlich und übernimmt die Verteilung der Tests. Sie ermittelt alle aktiven Tests, fasst sie in Gruppen zusammen und legt geplante Pipelines an, die zu zufälligen Zeitpunkten über die Woche laufen. Jede geplante Pipeline erhält eine Variable ",[120,121,122],"code",{},"TESTS_TO_RUN",", die festlegt, welche Tests sie ausführen soll.",[12,125,126,127,130,131,134],{},"In der Stage ",[71,128,129],{},"run_tests"," findet die eigentliche Angriffssimulation statt. Sie führt die dieser Pipeline zugewiesenen Tests aus, schreibt Ausführungsstatistiken in ",[120,132,133],{},"detection_status.json"," und hält die SOAR-Record-IDs fest, damit die Alert-Korrelation nachgelagert erfolgen kann.",[12,136,114,137,140],{},[71,138,139],{},"pages"," übernimmt Verifizierung und Reporting. Sie fragt unser SOAR ab, um zu bestätigen, dass Alerts erzeugt und korrekt geroutet wurden, aktualisiert die Detection-Metadaten mit den Prüfergebnissen und veröffentlicht das GitLab-Pages-Dashboard mit den aktuellen Testergebnissen.",[12,142,143,144,147],{},"Unten steht eine Vorlage für die GitLab-CI/CD-Konfigurationsdatei ",[120,145,146],{},".gitlab-ci.yml"," der WATCH-Pipeline:",[149,150,155],"pre",{"className":151,"code":152,"language":153,"meta":154,"style":154},"language-yaml shiki shiki-themes github-light","spec:\n  inputs:\n    weekly_scheduling:\n      type: boolean\n      default: false\n      description: \"Enable weekly scheduling of detection tests.\"\n    update_pages:\n      type: boolean\n      default: false\n      description: \"For triggering the update of GitLab Pages dashboard.\"\n\n---\n\n# Specify the Docker image to use for the job\nimage: python:3.12\n\nstages:\n  - schedule_pipelines\n  - run_tests\n  - pages\n\n# Job to manage scheduled pipelines (runs when weekly_scheduling input is true)\nmanage_scheduled_pipelines:\n  stage: schedule_pipelines\n  script:\n    - pip install -r requirements.txt\n    - python scripts/manage_scheduled_pipelines.py\n  rules:\n    - if: $TESTS_TO_RUN == null && $CI_PIPELINE_SOURCE == \"schedule\" && [[ inputs.weekly_scheduling ]] == true\n      when: on_success\n    - when: never\n\n# Job to run detection tests, save tines_record_id to detection_status.json, and commit\nrun_detection_tests:\n  stage: run_tests\n  script:\n    - pip install -r requirements.txt\n    - python main.py --prod --save-stats --scheduled-tests\n  rules:\n    - if: $TESTS_TO_RUN\n      when: on_success\n    - when: never\n\n# Job to verify alerts, update detection_status.json, commit, and deploy pages\npages:\n  stage: pages\n  script:\n    - pip install -r requirements.txt\n    - python scripts/verify_and_update_detections.py --tines-api-key ${TINES_API_KEY}\n    - mkdir -p public/data\n    - cp detection_status.json public/data/\n    - cp -r static/* public/\n  pages: true  # Required for GitLab 17.9+ to trigger Pages deployment\n  artifacts:\n    paths:\n      - public\n  rules:\n    - if: $TESTS_TO_RUN == null && [[ inputs.update_pages ]] == true\n      when: on_success\n    - when: never\n","yaml","",[120,156,157,170,178,186,199,211,222,230,239,248,258,265,272,277,284,295,300,308,317,325,333,338,344,352,362,370,379,387,395,408,419,432,437,443,451,460,467,474,482,489,501,510,521,526,532,539,548,555,562,570,578,586,594,608,616,624,633,640,652,661],{"__ignoreMap":154},[158,159,162,166],"span",{"class":160,"line":161},"line",1,[158,163,165],{"class":164},"shJU0","spec",[158,167,169],{"class":168},"sgsFI",":\n",[158,171,173,176],{"class":160,"line":172},2,[158,174,175],{"class":164},"  inputs",[158,177,169],{"class":168},[158,179,181,184],{"class":160,"line":180},3,[158,182,183],{"class":164},"    weekly_scheduling",[158,185,169],{"class":168},[158,187,189,192,195],{"class":160,"line":188},4,[158,190,191],{"class":164},"      type",[158,193,194],{"class":168},": ",[158,196,198],{"class":197},"sYBdl","boolean\n",[158,200,202,205,207],{"class":160,"line":201},5,[158,203,204],{"class":164},"      default",[158,206,194],{"class":168},[158,208,210],{"class":209},"sYu0t","false\n",[158,212,214,217,219],{"class":160,"line":213},6,[158,215,216],{"class":164},"      description",[158,218,194],{"class":168},[158,220,221],{"class":197},"\"Enable weekly scheduling of detection tests.\"\n",[158,223,225,228],{"class":160,"line":224},7,[158,226,227],{"class":164},"    update_pages",[158,229,169],{"class":168},[158,231,233,235,237],{"class":160,"line":232},8,[158,234,191],{"class":164},[158,236,194],{"class":168},[158,238,198],{"class":197},[158,240,242,244,246],{"class":160,"line":241},9,[158,243,204],{"class":164},[158,245,194],{"class":168},[158,247,210],{"class":209},[158,249,251,253,255],{"class":160,"line":250},10,[158,252,216],{"class":164},[158,254,194],{"class":168},[158,256,257],{"class":197},"\"For triggering the update of GitLab Pages dashboard.\"\n",[158,259,261],{"class":160,"line":260},11,[158,262,264],{"emptyLinePlaceholder":263},true,"\n",[158,266,268],{"class":160,"line":267},12,[158,269,271],{"class":270},"s7eDp","---\n",[158,273,275],{"class":160,"line":274},13,[158,276,264],{"emptyLinePlaceholder":263},[158,278,280],{"class":160,"line":279},14,[158,281,283],{"class":282},"sAwPA","# Specify the Docker image to use for the job\n",[158,285,287,290,292],{"class":160,"line":286},15,[158,288,289],{"class":164},"image",[158,291,194],{"class":168},[158,293,294],{"class":197},"python:3.12\n",[158,296,298],{"class":160,"line":297},16,[158,299,264],{"emptyLinePlaceholder":263},[158,301,303,306],{"class":160,"line":302},17,[158,304,305],{"class":164},"stages",[158,307,169],{"class":168},[158,309,311,314],{"class":160,"line":310},18,[158,312,313],{"class":168},"  - ",[158,315,316],{"class":197},"schedule_pipelines\n",[158,318,320,322],{"class":160,"line":319},19,[158,321,313],{"class":168},[158,323,324],{"class":197},"run_tests\n",[158,326,328,330],{"class":160,"line":327},20,[158,329,313],{"class":168},[158,331,332],{"class":197},"pages\n",[158,334,336],{"class":160,"line":335},21,[158,337,264],{"emptyLinePlaceholder":263},[158,339,341],{"class":160,"line":340},22,[158,342,343],{"class":282},"# Job to manage scheduled pipelines (runs when weekly_scheduling input is true)\n",[158,345,347,350],{"class":160,"line":346},23,[158,348,349],{"class":164},"manage_scheduled_pipelines",[158,351,169],{"class":168},[158,353,355,358,360],{"class":160,"line":354},24,[158,356,357],{"class":164},"  stage",[158,359,194],{"class":168},[158,361,316],{"class":197},[158,363,365,368],{"class":160,"line":364},25,[158,366,367],{"class":164},"  script",[158,369,169],{"class":168},[158,371,373,376],{"class":160,"line":372},26,[158,374,375],{"class":168},"    - ",[158,377,378],{"class":197},"pip install -r requirements.txt\n",[158,380,382,384],{"class":160,"line":381},27,[158,383,375],{"class":168},[158,385,386],{"class":197},"python scripts/manage_scheduled_pipelines.py\n",[158,388,390,393],{"class":160,"line":389},28,[158,391,392],{"class":164},"  rules",[158,394,169],{"class":168},[158,396,398,400,403,405],{"class":160,"line":397},29,[158,399,375],{"class":168},[158,401,402],{"class":164},"if",[158,404,194],{"class":168},[158,406,407],{"class":197},"$TESTS_TO_RUN == null && $CI_PIPELINE_SOURCE == \"schedule\" && [[ inputs.weekly_scheduling ]] == true\n",[158,409,411,414,416],{"class":160,"line":410},30,[158,412,413],{"class":164},"      when",[158,415,194],{"class":168},[158,417,418],{"class":197},"on_success\n",[158,420,422,424,427,429],{"class":160,"line":421},31,[158,423,375],{"class":168},[158,425,426],{"class":164},"when",[158,428,194],{"class":168},[158,430,431],{"class":197},"never\n",[158,433,435],{"class":160,"line":434},32,[158,436,264],{"emptyLinePlaceholder":263},[158,438,440],{"class":160,"line":439},33,[158,441,442],{"class":282},"# Job to run detection tests, save tines_record_id to detection_status.json, and commit\n",[158,444,446,449],{"class":160,"line":445},34,[158,447,448],{"class":164},"run_detection_tests",[158,450,169],{"class":168},[158,452,454,456,458],{"class":160,"line":453},35,[158,455,357],{"class":164},[158,457,194],{"class":168},[158,459,324],{"class":197},[158,461,463,465],{"class":160,"line":462},36,[158,464,367],{"class":164},[158,466,169],{"class":168},[158,468,470,472],{"class":160,"line":469},37,[158,471,375],{"class":168},[158,473,378],{"class":197},[158,475,477,479],{"class":160,"line":476},38,[158,478,375],{"class":168},[158,480,481],{"class":197},"python main.py --prod --save-stats --scheduled-tests\n",[158,483,485,487],{"class":160,"line":484},39,[158,486,392],{"class":164},[158,488,169],{"class":168},[158,490,492,494,496,498],{"class":160,"line":491},40,[158,493,375],{"class":168},[158,495,402],{"class":164},[158,497,194],{"class":168},[158,499,500],{"class":197},"$TESTS_TO_RUN\n",[158,502,504,506,508],{"class":160,"line":503},41,[158,505,413],{"class":164},[158,507,194],{"class":168},[158,509,418],{"class":197},[158,511,513,515,517,519],{"class":160,"line":512},42,[158,514,375],{"class":168},[158,516,426],{"class":164},[158,518,194],{"class":168},[158,520,431],{"class":197},[158,522,524],{"class":160,"line":523},43,[158,525,264],{"emptyLinePlaceholder":263},[158,527,529],{"class":160,"line":528},44,[158,530,531],{"class":282},"# Job to verify alerts, update detection_status.json, commit, and deploy pages\n",[158,533,535,537],{"class":160,"line":534},45,[158,536,139],{"class":164},[158,538,169],{"class":168},[158,540,542,544,546],{"class":160,"line":541},46,[158,543,357],{"class":164},[158,545,194],{"class":168},[158,547,332],{"class":197},[158,549,551,553],{"class":160,"line":550},47,[158,552,367],{"class":164},[158,554,169],{"class":168},[158,556,558,560],{"class":160,"line":557},48,[158,559,375],{"class":168},[158,561,378],{"class":197},[158,563,565,567],{"class":160,"line":564},49,[158,566,375],{"class":168},[158,568,569],{"class":197},"python scripts/verify_and_update_detections.py --tines-api-key ${TINES_API_KEY}\n",[158,571,573,575],{"class":160,"line":572},50,[158,574,375],{"class":168},[158,576,577],{"class":197},"mkdir -p public/data\n",[158,579,581,583],{"class":160,"line":580},51,[158,582,375],{"class":168},[158,584,585],{"class":197},"cp detection_status.json public/data/\n",[158,587,589,591],{"class":160,"line":588},52,[158,590,375],{"class":168},[158,592,593],{"class":197},"cp -r static/* public/\n",[158,595,597,600,602,605],{"class":160,"line":596},53,[158,598,599],{"class":164},"  pages",[158,601,194],{"class":168},[158,603,604],{"class":209},"true",[158,606,607],{"class":282},"  # Required for GitLab 17.9+ to trigger Pages deployment\n",[158,609,611,614],{"class":160,"line":610},54,[158,612,613],{"class":164},"  artifacts",[158,615,169],{"class":168},[158,617,619,622],{"class":160,"line":618},55,[158,620,621],{"class":164},"    paths",[158,623,169],{"class":168},[158,625,627,630],{"class":160,"line":626},56,[158,628,629],{"class":168},"      - ",[158,631,632],{"class":197},"public\n",[158,634,636,638],{"class":160,"line":635},57,[158,637,392],{"class":164},[158,639,169],{"class":168},[158,641,643,645,647,649],{"class":160,"line":642},58,[158,644,375],{"class":168},[158,646,402],{"class":164},[158,648,194],{"class":168},[158,650,651],{"class":197},"$TESTS_TO_RUN == null && [[ inputs.update_pages ]] == true\n",[158,653,655,657,659],{"class":160,"line":654},59,[158,656,413],{"class":164},[158,658,194],{"class":168},[158,660,418],{"class":197},[158,662,664,666,668,670],{"class":160,"line":663},60,[158,665,375],{"class":168},[158,667,426],{"class":164},[158,669,194],{"class":168},[158,671,431],{"class":197},[22,673,675],{"id":674},"tests-mit-gitlab-duo-schreiben","Tests mit GitLab Duo schreiben",[12,677,678,679,682],{},"Beim Entwurf von WATCH kam es unter anderem darauf an, dass im Signals-Engineering- und im SIRT-Team alle mühelos neue Tests ergänzen können. Das Framework stellt dafür eine abstrakte Klasse ",[120,680,681],{},"BaseSecurityTest"," bereit, die den gesamten Boilerplate-Code übernimmt: das Erzeugen der Test-ID, die Verwaltung der Akteursidentität und die Abstimmung mit dem SOAR. Wer Tests schreibt, muss sich damit nur um drei Dinge kümmern: die Testumgebung aufsetzen, das simulierte Angreiferverhalten ausführen und anschließend aufräumen.",[149,684,688],{"className":685,"code":686,"language":687,"meta":154,"style":154},"language-python shiki shiki-themes github-light","class BaseSecurityTest(ABC):\n\n    def __init__(self, config = {}, test_id: Optional[str] = None):\n        self.test_id = test_id or str(uuid.uuid4())\n        self.test_name = self.__class__.__name__\n        self.expected_detections = {}\n        self.actor_id = config.get('gitlab', {}).get(\n            'default_actor_id',\n            \"sirt_detection_test_user_\" + self.test_id[:8]\n        )\n        self.isActive = True\n        self.test_run_time = 300\n        self.config = config\n\n    @abstractmethod\n    def setup(self) -> bool:\n        \"\"\"Prepare test environment and resources\"\"\"\n\n    @abstractmethod\n    def execute(self) -> Dict[str, Any]:\n        \"\"\"Execute the malicious behavior simulation\"\"\"\n\n    @abstractmethod\n    def cleanup(self) -> bool:\n        \"\"\"Clean up test environment and resources\"\"\"\n","python",[120,689,690,708,712,742,764,787,799,817,825,844,849,861,873,885,889,894,909,914,918,922,937,942,946,950,963],{"__ignoreMap":154},[158,691,692,696,699,702,705],{"class":160,"line":161},[158,693,695],{"class":694},"sD7c4","class",[158,697,698],{"class":270}," BaseSecurityTest",[158,700,701],{"class":168},"(",[158,703,704],{"class":209},"ABC",[158,706,707],{"class":168},"):\n",[158,709,710],{"class":160,"line":172},[158,711,264],{"emptyLinePlaceholder":263},[158,713,714,717,720,723,726,729,732,735,737,740],{"class":160,"line":180},[158,715,716],{"class":694},"    def",[158,718,719],{"class":209}," __init__",[158,721,722],{"class":168},"(self, config ",[158,724,725],{"class":694},"=",[158,727,728],{"class":168}," {}, test_id: Optional[",[158,730,731],{"class":209},"str",[158,733,734],{"class":168},"] ",[158,736,725],{"class":694},[158,738,739],{"class":209}," None",[158,741,707],{"class":168},[158,743,744,747,750,752,755,758,761],{"class":160,"line":188},[158,745,746],{"class":209},"        self",[158,748,749],{"class":168},".test_id ",[158,751,725],{"class":694},[158,753,754],{"class":168}," test_id ",[158,756,757],{"class":694},"or",[158,759,760],{"class":209}," str",[158,762,763],{"class":168},"(uuid.uuid4())\n",[158,765,766,768,771,773,776,779,782,784],{"class":160,"line":201},[158,767,746],{"class":209},[158,769,770],{"class":168},".test_name ",[158,772,725],{"class":694},[158,774,775],{"class":209}," self",[158,777,778],{"class":168},".",[158,780,781],{"class":209},"__class__",[158,783,778],{"class":168},[158,785,786],{"class":209},"__name__\n",[158,788,789,791,794,796],{"class":160,"line":213},[158,790,746],{"class":209},[158,792,793],{"class":168},".expected_detections ",[158,795,725],{"class":694},[158,797,798],{"class":168}," {}\n",[158,800,801,803,806,808,811,814],{"class":160,"line":224},[158,802,746],{"class":209},[158,804,805],{"class":168},".actor_id ",[158,807,725],{"class":694},[158,809,810],{"class":168}," config.get(",[158,812,813],{"class":197},"'gitlab'",[158,815,816],{"class":168},", {}).get(\n",[158,818,819,822],{"class":160,"line":232},[158,820,821],{"class":197},"            'default_actor_id'",[158,823,824],{"class":168},",\n",[158,826,827,830,833,835,838,841],{"class":160,"line":241},[158,828,829],{"class":197},"            \"sirt_detection_test_user_\"",[158,831,832],{"class":694}," +",[158,834,775],{"class":209},[158,836,837],{"class":168},".test_id[:",[158,839,840],{"class":209},"8",[158,842,843],{"class":168},"]\n",[158,845,846],{"class":160,"line":250},[158,847,848],{"class":168},"        )\n",[158,850,851,853,856,858],{"class":160,"line":260},[158,852,746],{"class":209},[158,854,855],{"class":168},".isActive ",[158,857,725],{"class":694},[158,859,860],{"class":209}," True\n",[158,862,863,865,868,870],{"class":160,"line":267},[158,864,746],{"class":209},[158,866,867],{"class":168},".test_run_time ",[158,869,725],{"class":694},[158,871,872],{"class":209}," 300\n",[158,874,875,877,880,882],{"class":160,"line":274},[158,876,746],{"class":209},[158,878,879],{"class":168},".config ",[158,881,725],{"class":694},[158,883,884],{"class":168}," config\n",[158,886,887],{"class":160,"line":279},[158,888,264],{"emptyLinePlaceholder":263},[158,890,891],{"class":160,"line":286},[158,892,893],{"class":270},"    @abstractmethod\n",[158,895,896,898,901,904,907],{"class":160,"line":297},[158,897,716],{"class":694},[158,899,900],{"class":270}," setup",[158,902,903],{"class":168},"(self) -> ",[158,905,906],{"class":209},"bool",[158,908,169],{"class":168},[158,910,911],{"class":160,"line":302},[158,912,913],{"class":197},"        \"\"\"Prepare test environment and resources\"\"\"\n",[158,915,916],{"class":160,"line":310},[158,917,264],{"emptyLinePlaceholder":263},[158,919,920],{"class":160,"line":319},[158,921,893],{"class":270},[158,923,924,926,929,932,934],{"class":160,"line":327},[158,925,716],{"class":694},[158,927,928],{"class":270}," execute",[158,930,931],{"class":168},"(self) -> Dict[",[158,933,731],{"class":209},[158,935,936],{"class":168},", Any]:\n",[158,938,939],{"class":160,"line":335},[158,940,941],{"class":197},"        \"\"\"Execute the malicious behavior simulation\"\"\"\n",[158,943,944],{"class":160,"line":340},[158,945,264],{"emptyLinePlaceholder":263},[158,947,948],{"class":160,"line":346},[158,949,893],{"class":270},[158,951,952,954,957,959,961],{"class":160,"line":354},[158,953,716],{"class":694},[158,955,956],{"class":270}," cleanup",[158,958,903],{"class":168},[158,960,906],{"class":209},[158,962,169],{"class":168},[158,964,965],{"class":160,"line":364},[158,966,967],{"class":197},"        \"\"\"Clean up test environment and resources\"\"\"\n",[12,969,970,971,974,975,978,979,981],{},"Zentral für die Konfiguration ist das Dictionary ",[120,972,973],{},"expected_detections",". Es ordnet die SIEM-Regelnamen der erwarteten Detections der Akteursidentität und dem erwarteten Eintreffzeitpunkt des Alerts zu. Ein neuer Test ist einfach eine Python-Datei im Verzeichnis ",[120,976,977],{},"tests/",", die von ",[120,980,681],{}," erbt, ihr simuliertes Verhalten definiert und angibt, welche Detections sie auslösen soll. Der Test-Runner findet sie beim nächsten geplanten Lauf automatisch.",[12,983,984,985,988,989,992,993,996,997,1002],{},"Diese reibungsarme Schnittstelle ist wichtig, denn Detection-Tests funktionieren als Praxis nur, wenn das Team tatsächlich Tests schreibt. Wenn das Ergänzen eines Tests verlangt, die Interna der gesamten Pipeline zu durchdringen, wird es niemand tun. Der einfache Vertrag, ",[120,986,987],{},"setup",", ",[120,990,991],{},"execute"," und ",[120,994,995],{},"cleanup"," zu implementieren und die erwarteten Detections zu deklarieren, macht WATCH-Tests außerdem zu einem guten Kandidaten für ",[36,998,1001],{"href":999,"rel":1000},"https://about.gitlab.com/de-de/gitlab-duo-agent-platform/",[],"GitLab Duo",", GitLabs KI-Assistenz. Duo bekommt die Basisklasse und einen Prompt wie \"Erstelle mir einen Test, der viele Projekte aus einer Zielgruppe klont\" oder \"Erstelle mir einen Test, der über GraphQL auf alle CI-Variablen dieses Projekts zugreift\" oder auch \"Benenne all diese Projekte nach demselben Schema um\". Duo kann daraus einen funktionierenden WATCH-Test bauen, der sich direkt in das Framework einfügt. Das senkt die Hürde weiter: Vom Wunsch, eine bestimmte Detection zu testen, bis zum laufenden Test übernimmt Duo den Großteil der Umsetzung.",[12,1004,1005,1006,1011,1012,1015],{},"Tipp: Um GitLab Duo noch wirksamer einzusetzen, habe ich ",[36,1007,1010],{"href":1008,"rel":1009},"https://docs.gitlab.com/user/duo_agent_platform/customize/agent_skills/",[],"Duo Agent Skills"," genutzt. Sie eignen sich gut dafür, Standards und Abläufe für wiederkehrende Arbeit wie das Schreiben von Tests festzulegen. In unserem Projektverzeichnis liegt ein Ordner ",[120,1013,1014],{},"skills/WATCH-test-creator"," mit einer SKILL.md, die beschreibt, was einen guten Test auszeichnet, welche Hilfsfunktionen ein Test nutzen kann und wozu das Projekt dient. Diese Datei wird unmittelbar nach einem Prompt wie den oben genannten gelesen. Damit entfällt es, Duo ständig daran zu erinnern, worum es gerade geht und wie vorzugehen ist. Vor allem werden die Ergebnisse dadurch konsistenter und besser. Hier ein Auszug aus dieser Datei:",[149,1017,1022],{"className":1018,"code":1020,"language":1021,"meta":154},[1019],"language-text","---\nname: WATCH-test-creator\ndescription: Create WATCH (Orchestrated Offensive Penetration Simulator) security detection tests that simulate malicious behavior on GitLab infrastructure to validate SIEM detection rules and alerting pipelines.\n---\n\n## WATCH Test Creator\n\nYou are an expert at writing security detection tests for the WATCH framework. WATCH tests simulate malicious activities on GitLab-owned infrastructure to verify that the SecOps security monitoring stack (Elastic SIEM, Tines SOAR, alerting rules) properly detects and responds to threats.\n\n### Architecture Overview\n```\nProject Root\n├── core/\n│   ├── base_test.py          # Abstract base class all tests inherit from\n│   ├── test_runner.py         # Auto-discovers and executes tests\n│   └── webhook_manager.py     # Tines/SOAR notification integration\n├── tests/\n│   ├── gitlab/                # GitLab-specific detection tests\n│   └── gcp/                   # GCP-specific detection tests\n├── utils/\n│   ├── gitlab_helper.py       # GitLab API wrapper (users, projects, tokens, webhooks, OAuth)\n│   └── crypto_utils.py        # Password generation utility\n├── config/\n│   ├── settings.py            # Config loader (reads YAML + GITLAB_ADMIN_PAT env var)\n│   └── environments/\n│       ├── dev.yaml           # Local GDK config\n│       └── prod.yaml          # Production staging.gitlab.com config\n├── main.py                    # Entry point with CLI args\n└── detection_status.json      # Test results and detection metadata\n```\n\n","text",[120,1023,1020],{"__ignoreMap":154},[22,1025,1027],{"id":1026},"mehr-sichtbarkeit-durch-test-dashboards","Mehr Sichtbarkeit durch Test-Dashboards",[12,1029,1030],{},[1031,1032],"img",{"alt":1033,"src":1034},"Test-Dashboards","https://res.cloudinary.com/about-gitlab-com/image/upload/v1777574679/ylrc96iip682sinfg7zi.png",[12,1036,1037,1038,1043],{},"WATCH veröffentlicht außerdem zwei interaktive Dashboards über ",[36,1039,1042],{"href":1040,"rel":1041},"https://docs.gitlab.com/user/project/pages/",[],"GitLab Pages",", die dem Team in Echtzeit Einblick in den Zustand der Detections geben.",[1045,1046,1047,1054],"ul",{},[68,1048,1049,1050,1053],{},"Das ",[71,1051,1052],{},"Detection-Status-Dashboard"," gibt einen Überblick über alle Detection-Regeln und ihren aktuellen Teststatus, samt Kennzahlen wie der Zahl der bisherigen Auslösungen, dem aktuellen Pass-/Fail-Zustand und der Dauer, die eine Detection schon aktiv ist. Die Tabelle lässt sich filtern und sortieren, sodass sich schnell erkennen lässt, welche Detections Aufmerksamkeit brauchen.",[68,1055,1049,1056,1059],{},[71,1057,1058],{},"Test-Runs-Dashboard"," bietet eine detaillierte Sicht auf einzelne Testläufe, gruppiert nach Test-ID und mit einer Aufschlüsselung der Detection-Abdeckung. Es enthält eine Zeitleiste der Alert-Propagation, die zeigt, wie lange es von der Testausführung bis zum Eintreffen des Alerts dauerte, sowie direkte Verweise auf die zugehörigen Alerts in unserem SIEM.",[12,1061,1062],{},"Diese Dashboards ersetzen einen vormals manuellen Vorgang, bei dem sich das Team durch Pipeline-Logs und SIEM-Abfragen graben musste, um den Zustand der Detections zu beurteilen.",[12,1064,1065,1066,1071],{},"Wie der Rest von ",[36,1067,1070],{"href":1068,"rel":1069},"https://about.gitlab.com/de-de/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab/",[],"GUARD"," stützt sich WATCH stark auf GitLab als Plattform:",[1045,1073,1074,1080,1086,1092,1097],{},[68,1075,1076,1079],{},[71,1077,1078],{},"GitLab-CI/CD-Pipelines und geplante Pipelines"," orchestrieren den gesamten Test-Lebenszyklus, von der wöchentlichen Planung über die Ausführung bis zur Veröffentlichung der Dashboards.",[68,1081,1082,1085],{},[71,1083,1084],{},"Pipeline-Inputs"," erlauben es, Stages unabhängig anzustoßen. So lässt sich nur der Verifizierungsschritt oder nur die Dashboard-Aktualisierung erneut ausführen, ohne alle Tests neu laufen zu lassen.",[68,1087,1088,1091],{},[71,1089,1090],{},"CI/CD-Variablen"," halten die API-Schlüssel für Tines und den Zugang zur GitLab-Staging-Umgebung sicher vor.",[68,1093,1094,1096],{},[71,1095,1042],{}," hostet die WATCH-Dashboards ohne zusätzliche Infrastruktur. Es gibt also kein separates Hosting zu verwalten und keine zusätzlichen Deployment-Werkzeuge.",[68,1098,1099,1100,1103],{},"Da Tests einfach Python-Dateien in einem GitLab-Projekt sind, profitieren sie von ",[71,1101,1102],{},"Versionskontrolle, Merge-Request-Reviews und Code-Ownership",", genauso wie unsere Detection-Regeln über DaC.",[22,1105,1107],{"id":1106},"mit-watch-vorausschauend-bleiben","Mit WATCH vorausschauend bleiben",[12,1109,1110,1111,1114],{},"Mit WATCH hat sich das Verhältnis unseres Teams zur Detection-Qualität verschoben: von reaktiv zu vorausschauend. Vor WATCH zeigte sich eine defekte Detection erst dann, wenn ein Vorfall eintrat und der erwartete Alert ausblieb, also zum schlechtesten denkbaren Zeitpunkt. Inzwischen erhalten wir regelmäßig Rückmeldung zum Zustand unserer Detections und wissen von einem Defekt, ",[43,1112,1113],{},"bevor"," tatsächlich etwas passiert. Das gibt uns die Gewissheit, dass neue Detections nicht unbemerkt kaputtgehen und in Vergessenheit geraten.",[12,1116,1117],{},"WATCH hält außerdem die Taktiken, Techniken und Prozeduren (TTPs) fest, die unser Red Team bei Flash-Operationen eingesetzt hat. Sind Detections implementiert und ist die rückblickende Analyse einer Pentest-Operation abgeschlossen, lassen sich die verwendeten TTPs mit WATCH erneut abspielen, um diese Detections zu validieren. Im Kern macht WATCH aus atomaren Detection-Tests wiederholbare TTPs.",[22,1119,1121],{"id":1120},"watch-ausprobieren","WATCH ausprobieren",[12,1123,1124,1125,1130],{},"Wer ein SOC betreibt und sich beim Erkennen von Bedrohungen auf SIEM-Detections verlässt, steht nicht vor der Frage, ob Detections irgendwann versagen, sondern davor, ob der Ausfall auffällt. Für den Anfang braucht es dafür keine kommerzielle BAS-Plattform. Eine Sandbox-Umgebung, eine ",[36,1126,1129],{"href":1127,"rel":1128},"https://about.gitlab.com/de-de/topics/ci-cd/cicd-pipeline/",[],"CI/CD-Pipeline"," und ein Framework für skriptgesteuerte Angriffssimulationen bringen einen weit.",[12,1132,1133,1134,1139],{},"Ein eigenes Framework für Detection-Tests lässt sich mit einer ",[36,1135,1138],{"href":1136,"rel":1137},"https://about.gitlab.com/de-de/free-trial/",[],"kostenlosen Testversion von GitLab Ultimate"," aufbauen.",[1141,1142,1143],"style",{},"html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}",{"title":154,"searchDepth":172,"depth":172,"links":1145},[1146,1147,1148,1149,1150,1151,1152],{"id":24,"depth":172,"text":25},{"id":56,"depth":172,"text":57},{"id":107,"depth":172,"text":108},{"id":674,"depth":172,"text":675},{"id":1026,"depth":172,"text":1027},{"id":1106,"depth":172,"text":1107},{"id":1120,"depth":172,"text":1121},"security-labs","2026-08-14","Wie das Signals-Engineering-Team von GitLab das WATCH-Framework gebaut hat, um die eigene Security-Monitoring-Pipeline fortlaufend zu validieren.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772195014/ooezwusxjl1f7ijfmbvj.png",{},"/de-de/blog/automated-detection-testing-framework",{"config":1163,"title":1164,"description":1155},{"noIndex":1158},"Detection-Tests mit GitLab CI/CD automatisieren","automated-detection-testing-framework","de-de/blog/automated-detection-testing-framework",[1168,1169,1170],"security","security research","features","BlogPost","dmnwsuLl2OZRgJfCJ3UMwpW6Ijh-Je3fKICZTNvNCxQ",{"logo":1174,"freeTrial":1179,"sales":1184,"login":1189,"items":1194,"search":1525,"minimal":1560,"duo":1579,"switchNav":1588,"pricingDeployment":1599},{"config":1175},{"href":1176,"dataGaName":1177,"dataGaLocation":1178},"/de-de/","gitlab logo","header",{"text":1180,"config":1181},"Kostenlose Testversion anfordern",{"href":1182,"dataGaName":1183,"dataGaLocation":1178},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/de-de&glm_content=default-saas-trial/","free trial",{"text":1185,"config":1186},"Demo anfordern",{"href":1187,"dataGaName":1188,"dataGaLocation":1178},"/request-a-demo/","sales",{"text":1190,"config":1191},"Anmelden",{"href":1192,"dataGaName":1193,"dataGaLocation":1178},"https://gitlab.com/users/sign_in/","sign in",[1195,1281,1369,1374,1449,1503],{"text":1196,"left":263,"config":1197,"menu":1199},"Plattform",{"dataNavLevelOne":1198},"platform",{"type":1200,"link":1201,"columns":1205,"feature":1270},"lists",{"text":1202,"config":1203},"Die Plattform erkunden",{"href":1204,"dataGaName":1198,"dataGaLocation":1178},"/de-de/platform/",[1206,1229,1252],{"title":1207,"items":1208},"Ausführung und Workflows",[1209,1214,1219,1224],{"text":1210,"config":1211},"CI/CD",{"href":1212,"dataGaLocation":1178,"dataGaName":1213},"/de-de/solutions/continuous-integration/","ci/cd",{"text":1215,"config":1216},"Quellcodeverwaltung",{"href":1217,"dataGaLocation":1178,"dataGaName":1218},"/de-de/solutions/source-code-management/","source code management",{"text":1220,"config":1221},"Agile Delivery",{"href":1222,"dataGaLocation":1178,"dataGaName":1223},"/de-de/solutions/agile-delivery/","agile delivery",{"text":1225,"config":1226},"Artefaktverwaltung",{"href":1227,"dataGaLocation":1178,"dataGaName":1228},"/de-de/artifact-central/","artifact management",{"title":1230,"items":1231},"Sicherheit und Governance",[1232,1237,1242,1247],{"text":1233,"config":1234},"Anwendungssicherheitstests",{"href":1235,"dataGaLocation":1178,"dataGaName":1236},"/de-de/solutions/application-security-testing/","application security testing",{"text":1238,"config":1239},"Governance und Compliance",{"href":1240,"dataGaLocation":1178,"dataGaName":1241},"/de-de/solutions/software-compliance/","governance and compliance",{"text":1243,"config":1244},"Secrets-Management",{"href":1245,"dataGaLocation":1178,"dataGaName":1246},"/de-de/gitlab-secrets-manager/","secrets management",{"text":1248,"config":1249},"Lieferkettensicherheit",{"href":1250,"dataGaLocation":1178,"dataGaName":1251},"/de-de/solutions/supply-chain/","supply chain security",{"title":1253,"items":1254},"Kontext und KI",[1255,1260,1265],{"text":1256,"config":1257},"Agentische Orchestrierung",{"href":1258,"dataGaLocation":1178,"dataGaName":1259},"/de-de/gitlab-duo-agent-platform/","agentic orchestration",{"text":1261,"config":1262},"Kontextgraph",{"href":1263,"dataGaLocation":1178,"dataGaName":1264},"/de-de/gitlab-orbit/","context graph",{"text":1266,"config":1267},"Sichtbarkeit und Messung",{"href":1268,"dataGaLocation":1178,"dataGaName":1269},"/de-de/solutions/visibility-measurement/","visibility and measurement",{"config":1271,"title":1274,"text":1275,"link":1276},{"background":1272,"textColor":1273},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1790185102/o7dn32anqcb6z8dgd3as.jpg')","#000","Warum GitLab","Eine Plattform für Schnelligkeit und Kontrolle im gesamten Software-Lebenszyklus.",{"text":1277,"config":1278},"Mehr erfahren",{"href":1279,"dataGaName":1280,"dataGaLocation":1178},"/de-de/why-gitlab/","why gitlab",{"text":1282,"left":263,"config":1283,"menu":1285},"Lösungen",{"dataNavLevelOne":1284},"solutions",{"type":1200,"link":1286,"columns":1290,"feature":1360},{"text":1287,"config":1288},"Alle Lösungen anzeigen",{"href":1289,"dataGaName":1284,"dataGaLocation":1178},"/de-de/solutions/",[1291,1309,1327],{"title":1292,"items":1293},"Ergebnisse",[1294,1299,1304],{"text":1295,"config":1296},"DevOps-Modernisierung",{"href":1297,"dataGaLocation":1178,"dataGaName":1298},"/de-de/assessments/devops-modernization-assessment/","devops modernization",{"text":1300,"config":1301},"Sicherheitsmodernisierung",{"href":1302,"dataGaLocation":1178,"dataGaName":1303},"/de-de/assessments/security-modernization-assessment/","security modernization",{"text":1305,"config":1306},"KI-Modernisierung",{"href":1307,"dataGaLocation":1178,"dataGaName":1308},"/de-de/assessments/ai-modernization-assessment/","ai modernization",{"title":1310,"items":1311},"Nach Größe",[1312,1317,1322],{"text":1313,"config":1314},"Große Unternehmen",{"href":1315,"dataGaLocation":1178,"dataGaName":1316},"/de-de/enterprise/","enterprise",{"text":1318,"config":1319},"Kleine Unternehmen",{"href":1320,"dataGaLocation":1178,"dataGaName":1321},"/de-de/small-business/","small business",{"text":1323,"config":1324},"Start-ups",{"href":1325,"dataGaLocation":1178,"dataGaName":1326},"/de-de/solutions/startups/","startups",{"title":1328,"items":1329},"Branchen",[1330,1335,1340,1345,1350,1355],{"text":1331,"config":1332},"Finanzdienstleistungen",{"href":1333,"dataGaLocation":1178,"dataGaName":1334},"/de-de/solutions/finance/","financial services",{"text":1336,"config":1337},"Öffentlicher Sektor",{"href":1338,"dataGaLocation":1178,"dataGaName":1339},"/de-de/solutions/public-sector/","public sector",{"text":1341,"config":1342},"Telekommunikation",{"href":1343,"dataGaLocation":1178,"dataGaName":1344},"/de-de/solutions/telecommunications/","telecommunications",{"text":1346,"config":1347},"Automobilindustrie",{"href":1348,"dataGaLocation":1178,"dataGaName":1349},"/de-de/solutions/automotive/","automotive",{"text":1351,"config":1352},"Bildungswesen",{"href":1353,"dataGaLocation":1178,"dataGaName":1354},"/de-de/solutions/education/","education",{"text":1356,"config":1357},"Luft- und Raumfahrt",{"href":1358,"dataGaLocation":1178,"dataGaName":1359},"/de-de/solutions/aerospace/","aerospace",{"config":1361,"title":1362,"text":1363,"link":1364},{"background":1272,"textColor":1273},"GitLab-Sicherheitsstandard","Mehr dazu, wie du deine Software Factory stärkst und KI-Agenten Autonomie gewinnen lässt, ohne an Sicherheit einzubüßen.",{"text":1365,"config":1366},"Standard entdecken",{"href":1367,"dataGaName":1368,"dataGaLocation":1178},"/gitlab-security-standard/","gitlab security standard",{"text":1370,"config":1371},"Preise",{"href":1372,"dataGaName":1373,"dataGaLocation":1178,"dataNavLevelOne":1373},"/de-de/pricing/","pricing",{"text":1375,"config":1376,"menu":1378},"Ressourcen",{"dataNavLevelOne":1377},"resources",{"type":1200,"link":1379,"columns":1383,"feature":1440},{"text":1380,"config":1381},"Alle Ressourcen anzeigen",{"href":1382,"dataGaName":1377,"dataGaLocation":1178},"/de-de/resources/",[1384,1412],{"title":1385,"items":1386},"Entdecken",[1387,1392,1397,1402,1407],{"text":1388,"config":1389},"Dokumentation",{"href":1390,"dataGaName":1391,"dataGaLocation":1178},"https://docs.gitlab.com/","docs",{"text":1393,"config":1394},"GitLab University",{"href":1395,"dataGaName":1396,"dataGaLocation":1178},"https://university.gitlab.com/","university",{"text":1398,"config":1399},"Demo-Reihe",{"href":1400,"dataGaName":1401,"dataGaLocation":1178},"/de-de/gitlab-technical-demo-series/","demo series",{"text":1403,"config":1404},"Demo-Hub",{"href":1405,"dataGaName":1406,"dataGaLocation":1178},"/de-de/demo-hub/","demo hub",{"text":1408,"config":1409},"Dienste",{"href":1410,"dataGaName":1411,"dataGaLocation":1178},"/de-de/services/","services",{"title":1413,"items":1414},"Vernetzen",[1415,1420,1425,1430,1435],{"text":1416,"config":1417},"Blog",{"href":1418,"dataGaName":1419,"dataGaLocation":1178},"/de-de/blog/","blog",{"text":1421,"config":1422},"Community",{"href":1423,"dataGaName":1424,"dataGaLocation":1178},"/community/","community",{"text":1426,"config":1427},"Kunden",{"href":1428,"dataGaName":1429,"dataGaLocation":1178},"/de-de/customers/","customers",{"text":1431,"config":1432},"Partner",{"href":1433,"dataGaName":1434,"dataGaLocation":1178},"/de-de/partners/","partners",{"text":1436,"config":1437},"Veranstaltungen",{"href":1438,"dataGaName":1439,"dataGaLocation":1178},"/events/","events",{"config":1441,"title":1442,"text":1443,"link":1444},{"background":1272,"textColor":1273},"Neues bei GitLab","Über die neuesten Funktionen und Verbesserungen auf dem Laufenden bleiben.",{"text":1445,"config":1446},"Aktuelle Nachrichten",{"href":1447,"dataGaName":1448,"dataGaLocation":1178},"/de-de/whats-new/","whats new",{"text":1450,"config":1451,"menu":1453},"Unternehmen",{"dataNavLevelOne":1452},"company",{"type":1200,"columns":1454},[1455],{"items":1456},[1457,1462,1468,1473,1478,1483,1488,1493,1498],{"text":1458,"config":1459},"Über",{"href":1460,"dataGaName":1461,"dataGaLocation":1178},"/de-de/company/","about",{"text":1463,"config":1464,"footerGa":1467},"Karriere",{"href":1465,"dataGaName":1466,"dataGaLocation":1178},"/jobs/","jobs",{"dataGaName":1466},{"text":1469,"config":1470},"Presse",{"href":1471,"dataGaName":1472,"dataGaLocation":1178},"/press/","press",{"text":1474,"config":1475},"Handbuch",{"href":1476,"dataGaName":1477,"dataGaLocation":1178},"https://handbook.gitlab.com/","handbook",{"text":1479,"config":1480},"Geschäftsführung",{"href":1481,"dataGaName":1482,"dataGaLocation":1178},"/company/team/e-group/","leadership",{"text":1484,"config":1485},"Investor Relations",{"href":1486,"dataGaName":1487,"dataGaLocation":1178},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1489,"config":1490},"Trust Center",{"href":1491,"dataGaName":1492,"dataGaLocation":1178},"/de-de/security/","trust center",{"text":1494,"config":1495},"AI Transparency Center",{"href":1496,"dataGaName":1497,"dataGaLocation":1178},"/de-de/ai-transparency-center/","ai transparency center",{"text":1499,"config":1500},"Newsletter",{"href":1501,"dataGaName":1502,"dataGaLocation":1178},"/company/contact/#contact-forms","newsletter",{"text":1504,"config":1505,"menu":1506},"Kontakt",{"dataNavLevelOne":1452},{"type":1200,"columns":1507},[1508],{"items":1509},[1510,1515,1520],{"text":1511,"config":1512},"Vertrieb kontaktieren",{"href":1513,"dataGaName":1514,"dataGaLocation":1178},"/de-de/sales/","talk to sales",{"text":1516,"config":1517},"Support-Portal",{"href":1518,"dataGaName":1519,"dataGaLocation":1178},"https://support.gitlab.com/hc/en-us","support portal",{"text":1521,"config":1522},"Kundenportal",{"href":1523,"dataGaName":1524,"dataGaLocation":1178},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1526,"login":1527,"suggestions":1534},"Schließen",{"text":1528,"link":1529},"Um Repositorys und Projekte zu durchsuchen, melde dich an bei",{"text":1530,"config":1531},"gitlab.com",{"href":1192,"dataGaName":1532,"dataGaLocation":1533},"search login","search",{"text":1535,"default":1536},"Vorschläge",[1537,1540,1544,1546,1551,1556],{"text":1538,"config":1539},"GitLab Duo Agent Platform",{"href":1258,"dataGaName":1538,"dataGaLocation":1533},{"text":1541,"config":1542},"Codevorschläge (KI)",{"href":1258,"dataGaName":1543,"dataGaLocation":1533},"Code Suggestions (AI)",{"text":1210,"config":1545},{"href":1212,"dataGaName":1210,"dataGaLocation":1533},{"text":1547,"config":1548},"GitLab auf AWS",{"href":1549,"dataGaName":1550,"dataGaLocation":1533},"/de-de/partners/technology-partners/aws/","GitLab on AWS",{"text":1552,"config":1553},"GitLab auf Google Cloud",{"href":1554,"dataGaName":1555,"dataGaLocation":1533},"/de-de/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":1557,"config":1558},"Warum GitLab?",{"href":1279,"dataGaName":1559,"dataGaLocation":1533},"Why GitLab?",{"freeTrial":1561,"mobileIcon":1566,"desktopIcon":1571,"secondaryButton":1574},{"text":1562,"config":1563},"Kostenlos testen",{"href":1564,"dataGaName":1183,"dataGaLocation":1565},"https://gitlab.com/-/trials/new/","nav",{"altText":1567,"config":1568},"GitLab-Symbol",{"src":1569,"dataGaName":1570,"dataGaLocation":1565},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1567,"config":1572},{"src":1573,"dataGaName":1570,"dataGaLocation":1565},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1575,"config":1576},"Erste Schritte",{"href":1577,"dataGaName":1578,"dataGaLocation":1565},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/de-de/get-started/","get started",{"freeTrial":1580,"mobileIcon":1584,"desktopIcon":1586},{"text":1581,"config":1582},"Mehr über GitLab Duo erfahren",{"href":1258,"dataGaName":1583,"dataGaLocation":1565},"gitlab duo",{"altText":1567,"config":1585},{"src":1569,"dataGaName":1570,"dataGaLocation":1565},{"altText":1567,"config":1587},{"src":1573,"dataGaName":1570,"dataGaLocation":1565},{"button":1589,"mobileIcon":1594,"desktopIcon":1596},{"text":1590,"config":1591},"/Option",{"href":1592,"dataGaName":1593,"dataGaLocation":1565},"#contact","switch",{"altText":1567,"config":1595},{"src":1569,"dataGaName":1570,"dataGaLocation":1565},{"altText":1567,"config":1597},{"src":1598,"dataGaName":1570,"dataGaLocation":1565},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1600,"mobileIcon":1605,"desktopIcon":1607},{"text":1601,"config":1602},"Zurück zur Preisübersicht",{"href":1372,"dataGaName":1603,"dataGaLocation":1565,"icon":1604},"back to pricing","GoBack",{"altText":1567,"config":1606},{"src":1569,"dataGaName":1570,"dataGaLocation":1565},{"altText":1567,"config":1608},{"src":1573,"dataGaName":1570,"dataGaLocation":1565},{"title":1610,"button":1611,"config":1614},"GitLab Orbit ist da: die Kontextebene für KI-Agenten",{"text":1277,"config":1612},{"href":1263,"dataGaName":1613,"dataGaLocation":1178},"orbit",{"layout":1615,"disabled":1158},"release",{"data":1617},{"text":1618,"source":1619,"edit":1625,"contribute":1630,"config":1635,"items":1640,"minimal":1862},"Git ist eine Marke von Software Freedom Conservancy und unsere Verwendung von „GitLab“ erfolgt unter Lizenz.",{"text":1620,"config":1621},"Quelltext der Seite anzeigen",{"href":1622,"dataGaName":1623,"dataGaLocation":1624},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1626,"config":1627},"Diese Seite bearbeiten",{"href":1628,"dataGaName":1629,"dataGaLocation":1624},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1631,"config":1632},"Beteilige dich",{"href":1633,"dataGaName":1634,"dataGaLocation":1624},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1636,"facebook":1637,"youtube":1638,"linkedin":1639},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1641,1686,1744,1787,1829],{"title":1370,"links":1642,"subMenu":1657},[1643,1647,1652],{"text":1644,"config":1645},"Tarife anzeigen",{"href":1372,"dataGaName":1646,"dataGaLocation":1624},"view plans",{"text":1648,"config":1649},"Vorteile von Premium",{"href":1650,"dataGaName":1651,"dataGaLocation":1624},"/de-de/pricing/premium/","why premium",{"text":1653,"config":1654},"Vorteile von Ultimate",{"href":1655,"dataGaName":1656,"dataGaLocation":1624},"/de-de/pricing/ultimate/","why ultimate",[1658],{"title":1504,"links":1659},[1660,1662,1664,1666,1671,1676,1681],{"text":1511,"config":1661},{"href":1513,"dataGaName":1188,"dataGaLocation":1624},{"text":1516,"config":1663},{"href":1518,"dataGaName":1519,"dataGaLocation":1624},{"text":1521,"config":1665},{"href":1523,"dataGaName":1524,"dataGaLocation":1624},{"text":1667,"config":1668},"Status",{"href":1669,"dataGaName":1670,"dataGaLocation":1624},"https://status.gitlab.com/","status",{"text":1672,"config":1673},"Nutzungsbedingungen",{"href":1674,"dataGaName":1675,"dataGaLocation":1624},"/terms/","terms of use",{"text":1677,"config":1678},"Datenschutzerklärung",{"href":1679,"dataGaName":1680,"dataGaLocation":1624},"/de-de/privacy/","privacy statement",{"text":1682,"config":1683},"Cookie-Einstellungen",{"dataGaName":1684,"dataGaLocation":1624,"id":1685,"isOneTrustButton":263},"cookie preferences","ot-sdk-btn",{"title":1196,"links":1687,"subMenu":1701},[1688,1691,1693,1695,1697,1699],{"text":1689,"config":1690},"Plattform entdecken",{"href":1204,"dataGaName":1198,"dataGaLocation":1624},{"text":1256,"config":1692},{"href":1258,"dataGaName":1259,"dataGaLocation":1624},{"text":1210,"config":1694},{"href":1212,"dataGaName":1213,"dataGaLocation":1624},{"text":1261,"config":1696},{"href":1263,"dataGaName":1264,"dataGaLocation":1624},{"text":1243,"config":1698},{"href":1245,"dataGaName":1246,"dataGaLocation":1624},{"text":1274,"config":1700},{"href":1279,"dataGaName":1280,"dataGaLocation":1624},[1702],{"title":1703,"links":1704},"Themen",[1705,1709,1714,1719,1724,1729,1734,1739],{"text":1210,"config":1706},{"href":1707,"dataGaName":1708,"dataGaLocation":1624},"/de-de/topics/ci-cd/","cicd",{"text":1710,"config":1711},"GitOps",{"href":1712,"dataGaName":1713,"dataGaLocation":1624},"/de-de/topics/gitops/","gitops",{"text":1715,"config":1716},"DevOps",{"href":1717,"dataGaName":1718,"dataGaLocation":1624},"/de-de/topics/devops/","devops",{"text":1720,"config":1721},"Versionskontrolle",{"href":1722,"dataGaName":1723,"dataGaLocation":1624},"/de-de/topics/version-control/","version control",{"text":1725,"config":1726},"DevSecOps",{"href":1727,"dataGaName":1728,"dataGaLocation":1624},"/de-de/topics/devsecops/","devsecops",{"text":1730,"config":1731},"Cloud-nativ",{"href":1732,"dataGaName":1733,"dataGaLocation":1624},"/de-de/topics/cloud-native/","cloud native",{"text":1735,"config":1736},"KI für das Programmieren",{"href":1737,"dataGaName":1738,"dataGaLocation":1624},"/de-de/topics/devops/ai-for-coding/","ai for coding",{"text":1740,"config":1741},"Agentische KI",{"href":1742,"dataGaName":1743,"dataGaLocation":1624},"/de-de/topics/agentic-ai/","agentic ai",{"title":1282,"links":1745},[1746,1748,1750,1752,1754,1756,1758,1760,1762,1764,1767,1770,1772,1775,1779,1783],{"text":1295,"config":1747},{"href":1297,"dataGaName":1298,"dataGaLocation":1624},{"text":1300,"config":1749},{"href":1302,"dataGaName":1303,"dataGaLocation":1624},{"text":1305,"config":1751},{"href":1307,"dataGaName":1308,"dataGaLocation":1624},{"text":1331,"config":1753},{"href":1333,"dataGaName":1334,"dataGaLocation":1624},{"text":1336,"config":1755},{"href":1338,"dataGaName":1339,"dataGaLocation":1624},{"text":1341,"config":1757},{"href":1343,"dataGaName":1344,"dataGaLocation":1624},{"text":1346,"config":1759},{"href":1348,"dataGaName":1349,"dataGaLocation":1624},{"text":1351,"config":1761},{"href":1353,"dataGaName":1354,"dataGaLocation":1624},{"text":1356,"config":1763},{"href":1358,"dataGaName":1359,"dataGaLocation":1624},{"text":1765,"config":1766},"Enterprise",{"href":1315,"dataGaName":1316,"dataGaLocation":1624},{"text":1768,"config":1769},"Kleinunternehmen",{"href":1320,"dataGaName":1321,"dataGaLocation":1624},{"text":1323,"config":1771},{"href":1325,"dataGaName":1326,"dataGaLocation":1624},{"text":1710,"config":1773},{"href":1774,"dataGaName":1713,"dataGaLocation":1624},"/de-de/solutions/gitops/",{"text":1776,"config":1777},"Analyse der Softwarezusammensetzung (SCA)",{"href":1250,"dataGaName":1778,"dataGaLocation":1624},"software composition analysis",{"text":1780,"config":1781},"Wertstrommanagement",{"href":1268,"dataGaName":1782,"dataGaLocation":1624},"value stream management",{"text":1784,"config":1785},"Alle Lösungen",{"href":1289,"dataGaName":1786,"dataGaLocation":1624},"all solutions",{"title":1375,"links":1788},[1789,1794,1799,1801,1803,1805,1807,1809,1811,1813,1816,1818,1820,1822,1825],{"text":1790,"config":1791},"Installieren",{"href":1792,"dataGaName":1793,"dataGaLocation":1624},"/de-de/install/","install",{"text":1795,"config":1796},"Kurzanleitungen",{"href":1797,"dataGaName":1798,"dataGaLocation":1624},"/de-de/get-started/","quick setup checklists",{"text":1388,"config":1800},{"href":1390,"dataGaName":1391,"dataGaLocation":1624},{"text":1393,"config":1802},{"href":1395,"dataGaName":1396,"dataGaLocation":1624},{"text":1398,"config":1804},{"href":1400,"dataGaName":1401,"dataGaLocation":1624},{"text":1403,"config":1806},{"href":1405,"dataGaName":1406,"dataGaLocation":1624},{"text":1408,"config":1808},{"href":1410,"dataGaName":1411,"dataGaLocation":1624},{"text":1416,"config":1810},{"href":1418,"dataGaName":1419,"dataGaLocation":1624},{"text":1421,"config":1812},{"href":1423,"dataGaName":1424,"dataGaLocation":1624},{"text":1814,"config":1815},"Kund(inn)en",{"href":1428,"dataGaName":1429,"dataGaLocation":1624},{"text":1431,"config":1817},{"href":1433,"dataGaName":1434,"dataGaLocation":1624},{"text":1436,"config":1819},{"href":1438,"dataGaName":1439,"dataGaLocation":1624},{"text":1499,"config":1821},{"href":1501,"dataGaName":1502,"dataGaLocation":1624},{"text":1823,"config":1824},"Neuerungen",{"href":1447,"dataGaName":1448,"dataGaLocation":1624},{"text":1826,"config":1827},"Alle Ressourcen",{"href":1382,"dataGaName":1828,"dataGaLocation":1624},"all resources",{"title":1450,"links":1830},[1831,1833,1835,1837,1839,1841,1843,1845,1847,1852,1857],{"text":1458,"config":1832},{"href":1460,"dataGaName":1452,"dataGaLocation":1624},{"text":1463,"config":1834},{"href":1465,"dataGaName":1466,"dataGaLocation":1624},{"text":1469,"config":1836},{"href":1471,"dataGaName":1472,"dataGaLocation":1624},{"text":1474,"config":1838},{"href":1476,"dataGaName":1477,"dataGaLocation":1624},{"text":1479,"config":1840},{"href":1481,"dataGaName":1482,"dataGaLocation":1624},{"text":1484,"config":1842},{"href":1486,"dataGaName":1487,"dataGaLocation":1624},{"text":1489,"config":1844},{"href":1491,"dataGaName":1492,"dataGaLocation":1624},{"text":1494,"config":1846},{"href":1496,"dataGaName":1497,"dataGaLocation":1624},{"text":1848,"config":1849},"Nachhaltigkeit",{"href":1850,"dataGaName":1851,"dataGaLocation":1624},"/sustainability/","Sustainability",{"text":1853,"config":1854},"Vielfalt, Inklusion und Zugehörigkeit",{"href":1855,"dataGaName":1856,"dataGaLocation":1624},"/de-de/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1858,"config":1859},"Transparenzerklärung zu moderner Sklaverei",{"href":1860,"dataGaName":1861,"dataGaLocation":1624},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1863},[1864,1867,1870],{"text":1865,"config":1866},"Terms",{"href":1674,"dataGaName":1675,"dataGaLocation":1624},{"text":1868,"config":1869},"Cookies",{"dataGaName":1684,"dataGaLocation":1624,"id":1685,"isOneTrustButton":263},{"text":1871,"config":1872},"Datenschutz",{"href":1679,"dataGaName":1680,"dataGaLocation":1624},[1874],{"id":1875,"title":7,"body":1157,"config":1876,"content":1878,"description":1157,"extension":1883,"meta":1884,"navigation":263,"path":1885,"seo":1886,"stem":1887,"__hash__":1888},"blogAuthors/en-us/blog/authors/evan-baltman.yml",{"template":1877},"BlogAuthor",{"name":7,"config":1879},{"headshot":1880,"socialProof":1881},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1777579628/fkgn1kh0c1ndgba9yrkq.png",{"gitlabHandle":1882},"ebaltman","yml",{},"/en-us/blog/authors/evan-baltman",{},"en-us/blog/authors/evan-baltman","lIHS0uxztwtRrA-cy594VFaaYQp9r_oqQeUFF1B8eTU",[1890,1899,1905],{"title":1891,"description":1892,"heroImage":1893,"category":1153,"date":1894,"authors":1895,"slug":1898,"externalUrl":1157},"Kritische Codeausführung in DeepSeek-Reasonix mittels präparierter Git-Konfiguration","Warum Coding-Agenten der Git-Konfiguration fremder Repositorys nicht vertrauen sollten, zeigt eine kritische Lücke in DeepSeek-Reasonix.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782237704/cj50chkvprjthczevmog.png","2026-10-02",[1896,1897],"Abisheik Magesh","Daniel Abeles","deepseek-reasonix-vulnerability-discovered",{"title":1900,"description":1901,"heroImage":1893,"category":1153,"date":1902,"authors":1903,"slug":1904,"externalUrl":1157},"Kritische Remote Code Execution in der weit verbreiteten Node.js-Sandbox vm2","GitLabs Threat Research Group hat einen kritischen Sandbox Escape in vm2 gefunden – ausgelöst durch die dokumentierte Konfiguration der Bibliothek selbst.","2026-09-02",[1896,1897],"critical-remote-code-execution-in-vm2",{"title":1906,"description":1907,"heroImage":1893,"category":1153,"date":1908,"authors":1909,"slug":1910,"externalUrl":1157},"Kritische RCE-Schwachstelle in Serena, einem beliebten MCP-Coding-Agenten","Die Threat Research Group von GitLab hat in Serena eine kritische Template Injection gefunden, die beim Öffnen eines Repositorys fremden Code ausführt.","2026-08-17",[1897,1896],"critical-rce-in-serena",{"header":1912,"text":1913,"button":1917,"disclaimer":1920},"Kostenlose 30-tägige\n\nGitLab-Testversion starten\n",[1914,1915,1916],"GitLab Duo Agent Platform nutzen","Unsere fortschrittlichsten Funktionen ausprobieren","Komplexe Aufgaben mit KI automatisieren",{"text":1562,"config":1918},{"href":1919,"dataGaName":1183,"dataGaLocation":1419},"https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/de-de/blog/","Keine Kreditkarte erforderlich.",{"header":1922,"blurb":1923,"button":1924,"secondaryButton":1929},"Beginne noch heute, schneller zu entwickeln","Entdecke, was dein Team mit der intelligenten Orchestrierungsplattform für DevSecOps erreichen kann.\n",{"text":1925,"config":1926},"Kostenlosen Test starten",{"href":1927,"dataGaName":1183,"dataGaLocation":1928},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/de-de/","feature",{"text":1511,"config":1930},{"href":1513,"dataGaName":1188,"dataGaLocation":1928},1791952232104]