diff --git a/07-framework-security/cms/directus/INDEX.md b/07-framework-security/cms/directus/INDEX.md index 8d5af873..67797f16 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/cms/discourse/INDEX.md b/07-framework-security/cms/discourse/INDEX.md index 80fa2d5b..e786fed2 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/cms/drupal/INDEX.md b/07-framework-security/cms/drupal/INDEX.md index ed821cc1..f6dc0f6d 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/cms/ghost/INDEX.md b/07-framework-security/cms/ghost/INDEX.md index a10d492f..5724cc7d 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/cms/joomla/INDEX.md b/07-framework-security/cms/joomla/INDEX.md index 3e2d5ed4..5fdc29c8 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/cms/mediawiki/INDEX.md b/07-framework-security/cms/mediawiki/INDEX.md index e86778c4..ac92df6a 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/cms/moodle/INDEX.md b/07-framework-security/cms/moodle/INDEX.md index 3bbc35a7..0b696b17 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/cms/strapi/INDEX.md b/07-framework-security/cms/strapi/INDEX.md index 1a9daada..50d170b6 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/cms/wordpress/INDEX.md b/07-framework-security/cms/wordpress/INDEX.md index 0f7da579..c0850125 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/adobe-commerce/INDEX.md b/07-framework-security/ecommerce/adobe-commerce/INDEX.md index b085be40..4a269281 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+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 f4dc9236..5a1a4c94 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/medusa/INDEX.md b/07-framework-security/ecommerce/medusa/INDEX.md index fd7be24b..30cc55b6 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/opencart/INDEX.md b/07-framework-security/ecommerce/opencart/INDEX.md index 48cfd031..19ccaa36 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/openmage/INDEX.md b/07-framework-security/ecommerce/openmage/INDEX.md index fc8c21db..d107a165 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/prestashop/INDEX.md b/07-framework-security/ecommerce/prestashop/INDEX.md index f0586477..89e8a378 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/saleor/INDEX.md b/07-framework-security/ecommerce/saleor/INDEX.md index 4238c139..8fee89b3 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/shopware/INDEX.md b/07-framework-security/ecommerce/shopware/INDEX.md index ef50c5de..888acb84 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/ecommerce/woocommerce/INDEX.md b/07-framework-security/ecommerce/woocommerce/INDEX.md index c61819b1..53ffc810 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/angular/INDEX.md b/07-framework-security/frameworks/angular/INDEX.md index 07cce3d4..66a1eeeb 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/aspnet-core/INDEX.md b/07-framework-security/frameworks/aspnet-core/INDEX.md index 6bc120c0..b11983c1 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/astro/INDEX.md b/07-framework-security/frameworks/astro/INDEX.md index 221744e2..764bf4e1 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/django/INDEX.md b/07-framework-security/frameworks/django/INDEX.md index 6e33f724..772601de 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/echo/INDEX.md b/07-framework-security/frameworks/echo/INDEX.md index 13b63980..945bdc3b 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/esbuild/INDEX.md b/07-framework-security/frameworks/esbuild/INDEX.md index b33c0dd9..daa0b3d8 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/express/INDEX.md b/07-framework-security/frameworks/express/INDEX.md index 787a3e97..209eacc6 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/fastify/INDEX.md b/07-framework-security/frameworks/fastify/INDEX.md index 447b1861..7d60c8b6 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/flask/INDEX.md b/07-framework-security/frameworks/flask/INDEX.md index 64352714..14e5f92b 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/gin/INDEX.md b/07-framework-security/frameworks/gin/INDEX.md index fa0dbe52..bec788dd 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/hapi/INDEX.md b/07-framework-security/frameworks/hapi/INDEX.md index ab0d3f58..c77dee6e 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/koa/INDEX.md b/07-framework-security/frameworks/koa/INDEX.md index 1c2d57af..f22a5cc4 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/laravel/INDEX.md b/07-framework-security/frameworks/laravel/INDEX.md index f585fb5e..7ece308e 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/nestjs/INDEX.md b/07-framework-security/frameworks/nestjs/INDEX.md index 38a10436..52875476 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/nextjs/INDEX.md b/07-framework-security/frameworks/nextjs/INDEX.md index 53da1ddb..effbe677 100644 --- a/07-framework-security/frameworks/nextjs/INDEX.md +++ b/07-framework-security/frameworks/nextjs/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `0` - 待人工/缺浏览器证据: `26` -- 最近渲染时间: `2026-03-17T07:06:36+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/nodejs/INDEX.md b/07-framework-security/frameworks/nodejs/INDEX.md index 236fcdf0..92e5e274 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/nuxt/INDEX.md b/07-framework-security/frameworks/nuxt/INDEX.md index 40c550ad..83d653f7 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-17T07:06:36+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/rails/INDEX.md b/07-framework-security/frameworks/rails/INDEX.md index bcdc11b2..bd205c00 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/react/INDEX.md b/07-framework-security/frameworks/react/INDEX.md index fa1a99aa..2c7e0ae4 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-17T07:06:35+00:00` +- 最近渲染时间: `2026-03-17T07:27:10+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/spring-boot/INDEX.md b/07-framework-security/frameworks/spring-boot/INDEX.md index 763cf4ee..914c1138 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/spring-framework/INDEX.md b/07-framework-security/frameworks/spring-framework/INDEX.md index 6fc83470..01f71324 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/spring-security/INDEX.md b/07-framework-security/frameworks/spring-security/INDEX.md index 0c0a47f5..bd032cc9 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/sveltekit/INDEX.md b/07-framework-security/frameworks/sveltekit/INDEX.md index 653ed404..bb93dc07 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/symfony/INDEX.md b/07-framework-security/frameworks/symfony/INDEX.md index 8d842858..bdd30328 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/undici/INDEX.md b/07-framework-security/frameworks/undici/INDEX.md index 81ab019b..bd9a762d 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/vite/INDEX.md b/07-framework-security/frameworks/vite/INDEX.md index 17c15ba5..edc08fec 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-17T07:06:37+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/vue/INDEX.md b/07-framework-security/frameworks/vue/INDEX.md index 67123d7b..77df6373 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-17T07:06:36+00:00` +- 最近渲染时间: `2026-03-17T07:27:12+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/webpack/INDEX.md b/07-framework-security/frameworks/webpack/INDEX.md index a55840de..7e19b849 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/frameworks/werkzeug/INDEX.md b/07-framework-security/frameworks/werkzeug/INDEX.md index 1f45badf..6538e15d 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/adminer/INDEX.md b/07-framework-security/platforms/adminer/INDEX.md index 1f58eaab..81374b40 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/gitea/INDEX.md b/07-framework-security/platforms/gitea/INDEX.md index e95858f9..11858683 100644 --- a/07-framework-security/platforms/gitea/INDEX.md +++ b/07-framework-security/platforms/gitea/INDEX.md @@ -12,7 +12,7 @@ - 已实证(synthetic): `0` - 阻塞数: `1` - 待人工/缺浏览器证据: `36` -- 最近渲染时间: `2026-03-17T07:06:40+00:00` +- 最近渲染时间: `2026-03-17T07:27:15+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/gitlab-ce/INDEX.md b/07-framework-security/platforms/gitlab-ce/INDEX.md index e1460e81..e45c2e49 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-17T07:06:40+00:00` +- 最近渲染时间: `2026-03-17T07:27:15+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/grafana/INDEX.md b/07-framework-security/platforms/grafana/INDEX.md index 6bd1a324..4dbab379 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-17T07:06:40+00:00` +- 最近渲染时间: `2026-03-17T07:27:15+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/jenkins/INDEX.md b/07-framework-security/platforms/jenkins/INDEX.md index 47b1f634..597da6fe 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-17T07:06:40+00:00` +- 最近渲染时间: `2026-03-17T07:27:15+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/kibana/INDEX.md b/07-framework-security/platforms/kibana/INDEX.md index 0f52bbf2..e686ac84 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-17T07:06:40+00:00` +- 最近渲染时间: `2026-03-17T07:27:15+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/mattermost/INDEX.md b/07-framework-security/platforms/mattermost/INDEX.md index 8fc49ecc..2f2b05fa 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-17T07:06:40+00:00` +- 最近渲染时间: `2026-03-17T07:27:15+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/phpmyadmin/INDEX.md b/07-framework-security/platforms/phpmyadmin/INDEX.md index 1d8bce0d..490c3103 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/platforms/redmine/INDEX.md b/07-framework-security/platforms/redmine/INDEX.md index 5cb223e5..4e215142 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-17T07:06:40+00:00` +- 最近渲染时间: `2026-03-17T07:27:15+00:00` ## 目标约束 diff --git a/07-framework-security/servers/apache-httpd/INDEX.md b/07-framework-security/servers/apache-httpd/INDEX.md index d1e61bc3..ff6d9f98 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/servers/apache-tomcat/INDEX.md b/07-framework-security/servers/apache-tomcat/INDEX.md index 8875f4b9..89d6e826 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/servers/caddy/INDEX.md b/07-framework-security/servers/caddy/INDEX.md index a77400d4..48ad1fef 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/servers/haproxy/INDEX.md b/07-framework-security/servers/haproxy/INDEX.md index 9a0c8c5b..038f217a 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/servers/nginx/INDEX.md b/07-framework-security/servers/nginx/INDEX.md index 0524ef2c..7c3a3b12 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/07-framework-security/servers/traefik/INDEX.md b/07-framework-security/servers/traefik/INDEX.md index 3d8cf6ef..6efe75e8 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-17T07:06:38+00:00` +- 最近渲染时间: `2026-03-17T07:27:13+00:00` ## 目标约束 diff --git a/08-threat-intel/generated/dashboard/advisories.json b/08-threat-intel/generated/dashboard/advisories.json new file mode 100644 index 00000000..e6c43459 --- /dev/null +++ b/08-threat-intel/generated/dashboard/advisories.json @@ -0,0 +1,3558 @@ +{ + "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", + "summary": "Path Traversal 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-21T14:30:29Z", + "updated_at": "2026-03-03T04:50:06.638863Z", + "official_source_url": "https://github.com/advisories/GHSA-h3q4-vmw4-cpr5", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2021-29134", + "https://github.com/go-gitea/gitea/pull/15125/files", + "https://github.com/go-gitea/gitea/releases", + "https://github.com/go-gitea/gitea/releases/tag/v1.13.6" + ], + "aliases": [ + "BIT-gitea-2021-29134", + "CVE-2021-29134", + "GHSA-h3q4-vmw4-cpr5", + "GO-2022-0353" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "token-cookie-storage", + "proxy-trust-boundary", + "path-traversal-guard" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "gitea--CVE-2021-3382": { + "canonical_id": "gitea--CVE-2021-3382", + "title": "Buffer Overflow in gitea in code.gitea.io/gitea", + "summary": "Buffer Overflow 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-06-04T15:19:21Z", + "updated_at": "2026-03-03T04:55:15.307648Z", + "official_source_url": "https://github.com/advisories/GHSA-9f8c-pfvv-p4gm", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2021-3382", + "https://github.com/go-gitea/gitea/pull/14390" + ], + "aliases": [ + "BIT-gitea-2021-3382", + "CVE-2021-3382", + "GHSA-9f8c-pfvv-p4gm", + "GO-2024-2757" + ], + "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-45327": { + "canonical_id": "gitea--CVE-2021-45327", + "title": "Capture-replay in Gitea in code.gitea.io/gitea", + "summary": "Capture-replay 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-21T14:30:26Z", + "updated_at": "2026-03-03T04:52:07.840324Z", + "official_source_url": "https://github.com/advisories/GHSA-jrpg-35hw-m4p9", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2021-45327", + "https://blog.gitea.io/2020/03/gitea-1.11.2-is-released", + "https://github.com/go-gitea/gitea/commit/4cb18601ff33dda5edb47d5b452cc8f2dc39dd67", + "https://github.com/go-gitea/gitea/commit/6f5656ab0ebec03fe63898208dabc802c4be46ab", + "https://github.com/go-gitea/gitea/commit/ed664a9e1dae4d4660e60c981173bbc5102e69ea", + "https://github.com/go-gitea/gitea/pull/10462", + "https://github.com/go-gitea/gitea/pull/10465", + "https://github.com/go-gitea/gitea/pull/10582" + ], + "aliases": [ + "BIT-gitea-2021-45327", + "CVE-2021-45327", + "GHSA-jrpg-35hw-m4p9", + "GO-2022-0310" + ], + "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-45330": { + "canonical_id": "gitea--CVE-2021-45330", + "title": "Improper Privilege Management in Gitea in code.gitea.io/gitea", + "summary": "Improper Privilege Management 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-21T16:03:21Z", + "updated_at": "2026-03-03T04:52:33.136607Z", + "official_source_url": "https://github.com/advisories/GHSA-pg38-r834-g45j", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2021-45330", + "https://github.com/go-gitea/gitea/issues/4336", + "https://github.com/go-gitea/gitea/pull/4840" + ], + "aliases": [ + "BIT-gitea-2021-45330", + "CVE-2021-45330", + "GHSA-pg38-r834-g45j", + "GO-2022-0982" + ], + "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-45331": { + "canonical_id": "gitea--CVE-2021-45331", + "title": "Reuse of one time passwords allowed in Gitea in code.gitea.io/gitea", + "summary": "Reuse of one time passwords allowed 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-21T14:30:29Z", + "updated_at": "2026-03-03T04:52:07.604662Z", + "official_source_url": "https://github.com/advisories/GHSA-hfmf-q69j-6m5p", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2021-45331", + "https://blog.gitea.io/2018/08/gitea-1.5.0-is-released", + "https://github.com/go-gitea/gitea/pull/3878" + ], + "aliases": [ + "BIT-gitea-2021-45331", + "CVE-2021-45331", + "GHSA-hfmf-q69j-6m5p", + "GO-2022-0315" + ], + "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-2022-0905": { + "canonical_id": "gitea--CVE-2022-0905", + "title": "Gitea Missing Authorization vulnerability in code.gitea.io/gitea", + "summary": "Gitea Missing Authorization 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-21T15:11:40Z", + "updated_at": "2026-03-03T04:50:45.472605Z", + "official_source_url": "https://github.com/advisories/GHSA-jr9c-h74f-2v28", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-0905", + "https://github.com/go-gitea/gitea/commit/1314f38b59748397b3429fb9bc9f9d6bac85d2f2", + "https://github.com/go-gitea/gitea/commit/3e5c844a7758fa29126d201f4f98bf21bca6d314", + "https://huntr.dev/bounties/8d221f92-b2b1-4878-bc31-66ff272e5ceb" + ], + "aliases": [ + "BIT-gitea-2022-0905", + "CVE-2022-0905", + "GHSA-jr9c-h74f-2v28", + "GO-2022-0609" + ], + "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-2022-1058": { + "canonical_id": "gitea--CVE-2022-1058", + "title": "Gitea Open Redirect in code.gitea.io/gitea", + "summary": "Gitea Open Redirect in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2024-06-04T15:19:21Z", + "updated_at": "2026-03-03T04:51:49.844240Z", + "official_source_url": "https://github.com/advisories/GHSA-4rqq-rxvc-v2rc", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-1058", + "https://github.com/go-gitea/gitea/commit/e3d8e92bdc67562783de9a76b5b7842b68daeb48", + "https://github.com/go-gitea/gitea/pull/19175", + "https://github.com/go-gitea/gitea/pull/19186", + "https://huntr.dev/bounties/4fb42144-ac70-4f76-a5e1-ef6b5e55dc0d" + ], + "aliases": [ + "BIT-gitea-2022-1058", + "CVE-2022-1058", + "GHSA-4rqq-rxvc-v2rc", + "GO-2024-2752" + ], + "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-2022-1928": { + "canonical_id": "gitea--CVE-2022-1928", + "title": "Stored Cross-site Scripting in gitea in code.gitea.io/gitea", + "summary": "Stored 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:11:40Z", + "updated_at": "2026-03-03T04:50:45.577318Z", + "official_source_url": "https://github.com/advisories/GHSA-ph3w-2843-72mx", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-1928", + "https://github.com/go-gitea/gitea", + "https://github.com/go-gitea/gitea/commit/65e0688a5c9dacad50e71024b7529fdf0e3c2e9c", + "https://github.com/go-gitea/gitea/pull/19825", + "https://huntr.dev/bounties/6336ec42-5c4d-4f61-ae38-2bb539f433d2", + "https://security.gentoo.org/glsa/202210-14" + ], + "aliases": [ + "BIT-gitea-2022-1928", + "CVE-2022-1928", + "GHSA-ph3w-2843-72mx", + "GO-2022-0612" + ], + "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-2022-27313": { + "canonical_id": "gitea--CVE-2022-27313", + "title": "Arbitrary file deletion in gitea in code.gitea.io/gitea", + "summary": "Arbitrary file deletion 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:11:31Z", + "updated_at": "2026-03-03T04:50:19.647131Z", + "official_source_url": "https://github.com/advisories/GHSA-g7p7-x6w7-w6qg", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-27313", + "https://github.com/go-gitea/gitea/pull/19072", + "https://github.com/go-gitea/gitea/releases/tag/v1.16.4" + ], + "aliases": [ + "BIT-gitea-2022-27313", + "CVE-2022-27313", + "GHSA-g7p7-x6w7-w6qg", + "GO-2022-0442" + ], + "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-2022-30781": { + "canonical_id": "gitea--CVE-2022-30781", + "title": "Shell command injection in gitea in code.gitea.io/gitea", + "summary": "Shell command injection 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:11:31Z", + "updated_at": "2026-03-03T04:50:23.949796Z", + "official_source_url": "https://github.com/advisories/GHSA-p5f9-c9j9-g8qx", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-30781", + "http://packetstormsecurity.com/files/168400/Gitea-1.16.6-Remote-Code-Execution.html", + "http://packetstormsecurity.com/files/169928/Gitea-Git-Fetch-Remote-Code-Execution.html", + "https://blog.gitea.io/2022/05/gitea-1.16.7-is-released", + "https://github.com/go-gitea/gitea/pull/19487", + "https://github.com/go-gitea/gitea/pull/19490" + ], + "aliases": [ + "BIT-gitea-2022-30781", + "CVE-2022-30781", + "GHSA-p5f9-c9j9-g8qx", + "GO-2022-0450" + ], + "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-2022-38183": { + "canonical_id": "gitea--CVE-2022-38183", + "title": "Gitea allowed assignment of private issues in code.gitea.io/gitea", + "summary": "Gitea allowed assignment of private issues in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2024-06-10T16:38:54Z", + "updated_at": "2026-03-03T04:55:04.505871Z", + "official_source_url": "https://github.com/advisories/GHSA-fhv8-m4j4-cww2", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-38183", + "https://blog.gitea.io/2022/07/gitea-1.16.9-is-released", + "https://github.com/go-gitea/gitea/pull/20133", + "https://github.com/go-gitea/gitea/pull/20196", + "https://herolab.usd.de/security-advisories/usd-2022-0015" + ], + "aliases": [ + "BIT-gitea-2022-38183", + "CVE-2022-38183", + "GHSA-fhv8-m4j4-cww2", + "GO-2024-2769" + ], + "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-2022-38795": { + "canonical_id": "gitea--CVE-2022-38795", + "title": "Gitea erroneous repo clones in code.gitea.io/gitea", + "summary": "Gitea erroneous repo clones 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-21T14:17:52Z", + "updated_at": "2026-03-03T04:54:07.076900Z", + "official_source_url": "https://github.com/advisories/GHSA-8j3v-68w3-3848", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-38795", + "https://blog.gitea.com/release-of-1.17.2", + "https://github.com/go-gitea/gitea/pull/20869", + "https://github.com/go-gitea/gitea/pull/20892" + ], + "aliases": [ + "BIT-gitea-2022-38795", + "CVE-2022-38795", + "GHSA-8j3v-68w3-3848", + "GO-2023-1999" + ], + "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-2022-42968": { + "canonical_id": "gitea--CVE-2022-42968", + "title": "Gitea vulnerable to Argument Injection in code.gitea.io/gitea", + "summary": "Gitea vulnerable to Argument Injection 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-21T16:03:24Z", + "updated_at": "2026-03-03T04:52:41.181693Z", + "official_source_url": "https://github.com/advisories/GHSA-w8xw-7crf-h23x", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-42968", + "https://github.com/go-gitea/gitea/pull/21463", + "https://github.com/go-gitea/gitea/releases/tag/v1.17.3", + "https://security.gentoo.org/glsa/202210-14" + ], + "aliases": [ + "BIT-gitea-2022-42968", + "CVE-2022-42968", + "GHSA-w8xw-7crf-h23x", + "GO-2022-1065" + ], + "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-68938": { + "canonical_id": "gitea--CVE-2025-68938", + "title": "Gitea mishandles authorization for deletion of releases in code.gitea.io/gitea", + "summary": "Gitea mishandles authorization for deletion of releases 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:49.095775Z", + "official_source_url": "https://github.com/advisories/GHSA-cm54-pfmc-xrwx", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-68938", + "https://blog.gitea.com/release-of-1.25.2", + "https://github.com/go-gitea/gitea/pull/36002/commits/d4262131b39899d9e9ee5caa2635c810d476e43f#diff-8962bac89952027d50fa51f31f59d65bedb4c02bde0265eced5cf256cbed306d", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.2" + ], + "aliases": [ + "BIT-gitea-2025-68938", + "CVE-2025-68938", + "GHSA-cm54-pfmc-xrwx", + "GO-2025-4258" + ], + "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-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", + "summary": "Gitea mishandles access to a private resource upon receiving an API token with scope limited to public resources 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.339953Z", + "official_source_url": "https://github.com/advisories/GHSA-xfq3-qj7j-4565", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-68941", + "https://blog.gitea.com/release-of-1.22.3", + "https://github.com/go-gitea/gitea/pull/32218", + "https://github.com/go-gitea/gitea/releases/tag/v1.22.3" + ], + "aliases": [ + "BIT-gitea-2025-68941", + "CVE-2025-68941", + "GHSA-xfq3-qj7j-4565", + "GO-2025-4268" + ], + "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-68942": { + "canonical_id": "gitea--CVE-2025-68942", + "title": "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", + "summary": "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", + "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:49.781753Z", + "official_source_url": "https://github.com/advisories/GHSA-898p-hh3p-hf9r", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-68942", + "https://blog.gitea.com/release-of-1.22.2", + "https://github.com/go-gitea/gitea/pull/31966", + "https://github.com/go-gitea/gitea/releases/tag/v1.22.2" + ], + "aliases": [ + "BIT-gitea-2025-68942", + "CVE-2025-68942", + "GHSA-898p-hh3p-hf9r", + "GO-2025-4263" + ], + "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-2025-68943": { + "canonical_id": "gitea--CVE-2025-68943", + "title": "Gitea inadvertently discloses users' login times by allowing (for example) the lastlogintime explore/users sort order in code.gitea.io/gitea", + "summary": "Gitea inadvertently discloses users' login times by allowing (for example) the lastlogintime explore/users sort order 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:49.213758Z", + "official_source_url": "https://github.com/advisories/GHSA-jhx5-4vr4-f327", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-68943", + "https://blog.gitea.com/release-of-1.21.8-and-1.21.9-and-1.21.10", + "https://github.com/go-gitea/gitea/pull/29430", + "https://github.com/go-gitea/gitea/releases/tag/v1.21.8" + ], + "aliases": [ + "BIT-gitea-2025-68943", + "CVE-2025-68943", + "GHSA-jhx5-4vr4-f327", + "GO-2025-4266" + ], + "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-68944": { + "canonical_id": "gitea--CVE-2025-68944", + "title": "Gitea sometimes mishandles propagation of token scope for access control within one of its own package registries in code.gitea.io/gitea", + "summary": "Gitea sometimes mishandles propagation of token scope for access control within one of its own package registries 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.526913Z", + "official_source_url": "https://github.com/advisories/GHSA-f85h-c7m6-cfpm", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-68944", + "https://blog.gitea.com/release-of-1.22.2", + "https://github.com/go-gitea/gitea/pull/31967", + "https://github.com/go-gitea/gitea/releases/tag/v1.22.2" + ], + "aliases": [ + "BIT-gitea-2025-68944", + "CVE-2025-68944", + "GHSA-f85h-c7m6-cfpm", + "GO-2025-4264" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "token-cookie-storage", + "proxy-trust-boundary", + "dependency-upgrade-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "gitea--CVE-2025-68945": { + "canonical_id": "gitea--CVE-2025-68945", + "title": "Gitea: anonymous user can visit private user's project in code.gitea.io/gitea", + "summary": "Gitea: anonymous user can visit private user's project 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:51.457970Z", + "official_source_url": "https://github.com/advisories/GHSA-7xq4-mwcp-q8fx", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-68945", + "https://blog.gitea.com/release-of-1.21.2", + "https://github.com/go-gitea/gitea/pull/28423", + "https://github.com/go-gitea/gitea/releases/tag/v1.21.2" + ], + "aliases": [ + "BIT-gitea-2025-68945", + "CVE-2025-68945", + "GHSA-7xq4-mwcp-q8fx", + "GO-2025-4262" + ], + "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-68946": { + "canonical_id": "gitea--CVE-2025-68946", + "title": "Gitea vulnerable to Cross-site Scripting in code.gitea.io/gitea", + "summary": "Gitea vulnerable to Cross-site Scripting 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.473303Z", + "official_source_url": "https://github.com/advisories/GHSA-hq57-c72x-4774", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-68946", + "https://blog.gitea.com/release-of-1.20.1", + "https://github.com/go-gitea/gitea/pull/25960", + "https://github.com/go-gitea/gitea/releases/tag/v1.20.1" + ], + "aliases": [ + "BIT-gitea-2025-68946", + "CVE-2025-68946", + "GHSA-hq57-c72x-4774", + "GO-2025-4265" + ], + "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-2025-69413": { + "canonical_id": "gitea--CVE-2025-69413", + "title": "Gitea's /api/v1/user endpoint has different responses for failed authentication depending on whether a username exists in code.gitea.io/gitea", + "summary": "Gitea's /api/v1/user endpoint has different responses for failed authentication depending on whether a username exists in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-01-12T17:39:39Z", + "updated_at": "2026-03-03T04:57:49.801641Z", + "official_source_url": "https://github.com/advisories/GHSA-pc73-rj2c-wvf9", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-69413", + "https://blog.gitea.com/release-of-1.25.2", + "https://github.com/go-gitea/gitea/issues/35984", + "https://github.com/go-gitea/gitea/pull/36002", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.2" + ], + "aliases": [ + "BIT-gitea-2025-69413", + "CVE-2025-69413", + "GHSA-pc73-rj2c-wvf9", + "GO-2026-4274" + ], + "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-2026-0798": { + "canonical_id": "gitea--CVE-2026-0798", + "title": "Gitea may send release notification emails for private repositories to users whose access has been revoked in code.gitea.io/gitea", + "summary": "Gitea may send release notification emails for private repositories to users whose access has been revoked in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:54.518308Z", + "official_source_url": "https://github.com/advisories/GHSA-8fwc-qjw5-rvgp", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-0798", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/pull/36319", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-0798", + "CVE-2026-0798", + "GHSA-8fwc-qjw5-rvgp", + "GHSA-f4wq-6ww5-m56p", + "GO-2026-4365" + ], + "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-2026-20736": { + "canonical_id": "gitea--CVE-2026-20736", + "title": "Gitea has improper access control for uploaded attachments in code.gitea.io/gitea", + "summary": "Gitea has improper access control for uploaded attachments in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:53.977351Z", + "official_source_url": "https://github.com/advisories/GHSA-hgr3-x44x-33hx", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-20736", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/commit/fbea2c68e8df11cfa94e8ead913b79946780ed30", + "https://github.com/go-gitea/gitea/pull/36320", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-20736", + "CVE-2026-20736", + "GHSA-hgr3-x44x-33hx", + "GHSA-jr6h-pwwp-c8g6", + "GO-2026-4367" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "token-cookie-storage", + "proxy-trust-boundary", + "file-upload-validation" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "gitea--CVE-2026-20750": { + "canonical_id": "gitea--CVE-2026-20750", + "title": "Gitea does not properly validate project ownership in organization project operations in code.gitea.io/gitea", + "summary": "Gitea does not properly validate project ownership in organization project operations in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:57.697708Z", + "official_source_url": "https://github.com/advisories/GHSA-rw22-5hhq-pfpf", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-20750", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/commit/7b5de594cd92e30b9c3d40ffda119acad794cc64", + "https://github.com/go-gitea/gitea/pull/36318", + "https://github.com/go-gitea/gitea/pull/36373", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-20750", + "CVE-2026-20750", + "GHSA-h4fh-pc4w-8w27", + "GHSA-rw22-5hhq-pfpf", + "GO-2026-4370" + ], + "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-2026-20800": { + "canonical_id": "gitea--CVE-2026-20800", + "title": "Gitea improperly exposes issue and pull request titles in code.gitea.io/gitea", + "summary": "Gitea improperly exposes issue and pull request titles in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:54.012782Z", + "official_source_url": "https://github.com/advisories/GHSA-2vgv-hgv4-22mh", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-20800", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/commit/67e75f30a83d2523cedc37ad7b03bcba66947833", + "https://github.com/go-gitea/gitea/pull/36339", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-20800", + "CVE-2026-20800", + "GHSA-2vgv-hgv4-22mh", + "GHSA-g54m-9f6g-wj7q", + "GO-2026-4362" + ], + "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-2026-20883": { + "canonical_id": "gitea--CVE-2026-20883", + "title": "Gitea improperly exposes issue titles and repository names through previously started stopwatches in code.gitea.io/gitea", + "summary": "Gitea improperly exposes issue titles and repository names through previously started stopwatches in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:54.692700Z", + "official_source_url": "https://github.com/advisories/GHSA-j8xr-c56q-m8jj", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-20883", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/commit/95ea2df00a70176c516b12f3cfee8c84a310280f", + "https://github.com/go-gitea/gitea/pull/36340", + "https://github.com/go-gitea/gitea/pull/36368", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-20883", + "CVE-2026-20883", + "GHSA-644v-xv3j-xgqg", + "GHSA-j8xr-c56q-m8jj", + "GO-2026-4368" + ], + "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-2026-20888": { + "canonical_id": "gitea--CVE-2026-20888", + "title": "Gitea does not properly verify authorization when canceling scheduled auto-merges via the web interface in code.gitea.io/gitea", + "summary": "Gitea does not properly verify authorization when canceling scheduled auto-merges via the web interface in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:56.025932Z", + "official_source_url": "https://github.com/advisories/GHSA-9cgq-wp42-4rpq", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-20888", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/pull/36341", + "https://github.com/go-gitea/gitea/pull/36356", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-20888", + "CVE-2026-20888", + "GHSA-9cgq-wp42-4rpq", + "GHSA-ccq9-c5hv-cf64", + "GO-2026-4366" + ], + "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-2026-20897": { + "canonical_id": "gitea--CVE-2026-20897", + "title": "Gitea does not properly validate repository ownership when deleting Git LFS locks in code.gitea.io/gitea", + "summary": "Gitea does not properly validate repository ownership when deleting Git LFS locks in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:55.339967Z", + "official_source_url": "https://github.com/advisories/GHSA-393c-qgvj-3xph", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-20897", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/commit/da036f3f35ca830b22cf4480912ed261303b798f", + "https://github.com/go-gitea/gitea/pull/36344", + "https://github.com/go-gitea/gitea/pull/36349", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-20897", + "CVE-2026-20897", + "GHSA-393c-qgvj-3xph", + "GHSA-rrq5-r9h5-pc7c", + "GO-2026-4363" + ], + "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-2026-20904": { + "canonical_id": "gitea--CVE-2026-20904", + "title": "Gitea does not properly validate ownership when toggling OpenID URI visibility in code.gitea.io/gitea", + "summary": "Gitea does not properly validate ownership when toggling OpenID URI visibility in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:54.244003Z", + "official_source_url": "https://github.com/advisories/GHSA-qqgv-v353-cv8p", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-20904", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/commit/ed5720af2ac94d74f822721c05b42b6148ff9c22", + "https://github.com/go-gitea/gitea/pull/36346", + "https://github.com/go-gitea/gitea/pull/36361", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-20904", + "CVE-2026-20904", + "GHSA-jrpc-w85r-hgqx", + "GHSA-qqgv-v353-cv8p", + "GO-2026-4369" + ], + "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-2026-20912": { + "canonical_id": "gitea--CVE-2026-20912", + "title": "Gitea does not properly validate repository ownership when linking attachments to releases in code.gitea.io/gitea", + "summary": "Gitea does not properly validate repository ownership when linking attachments to releases in code.gitea.io/gitea", + "display_name": "Gitea", + "system_id": "gitea", + "category": "platforms", + "severity": "unknown", + "cvss_score": null, + "exploit_status": "unknown", + "published_at": "2026-02-02T21:05:55Z", + "updated_at": "2026-03-03T04:57:55.747880Z", + "official_source_url": "https://github.com/advisories/GHSA-4xx9-vc8v-87hv", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2026-20912", + "https://blog.gitea.com/release-of-1.25.4", + "https://github.com/go-gitea/gitea/commit/fbea2c68e8df11cfa94e8ead913b79946780ed30", + "https://github.com/go-gitea/gitea/pull/36320", + "https://github.com/go-gitea/gitea/pull/36355", + "https://github.com/go-gitea/gitea/releases/tag/v1.25.4" + ], + "aliases": [ + "BIT-gitea-2026-20912", + "CVE-2026-20912", + "GHSA-4xx9-vc8v-87hv", + "GHSA-vfmv-f93v-37mw", + "GO-2026-4364" + ], + "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": [] + } + }, + "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", + "summary": "### Impact\n\n- **Not affected**: Deployments on ZEIT Now v2 ([https://zeit.co](https://zeit.co/)) are not affected\n- **Not affected**: Deployments using the `serverless` target\n- **Not affected**: Deployments using `next export`\n- **Affected**: Users of Next.js below 9.3.2\n\nWe recommend everyone to upgrade regardless of whether you can reproduce the issue or not.\n\n### Patches\n\nhttps://github.com/zeit/next.js/releases/tag/v9.3.2\n\n### References\n\nhttps://github.com/zeit/next.js/releases/tag/v9.3.2", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2020-03-30T20:40:50Z", + "updated_at": "2025-09-26T17:49:56Z", + "official_source_url": "https://github.com/zeit/next.js/security/advisories/GHSA-fq77-7p7r-83rj", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2020-5284", + "https://github.com/zeit/next.js/releases/tag/v9.3.2", + "https://www.npmjs.com/advisories/1503" + ], + "aliases": [ + "CVE-2020-5284", + "GHSA-fq77-7p7r-83rj" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "path-traversal-guard" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--CVE-2021-37699": { + "canonical_id": "nextjs--CVE-2021-37699", + "title": "Open Redirect in Next.js", + "summary": "Next.js is an open source website development framework to be used with the React library. In affected versions specially encoded paths could be used when `pages/_error.js` was statically generated, allowing an open redirect to occur to an external site. In general, this redirect does not directly harm users although it can allow for phishing attacks by redirecting to an attacker's domain from a trusted domain.\n\n### Impact\n\n- **Affected:** Users of Next.js between `10.0.5` and `10.2.0`\n- **Affected:** Users of Next.js between `11.0.0` and `11.0.1` using `pages/_error.js` without `getInitialProps`\n- **Affected:** Users of Next.js between `11.0.0` and `11.0.1` using `pages/_error.js` and `next export`\n- **Not affected**: Deployments on Vercel ([vercel.com](https://vercel.com)) are not affected\n- **Not affected:** Deployments **with** `pages/404.js`\n- Note that versions prior to 0.9.9 package `next` npm package hosted a different utility (0.4.1 being the latest version of that codebase), and this advisory does not apply to those versions.\n\nWe recommend upgrading to the latest version of Next.js to improve the overall security of your application.\n\n### Patches\n\nhttps://github.com/vercel/next.js/releases/tag/v11.1.0", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2021-08-12T14:51:14Z", + "updated_at": "2026-03-13T22:00:08.038285Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-vxf5-wxwp-m7g9", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2021-37699", + "https://github.com/vercel/next.js", + "https://github.com/vercel/next.js/releases/tag/v11.1.0" + ], + "aliases": [ + "CVE-2021-37699", + "GHSA-vxf5-wxwp-m7g9" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "dependency-upgrade-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--CVE-2021-39178": { + "canonical_id": "nextjs--CVE-2021-39178", + "title": "XSS in Image Optimization API for Next.js", + "summary": "### Impact\n- **Affected:** All of the following must be true to be affected\n - Next.js between version 10.0.0 and 11.1.0\n - The `next.config.js` file has [`images.domains`](https://nextjs.org/docs/basic-features/image-optimization#domains) array assigned\n - The image host assigned in [`images.domains`](https://nextjs.org/docs/basic-features/image-optimization#domains) allows user-provided SVG\n- **Not affected**: The `next.config.js` file has [`images.loader`](https://nextjs.org/docs/basic-features/image-optimization#loader) assigned to something other than default\n- **Not affected**: Deployments on [Vercel](https://vercel.com) are not affected\n\n### Patches\n[Next.js v11.1.1](https://github.com/vercel/next.js/releases/tag/v11.1.1)\n\n", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2021-09-01T18:24:22Z", + "updated_at": "2026-03-13T22:00:20.154452Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-9gr3-7897-pp7m", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2021-39178", + "https://github.com/vercel/next.js/pull/28620", + "https://github.com/vercel/next.js/commit/7afc97c5744b38bdf36aa7f87625f438224688aa", + "https://github.com/vercel/next.js", + "https://github.com/vercel/next.js/releases/tag/v11.1.1" + ], + "aliases": [ + "CVE-2021-39178", + "GHSA-9gr3-7897-pp7m" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "xss-output-encoding" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--CVE-2021-43803": { + "canonical_id": "nextjs--CVE-2021-43803", + "title": "Unexpected server crash in Next.js.", + "summary": "Next.js is a React framework. In versions of Next.js prior to 12.0.5 or 11.1.3, invalid or malformed URLs could lead to a server crash. In order to be affected by this issue, the deployment must use Next.js versions above 11.1.0 and below 12.0.5, Node.js above 15.0.0, and next start or a custom server. Deployments on Vercel are not affected, along with similar environments where invalid requests are filtered before reaching Next.js. Versions 12.0.5 and 11.1.3 contain patches for this issue. Note that prior version 0.9.9 package `next` hosted a different utility (0.4.1 being the latest version of that codebase), and this advisory does not apply to those versions. ", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2021-12-07T21:12:09Z", + "updated_at": "2026-03-13T22:00:36.554552Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-25mp-g6fv-mqxx", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2021-43803", + "https://github.com/vercel/next.js/pull/32080", + "https://github.com/vercel/next.js/commit/6d98b4fb4315dec1badecf0e9bdc212a4272b264", + "https://github.com/vercel/next.js", + "https://github.com/vercel/next.js/releases/tag/v11.1.3", + "https://github.com/vercel/next.js/releases/v12.0.5" + ], + "aliases": [ + "CVE-2021-43803", + "GHSA-25mp-g6fv-mqxx" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "dependency-upgrade-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--CVE-2024-34351": { + "canonical_id": "nextjs--CVE-2024-34351", + "title": "Next.js Server-Side Request Forgery in Server Actions", + "summary": "### Impact\nA Server-Side Request Forgery (SSRF) vulnerability was identified in Next.js Server Actions by security researchers at Assetnote. If the `Host` header is modified, and the below conditions are also met, an attacker may be able to make requests that appear to be originating from the Next.js application server itself.\n\n#### Prerequisites\n* Next.js (`<14.1.1`) is running in a self-hosted* manner.\n* The Next.js application makes use of Server Actions.\n* The Server Action performs a redirect to a relative path which starts with a `/`.\n\n\\* Many hosting providers (including Vercel) route requests based on the Host header, so we do not believe that this vulnerability affects any Next.js applications where routing is done in this manner.\n\n### Patches\nThis vulnerability was patched in [#62561](https://github.com/vercel/next.js/pull/62561) and fixed in Next.js `14.1.1`.\n \n### Workarounds\nThere are no official workarounds for this vulnerability. We recommend upgrading to Next.js `14.1.1`.\n\n### Credit\nVercel and the Next.js team thank Assetnote for responsibly disclosing this issue to us, and for working with us to verify the fix. Thanks to:\n\nAdam Kues - Assetnote\nShubham Shah - Assetnote", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2024-05-09T21:18:57Z", + "updated_at": "2026-02-04T03:32:36.434669Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-fr5h-rqp8-mj6g", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2024-34351", + "https://github.com/vercel/next.js/pull/62561", + "https://github.com/vercel/next.js/commit/8f7a6ca7d21a97bc9f7a1bbe10427b5ad74b9085", + "https://github.com/vercel/next.js" + ], + "aliases": [ + "CVE-2024-34351", + "GHSA-fr5h-rqp8-mj6g" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "ssrf-url-validation" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--CVE-2024-46982": { + "canonical_id": "nextjs--CVE-2024-46982", + "title": "Next.js Cache Poisoning", + "summary": "### Impact\n\nBy sending a crafted HTTP request, it is possible to poison the cache of a non-dynamic server-side rendered route in the pages router (this does not affect the app router). When this crafted request is sent it could coerce Next.js to cache a route that is meant to not be cached and send a `Cache-Control: s-maxage=1, stale-while-revalidate` header which some upstream CDNs may cache as well. \n\nTo be potentially affected all of the following must apply: \n\n- Next.js between 13.5.1 and 14.2.9\n- Using pages router\n- Using non-dynamic server-side rendered routes e.g. `pages/dashboard.tsx` not `pages/blog/[slug].tsx`\n\nThe below configurations are unaffected:\n\n- Deployments using only app router\n- Deployments on [Vercel](https://vercel.com/) are not affected\n\n\n### Patches\n\nThis vulnerability was resolved in Next.js v13.5.7, v14.2.10, and later. We recommend upgrading regardless of whether you can reproduce the issue or not.\n\n### Workarounds\n\nThere are no official or recommended workarounds for this issue, we recommend that users patch to a safe version.\n\n#### Credits\n\n- Allam Rachid (zhero_)\n- Henry Chen", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2024-09-17T21:58:09Z", + "updated_at": "2026-02-04T03:45:33.402195Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-gp8f-8m3g-qvj9", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2024-46982", + "https://github.com/vercel/next.js/commit/7ed7f125e07ef0517a331009ed7e32691ba403d3", + "https://github.com/vercel/next.js/commit/bd164d53af259c05f1ab434004bcfdd3837d7cda", + "https://github.com/vercel/next.js" + ], + "aliases": [ + "CVE-2024-46982", + "GHSA-gp8f-8m3g-qvj9" + ], + "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-2024-47831": { + "canonical_id": "nextjs--CVE-2024-47831", + "title": "Denial of Service condition in Next.js image optimization", + "summary": "### Impact\nThe image optimization feature of Next.js contained a vulnerability which allowed for a potential Denial of Service (DoS) condition which could lead to excessive CPU consumption.\n\n**Not affected:**\n- The `next.config.js` file is configured with `images.unoptimized` set to `true` or `images.loader` set to a non-default value.\n- The Next.js application is hosted on Vercel. \n\n### Patches\nThis issue was fully patched in Next.js `14.2.7`. We recommend that users upgrade to at least this version.\n\n### Workarounds\nEnsure that the `next.config.js` file has either `images.unoptimized`, `images.loader` or `images.loaderFile` assigned.\n\n#### Credits\nBrandon Dahler (brandondahler), AWS\nDimitrios Vlastaras", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2024-10-14T19:45:21Z", + "updated_at": "2026-02-04T03:25:43.295558Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-g77x-44xx-532m", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2024-47831", + "https://github.com/vercel/next.js/commit/d11cbc9ff0b1aaefabcba9afe1e562e0b1fde65a", + "https://github.com/vercel/next.js" + ], + "aliases": [ + "CVE-2024-47831", + "GHSA-g77x-44xx-532m" + ], + "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-2024-51479": { + "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": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--CVE-2024-56332": { + "canonical_id": "nextjs--CVE-2024-56332", + "title": "Next.js Allows a Denial of Service (DoS) with Server Actions", + "summary": "### Impact\nA Denial of Service (DoS) attack allows attackers to construct requests that leaves requests to Server Actions hanging until the hosting provider cancels the function execution.\n\n_Note: Next.js server is idle during that time and only keeps the connection open. CPU and memory footprint are low during that time._\n\nDeployments without any protection against long running Server Action invocations are especially vulnerable. Hosting providers like Vercel or Netlify set a default maximum duration on function execution to reduce the risk of excessive billing.\n\nThis is the same issue as if the incoming HTTP request has an invalid `Content-Length` header or never closes. If the host has no other mitigations to those then this vulnerability is novel.\n\nThis vulnerability affects only Next.js deployments using Server Actions.\n\n### Patches\n\nThis vulnerability was resolved in Next.js 14.2.21, 15.1.2, and 13.5.8. We recommend that users upgrade to a safe version.\n\n### Workarounds\n\nThere are no official workarounds for this vulnerability.\n\n### Credits\n\nThanks to the PackDraw team for responsibly disclosing this vulnerability.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-01-03T20:19:29Z", + "updated_at": "2026-02-04T04:36:04.252972Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-7m27-7ghc-44w9", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2024-56332", + "https://github.com/vercel/next.js" + ], + "aliases": [ + "CVE-2024-56332", + "GHSA-7m27-7ghc-44w9" + ], + "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-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", + "summary": "## Summary\nIn the process of remediating [CVE-2025-29927](https://github.com/advisories/GHSA-f82v-jwr5-mffw), we looked at other possible exploits of Middleware. We independently verified this low severity vulnerability in parallel with two reports from independent researchers.\n\nLearn more [here](https://vercel.com/changelog/cve-2025-30218-5DREmEH765PoeAsrNNQj3O).\n\n## Credit\n\nThank you to Jinseo Kim [kjsman](https://hackerone.com/kjsman?type=user) and\u00a0[RyotaK](https://hackerone.com/ryotak?type=user) (GMO Flatt Security Inc.) with [takumi-san.ai](https://takumi-san.ai)\u00a0for the responsible disclosure. These researchers were awarded as part of our bug bounty program.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "medium", + "cvss_score": 4.0, + "exploit_status": "unknown", + "published_at": "2025-04-02T22:35:37Z", + "updated_at": "2025-10-13T15:35:50Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-223j-4rm8-mrmf", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-30218", + "https://github.com/vercel/next.js", + "https://vercel.com/changelog/cve-2025-30218-5DREmEH765PoeAsrNNQj3O" + ], + "aliases": [ + "CVE-2025-30218", + "GHSA-223j-4rm8-mrmf" + ], + "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-2025-32421": { + "canonical_id": "nextjs--CVE-2025-32421", + "title": "Next.js Race Condition to Cache Poisoning", + "summary": "**Summary** \nWe received a responsible disclosure from Allam Rachid (zhero) for a low-severity race-condition vulnerability in Next.js. This issue only affects the **Pages Router** under certain misconfigurations, causing normal endpoints to serve `pageProps` data instead of standard HTML.\n\n[Learn more here](https://vercel.com/changelog/cve-2025-32421)\n\n**Credit** \nThank you to **Allam Rachid (zhero)** for the responsible disclosure. This research was rewarded as part of our bug bounty program.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-05-15T14:12:26Z", + "updated_at": "2025-09-26T17:48:29Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-qpjv-v59x-3qc4", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-32421", + "https://github.com/vercel/next.js", + "https://vercel.com/changelog/cve-2025-32421" + ], + "aliases": [ + "CVE-2025-32421", + "GHSA-qpjv-v59x-3qc4" + ], + "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-2025-48068": { + "canonical_id": "nextjs--CVE-2025-48068", + "title": "Information exposure in Next.js dev server due to lack of origin verification", + "summary": "## Summary\n\nA low-severity vulnerability in **Next.js** has been fixed in **version 15.2.2**. This issue may have allowed limited source code exposure when the dev server was running with the App Router enabled. The vulnerability only affects local development environments and requires the user to visit a malicious webpage while `npm run dev` is active.\n\nBecause the mitigation is potentially a breaking change for some development setups, to opt-in to the fix, you must configure `allowedDevOrigins` in your next config after upgrading to a patched version. [Learn more](https://nextjs.org/docs/app/api-reference/config/next-config-js/allowedDevOrigins).\n\nLearn more: https://vercel.com/changelog/cve-2025-48068\n\n## Credit\n\nThanks to [sapphi-red](https://github.com/sapphi-red) and [Radman Siddiki](https://github.com/R4356th) for responsibly disclosing this issue.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "medium", + "cvss_score": 4.0, + "exploit_status": "unknown", + "published_at": "2025-05-28T21:52:13Z", + "updated_at": "2025-06-13T14:41:21Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-3h52-269p-cp9r", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-48068", + "https://github.com/vercel/next.js", + "https://vercel.com/changelog/cve-2025-48068" + ], + "aliases": [ + "CVE-2025-48068", + "GHSA-3h52-269p-cp9r" + ], + "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-2025-49005": { + "canonical_id": "nextjs--CVE-2025-49005", + "title": "Next.js has a Cache poisoning vulnerability due to omission of the Vary header", + "summary": "### Summary\n\nA cache poisoning issue in **Next.js App Router >=15.3.0 and < 15.3.3** may have allowed RSC payloads to be cached and served in place of HTML, under specific conditions involving middleware and redirects. This issue has been fixed in **Next.js 15.3.3**.\n\nUsers on affected versions should **upgrade immediately** and **redeploy** to ensure proper caching behavior.\n\nMore details: [CVE-2025-49005](https://vercel.com/changelog/cve-2025-49005)", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-07-03T20:30:18Z", + "updated_at": "2026-02-04T02:37:18.974477Z", + "official_source_url": "https://github.com/vercel/next.js/security/advisories/GHSA-r2fc-ccr8-96c4", + "secondary_source_urls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-49005", + "https://github.com/vercel/next.js/issues/79346", + "https://github.com/vercel/next.js/pull/79939", + "https://github.com/vercel/next.js/commit/ec202eccf05820b60c6126d6411fe16766ecc066", + "https://github.com/vercel/next.js", + "https://github.com/vercel/next.js/releases/tag/v15.3.3", + "https://vercel.com/changelog/cve-2025-49005" + ], + "aliases": [ + "CVE-2025-49005", + "GHSA-r2fc-ccr8-96c4" + ], + "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-2025-49826": { + "canonical_id": "nextjs--CVE-2025-49826", + "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)", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-07-03T21:14:48Z", + "updated_at": "2025-07-03T21:49:52Z", + "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" + ], + "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-2025-55173": { + "canonical_id": "nextjs--CVE-2025-55173", + "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)", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-08-29T21:59:55Z", + "updated_at": "2026-02-04T04:35:34.538107Z", + "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" + ], + "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-2025-57752": { + "canonical_id": "nextjs--CVE-2025-57752", + "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)", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-08-29T22:06:22Z", + "updated_at": "2026-02-04T02:50:08.291668Z", + "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" + ], + "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-2025-57822": { + "canonical_id": "nextjs--CVE-2025-57822", + "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)", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-08-29T21:33:09Z", + "updated_at": "2026-02-04T04:20:45.658010Z", + "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" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "ssrf-url-validation" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--CVE-2025-59471": { + "canonical_id": "nextjs--CVE-2025-59471", + "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.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-01-27T19:18:25Z", + "updated_at": "2026-02-10T01:28:46.973023Z", + "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" + ], + "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-2025-59472": { + "canonical_id": "nextjs--CVE-2025-59472", + "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.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-01-28T15:20:55Z", + "updated_at": "2026-02-06T13:13:43.709252Z", + "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" + ], + "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--GHSA-5j59-xgg2-r9c4": { + "canonical_id": "nextjs--GHSA-5j59-xgg2-r9c4", + "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.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-12-12T17:21:57Z", + "updated_at": "2026-02-04T02:46:38.768104Z", + "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" + ], + "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--GHSA-9qr9-h5gf-34mp": { + "canonical_id": "nextjs--GHSA-9qr9-h5gf-34mp", + "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", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-12-03T19:07:11Z", + "updated_at": "2026-02-04T03:45:15.823345Z", + "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" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "dependency-upgrade-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--GHSA-h25m-26qc-wcjf": { + "canonical_id": "nextjs--GHSA-h25m-26qc-wcjf", + "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.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-01-28T15:38:01Z", + "updated_at": "2026-02-13T00:43:52.836085Z", + "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" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "dependency-upgrade-policy", + "deserialization-safety" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--GHSA-mwv6-3258-q52c": { + "canonical_id": "nextjs--GHSA-mwv6-3258-q52c", + "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.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-12-11T22:49:27Z", + "updated_at": "2026-02-04T03:55:54.855562Z", + "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" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "dependency-upgrade-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "nextjs--GHSA-w37m-7fhw-fmv9": { + "canonical_id": "nextjs--GHSA-w37m-7fhw-fmv9", + "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.", + "display_name": "Next.js", + "system_id": "nextjs", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-12-11T22:49:56Z", + "updated_at": "2026-02-04T02:51:40.627151Z", + "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" + ], + "secure_code_topics": [ + "authz-server-side-recheck", + "proxy-trust-boundary", + "token-cookie-storage", + "dependency-upgrade-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2022-31151": { + "canonical_id": "undici--CVE-2022-31151", + "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", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2022-07-21T20:31:05Z", + "updated_at": "2026-02-04T03:02:08.652391Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary", + "token-cookie-storage", + "dependency-upgrade-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2022-32210": { + "canonical_id": "undici--CVE-2022-32210", + "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.", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2022-06-17T01:02:29Z", + "updated_at": "2026-03-13T22:15:23.541247Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2023-45143": { + "canonical_id": "undici--CVE-2023-45143", + "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", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2023-10-16T14:05:37Z", + "updated_at": "2026-02-04T02:35:56.289390Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "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": [] + } + }, + "undici--CVE-2024-30260": { + "canonical_id": "undici--CVE-2024-30260", + "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", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2024-04-04T14:20:39Z", + "updated_at": "2025-11-04T19:44:28Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2024-30261": { + "canonical_id": "undici--CVE-2024-30261", + "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", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2024-04-04T14:20:54Z", + "updated_at": "2025-11-04T19:44:42Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2025-22150": { + "canonical_id": "undici--CVE-2025-22150", + "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", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-01-21T21:10:47Z", + "updated_at": "2026-02-04T02:29:26.373390Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2025-47279": { + "canonical_id": "undici--CVE-2025-47279", + "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", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-05-15T14:15:06Z", + "updated_at": "2026-02-06T22:08:08.311705Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2026-1525": { + "canonical_id": "undici--CVE-2026-1525", + "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", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-03-13T20:07:03Z", + "updated_at": "2026-03-14T09:19:54.772219Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary", + "request-smuggling-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2026-1526": { + "canonical_id": "undici--CVE-2026-1526", + "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.", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-03-13T20:41:56Z", + "updated_at": "2026-03-13T20:54:25.563997Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary", + "plugin-extension-trust-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2026-1527": { + "canonical_id": "undici--CVE-2026-1527", + "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```", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-03-13T20:41:26Z", + "updated_at": "2026-03-13T20:54:25.572106Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2026-1528": { + "canonical_id": "undici--CVE-2026-1528", + "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.", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-03-13T20:07:26Z", + "updated_at": "2026-03-14T09:17:45.838435Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2026-22036": { + "canonical_id": "undici--CVE-2026-22036", + "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", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-01-14T21:06:08Z", + "updated_at": "2026-02-04T02:56:17.456091Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2026-2229": { + "canonical_id": "undici--CVE-2026-2229", + "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?_", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-03-13T20:41:41Z", + "updated_at": "2026-03-13T20:54:26.149214Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary", + "plugin-extension-trust-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "undici--CVE-2026-2581": { + "canonical_id": "undici--CVE-2026-2581", + "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.", + "display_name": "Undici", + "system_id": "undici", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2026-03-13T20:37:58Z", + "updated_at": "2026-03-13T20:54:25.417862Z", + "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" + ], + "secure_code_topics": [ + "ssrf-url-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2024-23331": { + "canonical_id": "vite--CVE-2024-23331", + "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", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2024-01-19T21:58:47Z", + "updated_at": "2026-02-04T04:17:01.410592Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2024-45811": { + "canonical_id": "vite--CVE-2024-45811", + "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", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2024-09-17T18:44:12Z", + "updated_at": "2026-02-04T04:05:31.919291Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2024-45812": { + "canonical_id": "vite--CVE-2024-45812", + "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```", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2024-09-17T19:28:01Z", + "updated_at": "2026-02-04T04:04:22.977459Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary", + "xss-output-encoding", + "plugin-extension-trust-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-24010": { + "canonical_id": "vite--CVE-2025-24010", + "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", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-01-21T19:52:55Z", + "updated_at": "2026-02-04T04:37:03.076966Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary", + "dom-sink-hardening", + "token-cookie-storage", + "plugin-extension-trust-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-30208": { + "canonical_id": "vite--CVE-2025-30208", + "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```", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-03-25T14:00:02Z", + "updated_at": "2026-02-04T03:13:24.371631Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-31125": { + "canonical_id": "vite--CVE-2025-31125", + "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`", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-03-31T17:31:54Z", + "updated_at": "2026-02-04T04:37:24.129476Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-31486": { + "canonical_id": "vite--CVE-2025-31486", + "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```", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "low", + "cvss_score": 3.1, + "exploit_status": "unknown", + "published_at": "2025-04-04T14:20:05Z", + "updated_at": "2026-02-04T03:51:38.412061Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary", + "plugin-extension-trust-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-32395": { + "canonical_id": "vite--CVE-2025-32395", + "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```", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "medium", + "cvss_score": 4.0, + "exploit_status": "unknown", + "published_at": "2025-04-11T14:06:03Z", + "updated_at": "2026-02-04T04:11:44.900383Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-46565": { + "canonical_id": "vite--CVE-2025-46565", + "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)", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "medium", + "cvss_score": 4.0, + "exploit_status": "unknown", + "published_at": "2025-04-30T17:40:27Z", + "updated_at": "2026-02-04T03:27:17.681639Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-58751": { + "canonical_id": "vite--CVE-2025-58751", + "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", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "medium", + "cvss_score": 4.0, + "exploit_status": "unknown", + "published_at": "2025-09-09T20:55:56Z", + "updated_at": "2026-02-04T04:33:22.508417Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-58752": { + "canonical_id": "vite--CVE-2025-58752", + "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.", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "medium", + "cvss_score": 4.0, + "exploit_status": "unknown", + "published_at": "2025-09-09T20:54:42Z", + "updated_at": "2026-02-04T04:35:16.287471Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary", + "plugin-extension-trust-policy" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + }, + "vite--CVE-2025-62522": { + "canonical_id": "vite--CVE-2025-62522", + "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\"", + "display_name": "Vite", + "system_id": "vite", + "category": "frameworks", + "severity": "medium", + "cvss_score": 4.0, + "exploit_status": "unknown", + "published_at": "2025-10-20T19:54:28Z", + "updated_at": "2026-02-04T04:13:38.886554Z", + "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" + ], + "secure_code_topics": [ + "dependency-upgrade-policy", + "file-upload-validation", + "proxy-trust-boundary" + ], + "verification_status": "triage-manual", + "verification_mode": "synthetic", + "artifact_mode": "synthetic", + "blocked_reason": null, + "browser_evidence": { + "required": false, + "present": false, + "refs": [] + } + } +} diff --git a/08-threat-intel/generated/dashboard/assets/app.js b/08-threat-intel/generated/dashboard/assets/app.js new file mode 100644 index 00000000..d7ec6b0e --- /dev/null +++ b/08-threat-intel/generated/dashboard/assets/app.js @@ -0,0 +1,507 @@ + +const state = { + summary: null, + runs: [], + systems: [], + advisories: {}, + profiles: {}, + selectedRunId: null, + selectedArtifact: null, + filters: { search: "", system: "", status: "", family: "" }, + autoRefresh: true, + refreshMs: 5000, + refreshHandle: null, +}; + +const $ = (id) => document.getElementById(id); +const statusClass = (status) => `status-pill ${({ + "blocked-artifact": "status-blocked-artifact", + "blocked-destructive": "status-blocked-destructive", + "triage-manual": "status-triage-manual", + "verified-real": "status-verified-real", + "verified-synthetic": "status-verified-synthetic", + "suspected": "status-suspected", + "completed": "status-verified-real", + "failed": "status-blocked-artifact", + "skipped": "status-triage-manual" +})[status] || "status-default"}`; + +function escapeHtml(value) { + return String(value ?? "") + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """); +} + +function timeAgo(value) { + if (!value) return "-"; + const diff = Date.now() - new Date(value).getTime(); + if (Number.isNaN(diff)) return value; + const seconds = Math.floor(diff / 1000); + if (seconds < 60) return `${seconds}s ago`; + const minutes = Math.floor(seconds / 60); + if (minutes < 60) return `${minutes}m ago`; + const hours = Math.floor(minutes / 60); + if (hours < 24) return `${hours}h ago`; + const days = Math.floor(hours / 24); + return `${days}d ago`; +} + +async function fetchJson(url) { + const response = await fetch(`${url}?t=${Date.now()}`, { cache: "no-store" }); + if (!response.ok) { + throw new Error(`${url} -> ${response.status}`); + } + return response.json(); +} + +async function loadData(preserveSelection = true) { + $("syncState").innerHTML = `Refreshing${new Date().toLocaleTimeString()}`; + const previousRun = state.selectedRunId; + try { + const [summary, runs, systems, advisories, profiles] = await Promise.all([ + fetchJson("./summary.json"), + fetchJson("./runs.json"), + fetchJson("./systems.json"), + fetchJson("./advisories.json"), + fetchJson("./profiles.json"), + ]); + state.summary = summary; + state.runs = runs; + state.systems = systems; + state.advisories = advisories; + state.profiles = profiles; + hydrateFilterOptions(); + + const hashRun = location.hash.startsWith("#run=") ? location.hash.replace("#run=", "") : null; + const selectedCandidate = preserveSelection ? (hashRun || previousRun) : hashRun; + if (selectedCandidate && runs.some((item) => item.run_id === selectedCandidate)) { + state.selectedRunId = selectedCandidate; + } else { + state.selectedRunId = runs[0]?.run_id || null; + } + + renderDashboard(); + $("syncState").innerHTML = `Live${summary.generated_at || new Date().toISOString()}`; + } catch (error) { + $("syncState").innerHTML = `Load Failed${escapeHtml(error.message)}`; + $("runList").innerHTML = `

Dashboard load failed: ${escapeHtml(error.message)}
`; + $("detailRoot").innerHTML = `
Unable to load dashboard data. Check generated JSON and local static server state.
`; + } +} + +function filteredRuns() { + return state.runs.filter((item) => { + if (state.filters.system && item.system_id !== state.filters.system) return false; + if (state.filters.status && item.verification_status !== state.filters.status) return false; + if (state.filters.family && item.repro_profile_id !== state.filters.family) return false; + if (!state.filters.search) return true; + const advisoryTitle = item.advisory_meta?.title || ""; + const haystack = [item.run_id, item.advisory_id, item.system_id, item.repro_profile_id, advisoryTitle] + .join(" ") + .toLowerCase(); + return haystack.includes(state.filters.search); + }); +} + +function renderMetrics() { + const metrics = [ + { label: "Advisories", value: state.summary?.advisory_count ?? 0 }, + { label: "Run Bundles", value: state.summary?.run_count ?? 0 }, + ...Object.entries(state.summary?.statuses || {}).map(([label, value]) => ({ label, value })), + ]; + $("metrics").innerHTML = metrics + .map((item) => `
${escapeHtml(item.label)}${escapeHtml(item.value)}
`) + .join(""); +} + +function renderSystemCoverage() { + $("systemCoverage").innerHTML = state.systems + .map((system) => { + const total = Math.max(system.total || 0, 1); + const verified = (system.verified_real || 0) + (system.verified_synthetic || 0); + const fill = Math.round((verified / total) * 100); + return ` +
+
+ ${escapeHtml(system.display_name || system.system_id)} + ${escapeHtml(system.browser_present || 0)}/${escapeHtml(system.browser_required || 0)} browser +
+
${escapeHtml(system.system_id)} · latest ${escapeHtml(system.latest_update || "-")}
+
+ real ${escapeHtml(system.verified_real || 0)} + synthetic ${escapeHtml(system.verified_synthetic || 0)} + blocked ${escapeHtml(system.blocked || 0)} + manual ${escapeHtml(system.manual || 0)} +
+
+
+ `; + }) + .join(""); +} + +function renderFailures() { + const failures = state.summary?.recent_failures || []; + $("failureFeed").innerHTML = failures.length + ? failures + .map((item) => ` +
+
+ ${escapeHtml(item.run_id)} + ${escapeHtml(item.status)} +
+
${escapeHtml(item.title || item.advisory_id)}
+
${escapeHtml(item.blocked_reason || "-")}
+
+ `) + .join("") + : `
No recent blockers.
`; +} + +function renderRunList() { + const filtered = filteredRuns(); + $("runCount").textContent = `${filtered.length} shown`; + $("runList").innerHTML = filtered.length + ? filtered + .map((item) => { + const active = item.run_id === state.selectedRunId ? "is-active" : ""; + const title = item.advisory_meta?.title || item.advisory_id; + const reasoning = item.reasoning_lines?.[0] || item.blocked_reason || ""; + return ` + + `; + }) + .join("") + : `
No runs match the current filters.
`; + + document.querySelectorAll("[data-run-id]").forEach((button) => { + button.addEventListener("click", () => { + state.selectedRunId = button.dataset.runId; + location.hash = `run=${state.selectedRunId}`; + renderRunList(); + renderDetail(); + }); + }); +} + +function renderDashboard() { + renderMetrics(); + renderSystemCoverage(); + renderFailures(); + renderRunList(); + renderDetail(); +} + +function setFilterListeners() { + [["searchInput", "search"], ["systemFilter", "system"], ["statusFilter", "status"], ["familyFilter", "family"]].forEach(([id, key]) => { + $(id).addEventListener("input", (event) => { + state.filters[key] = String(event.target.value || "").trim().toLowerCase(); + if (key !== "search") { + state.filters[key] = String(event.target.value || ""); + } + renderRunList(); + }); + }); +} + +function hydrateFilterOptions() { + const distinct = (items) => [...new Set(items.filter(Boolean))].sort(); + const patchOptions = (id, values) => { + const control = $(id); + const current = control.value; + control.innerHTML = control.dataset.base; + control.innerHTML += distinct(values).map((value) => ``).join(""); + control.value = current; + }; + patchOptions("systemFilter", state.runs.map((item) => item.system_id)); + patchOptions("statusFilter", state.runs.map((item) => item.verification_status)); + patchOptions("familyFilter", state.runs.map((item) => item.repro_profile_id)); +} + +function defaultArtifact(run) { + const preference = ["requests", "container", "browser", "compose", "reports"]; + for (const key of preference) { + const group = (run.artifact_groups || []).find((item) => item.key === key && item.items?.length); + if (!group) continue; + const preferredText = group.items.find((item) => item.kind === "text"); + return preferredText || group.items[0]; + } + return null; +} + +async function openArtifact(href, label, kind) { + state.selectedArtifact = { href, label, kind }; + document.querySelectorAll(".artifact-button").forEach((button) => { + button.classList.toggle("is-active", button.dataset.href === href); + }); + $("artifactLabel").textContent = label; + $("artifactOpen").href = href; + $("artifactMeta").textContent = href; + try { + if (kind === "image") { + $("artifactViewer").innerHTML = `${escapeHtml(label)}`; + return; + } + if (href.endsWith(".html")) { + $("artifactViewer").innerHTML = ``; + return; + } + const response = await fetch(`${href}?t=${Date.now()}`, { cache: "no-store" }); + if (!response.ok) throw new Error(`${href} -> ${response.status}`); + const text = await response.text(); + let formatted = text; + if (href.endsWith(".json")) { + try { + formatted = JSON.stringify(JSON.parse(text), null, 2); + } catch (_error) { + } + } + $("artifactViewer").innerHTML = `
${escapeHtml(formatted)}
`; + } catch (error) { + $("artifactViewer").innerHTML = `
Artifact load failed: ${escapeHtml(error.message)}
`; + } +} + +function renderDetail() { + const run = state.runs.find((item) => item.run_id === state.selectedRunId); + if (!run) { + $("detailRoot").innerHTML = `
Select a run to inspect full timeline, logs, sources, and reasoning.
`; + return; + } + + const advisory = run.advisory_meta || {}; + const profile = run.profile_meta || {}; + const screenshotItems = (run.artifact_groups || []) + .find((group) => group.key === "browser") + ?.items.filter((item) => item.kind === "image") || []; + + $("detailRoot").innerHTML = ` +
+
Local Verification Workspace
+
+ ${escapeHtml(run.verification_status)} +
+ ${escapeHtml(run.system_id)} + ${escapeHtml(run.repro_profile_id)} + ${escapeHtml(run.artifact_mode)} + ${escapeHtml(run.verification_mode)} +
+
+

${escapeHtml(advisory.title || run.advisory_id)}

+

${escapeHtml(advisory.summary || "No summary available.")}

+ +
+
Timeline Steps${escapeHtml(run.timeline?.length || 0)}
+
Artifacts${escapeHtml((run.artifact_groups || []).reduce((sum, group) => sum + group.count, 0))}
+
Browser${run.browser_evidence?.present ? "Ready" : "Missing"}
+
Finished${escapeHtml(timeAgo(run.finished_at))}
+
+
+ +
+
+
+ Progress Timeline${escapeHtml(run.timeline?.length || 0)} steps +
+
+ completed ${escapeHtml(run.progress?.completed || 0)} + blocked ${escapeHtml(run.progress?.blocked || 0)} + skipped ${escapeHtml(run.progress?.skipped || 0)} + failed ${escapeHtml(run.progress?.failed || 0)} +
+
+ ${(run.timeline || []).map((item) => ` +
+
${escapeHtml(item.at || "-")}
+
${escapeHtml(item.step || "-")}
+
+
${escapeHtml(item.status || "unknown")}
+
${escapeHtml(item.detail || "-")}
+
+
+ `).join("") || `
No timeline items available.
`} +
+
+
+ +
+ Attack Plan & Reasoning${escapeHtml(profile.vuln_family || "unknown")} +
+ ${run.blocked_reason ? `
Failure reason
${escapeHtml(run.blocked_reason)}
` : ""} +
+ destructive risk ${escapeHtml(profile.destructive_risk || "-")} + cleanup ${escapeHtml(profile.cleanup_policy || "-")} + targets ${(profile.allowed_target_types || []).join(", ") || "-"} +
+
+ ${(run.reasoning_lines || []).map((line) => `
${escapeHtml(line)}
`).join("")} +
+
+ ${(profile.success_criteria || []).map((line) => `${escapeHtml(line)}`).join("")} +
+
+
+ +
+ Evidence Explorer${escapeHtml((run.artifact_groups || []).length)} groups +
+ ${(run.artifact_groups || []).map((group) => ` +
+

${escapeHtml(group.label)} · ${escapeHtml(group.count)}

+
+ ${group.items.map((item) => ` + + `).join("")} +
+
+ `).join("") || `
No artifacts linked for this run.
`} + ${screenshotItems.length ? ` + + ` : ""} +
+
+ +
+ Live Log Viewer${state.selectedArtifact ? "active" : "idle"} +
+
+
+
+ ${escapeHtml(state.selectedArtifact?.label || "Select an artifact")} +
${escapeHtml(state.selectedArtifact?.href || "Artifacts and logs can be previewed here.")}
+
+
+ Open artifact + +
+
+
Select a report, log, JSON, screenshot, or timeline file to preview it here.
+
+
+
+
+ +
+
+ Sources & Fix Topics${escapeHtml((advisory.secondary_source_urls || []).length + (advisory.official_source_url ? 1 : 0))} links +
+
+ ${(advisory.aliases || []).map((alias) => `${escapeHtml(alias)}`).join("")} +
+
+ ${advisory.official_source_url ? `${escapeHtml(advisory.official_source_url)}` : `
No official source linked.
`} + ${(advisory.secondary_source_urls || []).map((ref) => `${escapeHtml(ref)}`).join("")} +
+
+ ${(advisory.secure_code_topics || []).map((topic) => `${escapeHtml(topic)}`).join("")} +
+
+
+ +
+ Run JSONraw +
${escapeHtml(JSON.stringify(run, null, 2))}
+
+ +
+ Advisory JSONraw +
${escapeHtml(JSON.stringify(advisory, null, 2))}
+
+ +
+ Profile JSONraw +
${escapeHtml(JSON.stringify(profile, null, 2))}
+
+
+
+ `; + + document.querySelectorAll(".artifact-button").forEach((button) => { + button.addEventListener("click", () => openArtifact(button.dataset.href, button.dataset.label, button.dataset.kind)); + }); + + $("refreshArtifact")?.addEventListener("click", () => { + if (state.selectedArtifact) { + openArtifact(state.selectedArtifact.href, state.selectedArtifact.label, state.selectedArtifact.kind); + } + }); + + if (!state.selectedArtifact || !(run.artifact_groups || []).some((group) => group.items.some((item) => item.href === state.selectedArtifact.href))) { + const artifact = defaultArtifact(run); + if (artifact) { + openArtifact(artifact.href, artifact.label, artifact.kind); + } + } else { + openArtifact(state.selectedArtifact.href, state.selectedArtifact.label, state.selectedArtifact.kind); + } +} + +function attachGlobalActions() { + $("searchInput").addEventListener("input", (event) => { + state.filters.search = String(event.target.value || "").trim().toLowerCase(); + renderRunList(); + }); + [["systemFilter", "system"], ["statusFilter", "status"], ["familyFilter", "family"]].forEach(([id, key]) => { + $(id).addEventListener("input", (event) => { + state.filters[key] = String(event.target.value || ""); + renderRunList(); + }); + }); + $("refreshDashboard").addEventListener("click", () => loadData(false)); + $("autoRefresh").addEventListener("change", (event) => { + state.autoRefresh = Boolean(event.target.checked); + startRefreshLoop(); + }); +} + +function startRefreshLoop() { + if (state.refreshHandle) { + clearInterval(state.refreshHandle); + state.refreshHandle = null; + } + if (!state.autoRefresh) return; + state.refreshHandle = setInterval(() => loadData(true), state.refreshMs); +} + +async function init() { + ["systemFilter", "statusFilter", "familyFilter"].forEach((id) => { + $(id).dataset.base = $(id).innerHTML; + }); + attachGlobalActions(); + await loadData(false); + startRefreshLoop(); + window.addEventListener("hashchange", () => loadData(false)); +} + +document.addEventListener("DOMContentLoaded", init); diff --git a/08-threat-intel/generated/dashboard/assets/styles.css b/08-threat-intel/generated/dashboard/assets/styles.css new file mode 100644 index 00000000..ad2ac571 --- /dev/null +++ b/08-threat-intel/generated/dashboard/assets/styles.css @@ -0,0 +1,664 @@ + +:root { + --bg: #07111f; + --panel: rgba(9, 18, 32, 0.86); + --panel-2: rgba(10, 24, 44, 0.92); + --panel-soft: rgba(18, 32, 56, 0.74); + --border: rgba(137, 171, 214, 0.22); + --text: #f7fafc; + --muted: #9fb3ca; + --accent: #5eead4; + --accent-2: #ffb86b; + --accent-3: #90cdf4; + --danger: #ff7b7b; + --warning: #ffd166; + --success: #6ee7a5; + --shadow: 0 24px 80px rgba(1, 7, 20, 0.45); + --radius: 20px; +} + +* { box-sizing: border-box; } +html, body { margin: 0; min-height: 100%; } +body { + font-family: "IBM Plex Sans", "Avenir Next", "Segoe UI", sans-serif; + background: + radial-gradient(circle at top left, rgba(94, 234, 212, 0.15), transparent 28%), + radial-gradient(circle at top right, rgba(255, 184, 107, 0.18), transparent 22%), + linear-gradient(145deg, #050c16 0%, #08111f 44%, #0d1c31 100%); + color: var(--text); + overflow-x: hidden; +} + +body::before { + content: ""; + position: fixed; + inset: 0; + pointer-events: none; + background-image: + linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px), + linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px); + background-size: 32px 32px; + mask-image: radial-gradient(circle at center, black 36%, transparent 78%); + opacity: 0.28; +} + +a { color: var(--accent); text-decoration: none; } +a:hover { text-decoration: underline; } +button, input, select { + font: inherit; +} + +.dashboard-shell { + position: relative; + max-width: 1640px; + margin: 0 auto; + padding: 32px 24px 40px; +} + +.hero { + position: sticky; + top: 0; + z-index: 20; + backdrop-filter: blur(18px); + background: linear-gradient(180deg, rgba(7, 17, 31, 0.94), rgba(7, 17, 31, 0.75)); + border: 1px solid var(--border); + border-radius: 28px; + padding: 24px 24px 20px; + box-shadow: var(--shadow); +} + +.hero-grid { + display: grid; + grid-template-columns: 1.6fr 1fr; + gap: 20px; + align-items: start; +} + +.eyebrow { + display: inline-flex; + align-items: center; + gap: 8px; + color: var(--muted); + font-size: 0.88rem; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.eyebrow::before { + content: ""; + width: 10px; + height: 10px; + border-radius: 999px; + background: radial-gradient(circle, var(--accent), rgba(94, 234, 212, 0.15)); + box-shadow: 0 0 24px rgba(94, 234, 212, 0.8); + animation: pulse 2.8s ease-in-out infinite; +} + +.hero h1 { + margin: 12px 0 10px; + font-family: "IBM Plex Serif", "Iowan Old Style", Georgia, serif; + font-size: clamp(2rem, 4vw, 3.5rem); + line-height: 1.02; +} + +.hero p { + margin: 0; + color: var(--muted); + max-width: 74ch; +} + +.hero-actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-top: 18px; +} + +.chip, .ghost-chip { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + border-radius: 999px; + border: 1px solid var(--border); + padding: 10px 14px; + background: rgba(255,255,255,0.06); + color: var(--text); +} + +.ghost-chip { + background: rgba(255,255,255,0.04); +} + +.hero-meta { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px; +} + +.meta-card, .glass-panel { + background: var(--panel); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: var(--shadow); +} + +.meta-card { + padding: 18px; + min-height: 116px; +} + +.meta-card strong { + display: block; + color: var(--muted); + font-size: 0.84rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.meta-card span { + display: block; + margin-top: 10px; + font-size: 2rem; + font-weight: 700; +} + +.workspace { + display: grid; + grid-template-columns: 420px minmax(0, 1fr); + gap: 20px; + margin-top: 22px; +} + +.sidebar { + display: flex; + flex-direction: column; + gap: 18px; +} + +.panel-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-bottom: 16px; +} + +.panel-header h2, .panel-header h3 { + margin: 0; + font-size: 1rem; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--muted); +} + +.glass-panel { + padding: 18px; + background: + linear-gradient(180deg, rgba(255,255,255,0.04), transparent 35%), + var(--panel); +} + +.filters { + display: grid; + gap: 12px; +} + +.filters label { + display: grid; + gap: 6px; + color: var(--muted); + font-size: 0.9rem; +} + +.filters input, .filters select { + width: 100%; + background: rgba(255,255,255,0.05); + color: var(--text); + border: 1px solid rgba(159, 179, 202, 0.18); + border-radius: 14px; + padding: 12px 14px; +} + +.run-list { + display: grid; + gap: 12px; + max-height: calc(100vh - 460px); + overflow: auto; + padding-right: 4px; +} + +.run-card { + width: 100%; + text-align: left; + padding: 16px; + border-radius: 18px; + border: 1px solid rgba(159, 179, 202, 0.14); + background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.03)); + color: var(--text); + cursor: pointer; + transition: transform 180ms ease, border-color 180ms ease, background 180ms ease; +} + +.run-card:hover, .run-card.is-active { + transform: translateY(-1px); + border-color: rgba(94, 234, 212, 0.42); + background: linear-gradient(180deg, rgba(94, 234, 212, 0.14), rgba(255,255,255,0.05)); +} + +.run-card-top, .flex-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.run-card h4 { + margin: 10px 0 8px; + font-size: 1rem; + line-height: 1.35; +} + +.mini-muted { + color: var(--muted); + font-size: 0.86rem; +} + +.status-pill { + display: inline-flex; + align-items: center; + gap: 7px; + border-radius: 999px; + padding: 6px 10px; + font-size: 0.82rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + border: 1px solid transparent; +} + +.status-pill::before { + content: ""; + width: 8px; + height: 8px; + border-radius: 999px; + background: currentColor; + box-shadow: 0 0 16px currentColor; +} + +.status-blocked-artifact, .status-blocked-destructive { + color: var(--danger); + background: rgba(255, 123, 123, 0.14); + border-color: rgba(255, 123, 123, 0.24); +} + +.status-triage-manual, .status-suspected { + color: var(--warning); + background: rgba(255, 209, 102, 0.14); + border-color: rgba(255, 209, 102, 0.24); +} + +.status-verified-real { + color: var(--success); + background: rgba(110, 231, 165, 0.14); + border-color: rgba(110, 231, 165, 0.24); +} + +.status-verified-synthetic { + color: var(--accent-3); + background: rgba(144, 205, 244, 0.14); + border-color: rgba(144, 205, 244, 0.24); +} + +.status-default { + color: var(--accent); + background: rgba(94, 234, 212, 0.14); + border-color: rgba(94, 234, 212, 0.24); +} + +.detail-view { + display: grid; + gap: 18px; +} + +.detail-hero { + padding: 22px; + overflow: hidden; + position: relative; +} + +.detail-hero::after { + content: ""; + position: absolute; + inset: auto -20% -55% 25%; + height: 220px; + background: radial-gradient(circle, rgba(94, 234, 212, 0.2), transparent 55%); + pointer-events: none; +} + +.detail-headline { + margin: 8px 0 12px; + font-family: "IBM Plex Serif", "Iowan Old Style", Georgia, serif; + font-size: clamp(1.6rem, 3vw, 2.8rem); + line-height: 1.08; +} + +.tag-row, .link-row, .artifact-row { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.tag { + display: inline-flex; + align-items: center; + padding: 7px 10px; + border-radius: 999px; + background: rgba(255,255,255,0.06); + border: 1px solid rgba(159, 179, 202, 0.18); + color: var(--text); + font-size: 0.86rem; +} + +.stat-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 12px; + margin-top: 18px; +} + +.stat-card { + padding: 14px; + border-radius: 16px; + background: rgba(255,255,255,0.04); + border: 1px solid rgba(159, 179, 202, 0.16); +} + +.stat-card strong { + display: block; + color: var(--muted); + font-size: 0.78rem; + text-transform: uppercase; + letter-spacing: 0.08em; +} + +.stat-card span { + display: block; + margin-top: 10px; + font-size: 1.15rem; + font-weight: 700; +} + +.detail-grid { + display: grid; + grid-template-columns: minmax(0, 1fr) 360px; + gap: 18px; +} + +.stack { + display: grid; + gap: 18px; +} + +.accordion { + overflow: hidden; +} + +.accordion > summary { + list-style: none; + cursor: pointer; + padding: 18px 20px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.accordion > summary::-webkit-details-marker { display: none; } +.accordion > summary span { + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--muted); +} + +.accordion .accordion-content { + padding: 0 20px 20px; + border-top: 1px solid rgba(159, 179, 202, 0.12); +} + +.timeline-list { + display: grid; + gap: 12px; +} + +.timeline-item { + display: grid; + grid-template-columns: 120px 180px minmax(0, 1fr); + gap: 12px; + padding: 12px 0; + border-bottom: 1px solid rgba(159, 179, 202, 0.12); +} + +.timeline-item:last-child { + border-bottom: 0; +} + +.timeline-step { + font-weight: 700; +} + +.artifact-group { + margin-bottom: 14px; +} + +.artifact-group h4 { + margin: 0 0 10px; + color: var(--muted); + font-size: 0.88rem; + text-transform: uppercase; + letter-spacing: 0.08em; +} + +.artifact-button { + display: inline-flex; + align-items: center; + gap: 8px; + margin: 0 10px 10px 0; + padding: 10px 12px; + border-radius: 14px; + border: 1px solid rgba(159, 179, 202, 0.16); + background: rgba(255,255,255,0.05); + color: var(--text); + cursor: pointer; +} + +.artifact-button:hover, .artifact-button.is-active { + border-color: rgba(94, 234, 212, 0.4); + background: rgba(94, 234, 212, 0.12); +} + +.log-viewer { + min-height: 420px; + display: grid; + gap: 14px; +} + +.viewer-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + gap: 10px; + align-items: center; +} + +.viewer-frame { + background: rgba(2, 8, 22, 0.88); + border: 1px solid rgba(159, 179, 202, 0.18); + border-radius: 16px; + min-height: 300px; + overflow: hidden; +} + +.viewer-frame pre { + margin: 0; + padding: 18px; + max-height: 560px; + overflow: auto; + font-family: "IBM Plex Mono", "SFMono-Regular", "Menlo", monospace; + font-size: 0.88rem; + line-height: 1.6; + color: #d6e5f5; + white-space: pre-wrap; +} + +.viewer-frame img { + display: block; + width: 100%; + height: auto; +} + +.gallery { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 14px; +} + +.gallery button { + all: unset; + cursor: pointer; + border-radius: 18px; + overflow: hidden; + border: 1px solid rgba(159, 179, 202, 0.18); + background: rgba(255,255,255,0.04); +} + +.gallery img { + display: block; + width: 100%; + aspect-ratio: 4 / 3; + object-fit: cover; +} + +.gallery figcaption { + padding: 10px 12px 14px; + color: var(--muted); + font-size: 0.84rem; +} + +.failure-callout { + padding: 16px 18px; + border-radius: 18px; + border: 1px solid rgba(255, 123, 123, 0.2); + background: rgba(255, 123, 123, 0.09); +} + +.json-block { + background: rgba(2, 8, 22, 0.72); + border-radius: 16px; + border: 1px solid rgba(159, 179, 202, 0.14); + padding: 16px; + overflow: auto; + font-family: "IBM Plex Mono", "SFMono-Regular", monospace; + font-size: 0.84rem; + line-height: 1.55; + color: #c9d8e8; +} + +.empty-state { + padding: 40px 24px; + text-align: center; + color: var(--muted); +} + +.failure-feed { + display: grid; + gap: 10px; +} + +.failure-item { + padding: 12px 14px; + border-radius: 16px; + background: rgba(255,255,255,0.04); + border: 1px solid rgba(159, 179, 202, 0.16); +} + +.system-grid { + display: grid; + gap: 10px; +} + +.system-card { + padding: 14px 16px; + border-radius: 16px; + background: rgba(255,255,255,0.04); + border: 1px solid rgba(159, 179, 202, 0.14); +} + +.meter { + position: relative; + height: 10px; + border-radius: 999px; + background: rgba(255,255,255,0.08); + overflow: hidden; + margin-top: 10px; +} + +.meter > span { + position: absolute; + inset: 0 auto 0 0; + width: var(--fill, 0%); + background: linear-gradient(90deg, var(--accent), var(--accent-2)); + border-radius: inherit; +} + +.sync-indicator { + display: inline-flex; + align-items: center; + gap: 8px; +} + +.sync-indicator strong { + color: var(--text); +} + +.dot { + width: 10px; + height: 10px; + border-radius: 999px; + background: var(--accent); + box-shadow: 0 0 18px rgba(94, 234, 212, 0.8); +} + +@keyframes pulse { + 0%, 100% { transform: scale(1); opacity: 0.88; } + 50% { transform: scale(1.35); opacity: 1; } +} + +@media (max-width: 1280px) { + .workspace, .detail-grid, .hero-grid { + grid-template-columns: 1fr; + } + + .stat-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 760px) { + .dashboard-shell { + padding: 18px 14px 32px; + } + + .hero { + position: static; + } + + .stat-grid, .hero-meta { + grid-template-columns: 1fr; + } + + .timeline-item { + grid-template-columns: 1fr; + } +} diff --git a/08-threat-intel/generated/dashboard/index.html b/08-threat-intel/generated/dashboard/index.html index d6989a0b..8cdf32bd 100644 --- a/08-threat-intel/generated/dashboard/index.html +++ b/08-threat-intel/generated/dashboard/index.html @@ -1,95 +1,80 @@ + - + - websafe dashboard - + + websafe authorized lab dashboard + -

websafe Local Lab Dashboard

-

LAB ONLY | AUTHORIZED TARGETS ONLY | 本地静态看板

-
-

System Coverage

- - - -
SystemTotalVerified RealVerified SyntheticBlockedManualBrowserLatest
-

Recent Runs

-
- - - - +
+
+
+
+
Authorized Lab Dashboard
+

本地攻防实证工作台

+

面向授权实验场景的本地静态前端。聚合 advisory、run bundle、日志、浏览器证据、失败原因、利用思路与源头信息,并支持可折叠细节与自动刷新。

+
+ + + Open Summary JSON +
+
+
+
+

Sync State

+
BootingLoading generated JSON
+
+
+
+
+
+ +
+ + +
+
Select a run to inspect full details.
+
+
- - - -
RunSystemAdvisoryStatusModeProfileFinishedArtifacts
- + diff --git a/08-threat-intel/generated/dashboard/profiles.json b/08-threat-intel/generated/dashboard/profiles.json new file mode 100644 index 00000000..f1b7fac2 --- /dev/null +++ b/08-threat-intel/generated/dashboard/profiles.json @@ -0,0 +1,513 @@ +{ + "authz-bypass-generic": { + "profile_id": "authz-bypass-generic", + "vuln_family": "authz-bypass", + "provisioning_mode": "real", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Protected route or action is evaluated with controlled credentials and logged." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Create low-privilege and admin test users for server-side recheck validation." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Use minimal authorization bypass probes defined by case-specific runner or manual session tooling." + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "deserialization-generic": { + "profile_id": "deserialization-generic", + "vuln_family": "deserialization", + "provisioning_mode": "synthetic", + "destructive_risk": "high", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "source-or-synthetic" + }, + "success_criteria": [ + "Deserialization path is confirmed without executing destructive gadget chains." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Use inert serialized payloads and do not execute gadget chains against non-lab targets." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Demonstrate unsafe decode path with inert object graph or marker token." + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "file-upload-generic": { + "profile_id": "file-upload-generic", + "vuln_family": "file-upload", + "provisioning_mode": "real", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Upload acceptance or bypass path is demonstrated with reversible test artifacts." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Use inert marker files and non-executable payloads by default." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Validate extension, storage path, and preview behavior using inert files." + } + ], + "browser_assertions": { + "required": true + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "misconfiguration-generic": { + "profile_id": "misconfiguration-generic", + "vuln_family": "misconfiguration", + "provisioning_mode": "real", + "destructive_risk": "low", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Misconfiguration indicator is captured with HTTP or server evidence." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Keep checks limited to target-local paths and configured lab endpoints." + } + ], + "attack_actions": [ + { + "kind": "tool", + "tool": "misconfig-lab", + "args": [ + "--target", + "{target_url}", + "--evidence-dir", + "{evidence_dir}", + "--run-id", + "{run_id}", + "--case-id", + "{case_id}" + ] + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "path-traversal-generic": { + "profile_id": "path-traversal-generic", + "vuln_family": "path-traversal", + "provisioning_mode": "real", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Marker file outside intended root becomes reachable or denial path is confirmed." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Use inert marker files inside isolated volume mounts only." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Validate canonicalization failures with marker files rather than real secrets." + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "plugin-extension-generic": { + "profile_id": "plugin-extension-generic", + "vuln_family": "plugin-extension", + "provisioning_mode": "synthetic", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "ecosystem-package-or-synthetic" + }, + "success_criteria": [ + "Extension-specific attack path is demonstrated or blocked with artifact evidence." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Prefer historical plugin/module package; fall back to synthetic isolated reproduction when unavailable." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Validate trust-boundary or input-handling weakness using isolated extension package only." + } + ], + "browser_assertions": { + "required": true + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "proxy-boundary-generic": { + "profile_id": "proxy-boundary-generic", + "vuln_family": "proxy-boundary", + "provisioning_mode": "real", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Header trust discrepancy is captured with upstream/downstream logs." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Log reverse-proxy and application headers before any trust-boundary test." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Perform minimal forwarded-header manipulation only inside isolated lab paths." + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "request-smuggling-generic": { + "profile_id": "request-smuggling-generic", + "vuln_family": "request-smuggling", + "provisioning_mode": "synthetic", + "destructive_risk": "high", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "synthetic-proxy-pair" + }, + "success_criteria": [ + "Proxy and backend parse disagreement is captured in evidence." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Stand up isolated proxy/app pair only; do not forward to unrelated targets." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Run minimal ambiguous request probes and capture both proxy and app logs." + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "session-token-generic": { + "profile_id": "session-token-generic", + "vuln_family": "session-token", + "provisioning_mode": "real", + "destructive_risk": "low", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Cookie, storage or fixation issue is captured with browser and header evidence." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Seed only local demo identities and short-lived cookies/tokens." + } + ], + "attack_actions": [ + { + "kind": "tool", + "tool": "session-lab", + "args": [ + "--target", + "{target_url}", + "--evidence-dir", + "{evidence_dir}", + "--run-id", + "{run_id}", + "--case-id", + "{case_id}" + ] + } + ], + "browser_assertions": { + "required": true + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "sqli-generic": { + "profile_id": "sqli-generic", + "vuln_family": "sqli", + "provisioning_mode": "synthetic", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-synthetic" + }, + "success_criteria": [ + "Time-based or error-based probe lands with non-destructive evidence." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Keep seed data reversible and avoid destructive SQL mutations." + } + ], + "attack_actions": [ + { + "kind": "tool", + "tool": "sqli-scanner", + "args": [ + "-u", + "{target_url}", + "--evidence-dir", + "{evidence_dir}", + "--run-id", + "{run_id}", + "--case-id", + "{case_id}" + ] + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "ssrf-generic": { + "profile_id": "ssrf-generic", + "vuln_family": "ssrf", + "provisioning_mode": "real", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Request sink receives expected callback without crossing authorization boundaries." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Route callbacks to local sink endpoints only." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Exercise local sink endpoints, not external third-party destinations." + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "template-injection-generic": { + "profile_id": "template-injection-generic", + "vuln_family": "template-injection", + "provisioning_mode": "synthetic", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "source-or-synthetic" + }, + "success_criteria": [ + "Template evaluation path is proven with harmless marker output." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Keep expressions inert and avoid destructive primitives by default." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Validate expression evaluation with benign markers." + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "xss-generic": { + "profile_id": "xss-generic", + "vuln_family": "xss", + "provisioning_mode": "synthetic", + "destructive_risk": "low", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-synthetic" + }, + "success_criteria": [ + "Browser evidence confirms payload reflection or DOM sink execution path." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Seed a low-privilege user and a review page when the target supports stored content." + } + ], + "attack_actions": [ + { + "kind": "tool", + "tool": "xss-fuzzer", + "args": [ + "-u", + "{target_url}", + "--dom-scan", + "--check-csp", + "--evidence-dir", + "{evidence_dir}", + "--run-id", + "{run_id}", + "--case-id", + "{case_id}" + ] + } + ], + "browser_assertions": { + "required": true, + "strategy": "reflect-or-render" + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + } +} diff --git a/08-threat-intel/generated/dashboard/runs.json b/08-threat-intel/generated/dashboard/runs.json index 3f25c79a..9820e0a9 100644 --- a/08-threat-intel/generated/dashboard/runs.json +++ b/08-threat-intel/generated/dashboard/runs.json @@ -101,7 +101,140 @@ }, "browser_links": [], "container_links": [], - "request_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": [] + } + }, + "profile_meta": { + "profile_id": "file-upload-generic", + "vuln_family": "file-upload", + "provisioning_mode": "real", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Upload acceptance or bypass path is demonstrated with reversible test artifacts." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Use inert marker files and non-executable payloads by default." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Validate extension, storage path, and preview behavior using inert files." + } + ], + "browser_assertions": { + "required": true + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "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?" + ], + "progress": { + "completed": 3, + "skipped": 5, + "failed": 0, + "blocked": 1, + "planned": 0, + "other": 0 + }, + "artifact_groups": [ + { + "key": "reports", + "label": "Reports", + "count": 4, + "items": [ + { + "href": "./runs/gitea-livecheck-20260316/report.html", + "label": "report.html", + "kind": "text" + }, + { + "href": "./runs/gitea-livecheck-20260316/report.md", + "label": "report.md", + "kind": "text" + }, + { + "href": "./runs/gitea-livecheck-20260316/timeline.mmd", + "label": "timeline.mmd", + "kind": "text" + }, + { + "href": "./runs/gitea-livecheck-20260316/run.json", + "label": "run.json", + "kind": "text" + } + ] + }, + { + "key": "compose", + "label": "Compose", + "count": 1, + "items": [ + { + "href": "./runs/gitea-livecheck-20260316/compose/compose.yaml", + "label": "compose.yaml", + "kind": "text" + } + ] + } + ] }, { "run_id": "gitea-gitea--CVE-2025-68939-20260317063330", @@ -144,6 +277,144 @@ "request_links": [ "./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": [] + } + }, + "profile_meta": { + "profile_id": "file-upload-generic", + "vuln_family": "file-upload", + "provisioning_mode": "real", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Upload acceptance or bypass path is demonstrated with reversible test artifacts." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Use inert marker files and non-executable payloads by default." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Validate extension, storage path, and preview behavior using inert files." + } + ], + "browser_assertions": { + "required": true + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "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?" + ], + "progress": { + "completed": 0, + "skipped": 0, + "failed": 0, + "blocked": 0, + "planned": 0, + "other": 0 + }, + "artifact_groups": [ + { + "key": "reports", + "label": "Reports", + "count": 4, + "items": [ + { + "href": "./runs/gitea-gitea--CVE-2025-68939-20260317063330/report.html", + "label": "report.html", + "kind": "text" + }, + { + "href": "./runs/gitea-gitea--CVE-2025-68939-20260317063330/report.md", + "label": "report.md", + "kind": "text" + }, + { + "href": "./runs/gitea-gitea--CVE-2025-68939-20260317063330/timeline.mmd", + "label": "timeline.mmd", + "kind": "text" + }, + { + "href": "./runs/gitea-gitea--CVE-2025-68939-20260317063330/run.json", + "label": "run.json", + "kind": "text" + } + ] + }, + { + "key": "requests", + "label": "Request Logs", + "count": 2, + "items": [ + { + "href": "./runs/gitea-gitea--CVE-2025-68939-20260317063330/logs/attack.json", + "label": "attack.json", + "kind": "text" + }, + { + "href": "./runs/gitea-gitea--CVE-2025-68939-20260317063330/logs/baseline.json", + "label": "baseline.json", + "kind": "text" + } + ] + } ] }, { @@ -196,6 +467,147 @@ "request_links": [ "./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": [] + } + }, + "profile_meta": { + "profile_id": "authz-bypass-generic", + "vuln_family": "authz-bypass", + "provisioning_mode": "real", + "destructive_risk": "medium", + "cleanup_policy": "destroy", + "artifact_source": { + "strategy": "official-image-or-source" + }, + "success_criteria": [ + "Protected route or action is evaluated with controlled credentials and logged." + ], + "seed_actions": [ + { + "kind": "note", + "message": "Create low-privilege and admin test users for server-side recheck validation." + } + ], + "attack_actions": [ + { + "kind": "note", + "message": "Use minimal authorization bypass probes defined by case-specific runner or manual session tooling." + } + ], + "browser_assertions": { + "required": false + }, + "allowed_target_types": [ + "lab-local", + "lab-public", + "authorized-third-party" + ], + "required_services": [ + "app" + ] + }, + "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" + ], + "progress": { + "completed": 0, + "skipped": 0, + "failed": 0, + "blocked": 0, + "planned": 0, + "other": 0 + }, + "artifact_groups": [ + { + "key": "reports", + "label": "Reports", + "count": 4, + "items": [ + { + "href": "./runs/nextjs-nextjs--CVE-2025-29927-20260317063047/report.html", + "label": "report.html", + "kind": "text" + }, + { + "href": "./runs/nextjs-nextjs--CVE-2025-29927-20260317063047/report.md", + "label": "report.md", + "kind": "text" + }, + { + "href": "./runs/nextjs-nextjs--CVE-2025-29927-20260317063047/timeline.mmd", + "label": "timeline.mmd", + "kind": "text" + }, + { + "href": "./runs/nextjs-nextjs--CVE-2025-29927-20260317063047/run.json", + "label": "run.json", + "kind": "text" + } + ] + }, + { + "key": "requests", + "label": "Request Logs", + "count": 2, + "items": [ + { + "href": "./runs/nextjs-nextjs--CVE-2025-29927-20260317063047/logs/attack.json", + "label": "attack.json", + "kind": "text" + }, + { + "href": "./runs/nextjs-nextjs--CVE-2025-29927-20260317063047/logs/baseline.json", + "label": "baseline.json", + "kind": "text" + } + ] + } ] } ] diff --git a/08-threat-intel/generated/dashboard/summary.json b/08-threat-intel/generated/dashboard/summary.json index 8bba20dd..0deefa04 100644 --- a/08-threat-intel/generated/dashboard/summary.json +++ b/08-threat-intel/generated/dashboard/summary.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-17T07:06:50+00:00", + "generated_at": "2026-03-17T07:27:25+00:00", "advisory_count": 89, "run_count": 3, "statuses": { @@ -11,18 +11,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", "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", "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", "blocked_reason": "dry-run only" } ], diff --git a/08-threat-intel/generated/latest-ingest.md b/08-threat-intel/generated/latest-ingest.md index 5a262a03..e5be00b1 100644 --- a/08-threat-intel/generated/latest-ingest.md +++ b/08-threat-intel/generated/latest-ingest.md @@ -1,6 +1,6 @@ # 最新同步摘要 -- 渲染时间: `2026-03-17T07:06:50+00:00` +- 渲染时间: `2026-03-17T07:27:25+00:00` - 系统数量: `62` - Advisory 数量: `89` - 重点 Markdown 数量: `89` diff --git a/08-threat-intel/generated/run-summary.json b/08-threat-intel/generated/run-summary.json index 25356e3f..9d59a02d 100644 --- a/08-threat-intel/generated/run-summary.json +++ b/08-threat-intel/generated/run-summary.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-03-17T07:06:50+00:00", + "generated_at": "2026-03-17T07:27:25+00:00", "system_count": 62, "advisory_count": 89, "markdown_count": 89, diff --git a/README.md b/README.md index a5578606..8cd194cb 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ ## 入口 +- [项目文档总览](/Users/x/websafe/docs/README.md) - [目标边界与授权模型](/Users/x/websafe/09-scope-and-targeting/authorization-model.md) - [主流开源 Web 系统安全总览](/Users/x/websafe/07-framework-security/README.md) - [漏洞情报与自动入库总览](/Users/x/websafe/08-threat-intel/README.md) @@ -27,6 +28,7 @@ websafe/ ├── 07-framework-security/ # CMS、电商、框架、服务器、平台系统安全 ├── 08-threat-intel/ # source-map、repro-map、registry、dashboard、订阅规则、自动入库 ├── 09-scope-and-targeting/ # 授权模型、资产模板、测试记录模板 +├── docs/ # 项目功能文档、前端设计文档与展示规范 ├── requirements-intel.txt # intel + lab 自动化依赖(含 Playwright Python 包) ├── scripts/intel/ # hotlane / ingest / reconcile / backfill / open-pr CLI └── scripts/lab/ # provision / baseline / attack / browser / evidence / render / queue CLI diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..63e0857b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,19 @@ +# 项目文档总览 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` | `NOT A PRODUCTION BASELINE` + +本目录汇总本项目的功能说明、数据面说明和前端展示设计,服务于两个目标: + +- 让仓库使用者快速理解“项目做什么、怎么跑、哪些能力已经落地”。 +- 让本地 dashboard 的展示、交互、日志查看、折叠/展开和实时刷新有明确设计准则,不再只是临时页面。 + +## 文档入口 + +- [项目功能与特性总览](/Users/x/websafe/docs/project-features.md) +- [本地前端工作台设计文档](/Users/x/websafe/docs/frontend-dashboard-design.md) + +## 文档边界 + +- 仅描述 `lab-local`、`lab-public`、`authorized-third-party` 三类授权目标下的功能与前端展示。 +- 不把本仓库内容包装成生产安全最佳实践,也不为未授权互联网资产提供工作流语境。 +- 页面中出现的利用、注入、日志、失败原因、源头链接和思路说明,均应绑定到授权实验或自有测试资产。 diff --git a/docs/frontend-dashboard-design.md b/docs/frontend-dashboard-design.md new file mode 100644 index 00000000..ca37a9b6 --- /dev/null +++ b/docs/frontend-dashboard-design.md @@ -0,0 +1,309 @@ +# 本地前端工作台设计文档 + +> `LAB ONLY` | `AUTHORIZED TARGETS ONLY` + +## 1. 设计目标 + +本地 dashboard 要从“简单索引页”升级成“完整的授权攻防实证工作台”。它需要同时满足三类使用场景: + +1. 运行中观察 + - 看当前 run 进度 + - 看失败原因和阻塞点 + - 实时打开日志和证据 +2. 复盘分析 + - 查看 timeline、思路、利用路径、来源与修复主题 + - 对比真实版本与 synthetic 复现差异 +3. 审阅归档 + - 从一个前端入口点进 `report.md`, `report.html`, `run.json`, 原始日志和截图 + +## 2. 页面定位 + +### 2.1 页面名称 + +- 页面名称:`Authorized Lab Dashboard` +- 页面语境:本地静态前端 + 本地文件 JSON 数据源 +- 非目标:在线 SaaS、多用户后端、生产管理台 + +### 2.2 核心原则 + +- 所有展示都围绕授权目标 +- 失败信息不能被隐藏在深层页面里 +- 信息密度高,但必须可折叠、可筛选、可逐层展开 +- 日志与原始 JSON 必须能直接预览 +- 页面视觉应更生动,但不能牺牲扫描效率 + +## 3. 信息架构 + +```mermaid +flowchart LR + A["Hero + Global Status"] --> B["Sidebar Filters"] + A --> C["Run Queue List"] + C --> D["Run Detail Hero"] + D --> E["Progress Timeline"] + D --> F["Attack Plan & Reasoning"] + D --> G["Evidence Explorer"] + D --> H["Live Log Viewer"] + D --> I["Sources & Fix Topics"] + D --> J["Raw JSON Panels"] +``` + +## 4. 页面布局 + +### 4.1 顶部 Hero + +必须展示: + +- 页面名称 +- 授权实验语境说明 +- 刷新按钮 +- 自动刷新开关 +- 当前同步状态 +- 核心 metric cards + +视觉要求: + +- 不能是纯白表格页 +- 需要有分层背景、渐变光晕、轻微动态氛围 +- 顶栏 sticky,滚动时仍可看到刷新和状态 + +### 4.2 左侧侧栏 + +包含四块: + +- Filters + - 搜索 + - system filter + - status filter + - profile filter +- Systems + - 系统覆盖度 + - browser evidence 覆盖 + - latest update +- Recent Failures + - 最近 blocker + - status + - 原因摘要 +- Run Queue View + - 最近 run 卡片列表 + - 可选中并切换到 detail panel + +### 4.3 右侧 Detail Workspace + +必须包含: + +- Run Hero + - advisory 标题 + - system / profile / artifact / verification 状态 + - report / bundle / markdown 入口 +- Progress Timeline + - 每一步的时间、状态、说明 +- Attack Plan & Reasoning + - success criteria + - seed / attack notes + - failure reason + - 当前 blocker +- Evidence Explorer + - reports + - compose + - browser evidence + - request logs + - container logs +- Live Log Viewer + - 预览 text/json/html/image + - refresh preview + - open artifact +- Sources & Fix Topics + - official source + - secondary sources + - aliases + - secure code topics +- Raw JSON + - run JSON + - advisory JSON + - profile JSON + +## 5. 交互要求 + +### 5.1 折叠 / 展开 + +所有 detail 分区都应支持折叠: + +- Progress Timeline +- Attack Plan & Reasoning +- Evidence Explorer +- Live Log Viewer +- Sources & Fix Topics +- Raw JSON sections + +折叠要求: + +- 默认展开常用分区 +- 次级原始数据可以默认收起 +- 折叠状态视觉要清晰,不靠小箭头弱提示 + +### 5.2 Run 切换 + +- 点击左侧 run card 后,右侧 detail panel 即时刷新 +- 当前选中项要有强视觉区别 +- URL hash 应保留 `#run=`,方便直接打开特定 run + +### 5.3 Artifact 预览 + +点击 artifact button 后: + +- JSON 自动格式化 +- 日志文件以 `
` 方式显示
+- 图片以内联方式展示
+- HTML 报告可 iframe 预览或新窗口打开
+
+### 5.4 自动刷新
+
+- 默认每 5 秒刷新一次 dashboard JSON
+- 用户可以关闭自动刷新
+- 当前正在查看的 artifact 在自动刷新开启时应支持重新抓取
+
+### 5.5 失败原因高亮
+
+对于 `blocked-*` 和 `triage-manual`:
+
+- 顶部 hero 要显示状态 pill
+- reasoning 面板要显示 failure callout
+- 左侧 Recent Failures 要保留最近失败摘要
+
+## 6. 展示字段清单
+
+### 6.1 Hero 区
+
+- run_id
+- advisory_id
+- advisory title
+- verification_status
+- verification_mode
+- artifact_mode
+- system_id
+- repro_profile_id
+- finished_at
+
+### 6.2 Timeline 区
+
+- `timeline[].at`
+- `timeline[].step`
+- `timeline[].status`
+- `timeline[].detail`
+
+### 6.3 Reasoning 区
+
+- advisory summary
+- profile seed messages
+- profile attack messages
+- profile success criteria
+- blocked reason
+
+### 6.4 Sources 区
+
+- official_source_url
+- secondary_source_urls
+- aliases
+- secure_code_topics
+
+### 6.5 Evidence 区
+
+- report.html
+- report.md
+- timeline.mmd
+- bundle json
+- compose.yaml
+- browser screenshots / DOM / console / network
+- request logs
+- container logs
+
+## 7. 动效与视觉要求
+
+### 7.1 必须有的视觉增强
+
+- 顶部背景渐变和环境光
+- status pill 发光色彩区分
+- 卡片 hover 浮起
+- sticky hero
+- 折叠面板开合层次
+- gallery 缩略图点击查看
+
+### 7.2 推荐但必须受控
+
+- 状态小圆点 pulse
+- 背景网格或轻微数据面纹理
+- 面板玻璃感和浅透视阴影
+
+### 7.3 不允许
+
+- 花哨但影响可读性的动画
+- 大面积纯装饰 3D 效果
+- 自动播放噪音式动效
+- 让日志区难以复制文本的视觉处理
+
+## 8. 实时日志与细节查看要求
+
+### 8.1 日志查看器
+
+日志查看器必须支持:
+
+- 选中文件后即刻预览
+- JSON 格式化
+- text/json/html/image 四类预览
+- 打开原文件
+- 在自动刷新开启时重新抓取当前文件
+
+### 8.2 重点要看的日志
+
+- compose / environment 文件
+- baseline / attack / browser json
+- container logs
+- request logs
+- timeline / bundle
+
+### 8.3 失败排查导向
+
+失败时应优先展示:
+
+- `blocked_reason`
+- 当前 step
+- 上一个完成 step
+- 当前可打开的日志 / 报告 / run bundle
+- 对应 advisory 来源与 profile success criteria
+
+## 9. 数据源契约
+
+前端依赖的本地 JSON/文件源:
+
+- `summary.json`
+- `runs.json`
+- `systems.json`
+- `advisories.json`
+- `profiles.json`
+- `runs//report.html`
+- `runs//report.md`
+- `runs//run.json`
+- `runs//logs/*`
+- `runs//assets/*`
+
+前端不直接写这些数据,只读取并展示。
+
+## 10. 落地约束
+
+- 保持静态前端,不引入长期运行后端
+- 本地 `serve-dashboard` 即可查看
+- 对于正在跑的 case,前端通过轮询读取新 JSON 实现“近实时”
+- 不依赖第三方 CDN UI 库
+- 优先使用原生 HTML/CSS/JS,可长期维护
+
+## 11. 验收标准
+
+页面完成后,应满足:
+
+- 能从 run list 切换到 detail panel
+- 能折叠与展开各信息区
+- 能打开并预览 JSON / text / image / html artifact
+- 能看到失败原因、思路、来源、修复主题
+- 能筛选 system / status / profile
+- 能在自动刷新开启时重新载入 dashboard 数据
+- 页面视觉比“普通表格页”更生动,但仍适合高密度阅读
diff --git a/docs/project-features.md b/docs/project-features.md
new file mode 100644
index 00000000..78f2ea52
--- /dev/null
+++ b/docs/project-features.md
@@ -0,0 +1,162 @@
+# 项目功能与特性总览
+
+> `LAB ONLY` | `AUTHORIZED TARGETS ONLY`
+
+## 1. 项目定位
+
+`websafe` 是一套“授权攻防实验与研究知识库 + 本地实证系统”。它不是生产安全基线库,也不是面向任意第三方站点的扫描平台。
+
+项目覆盖:
+
+- 本地靶场、Docker 集群、内网实验节点
+- 自建且可公网访问的测试网站、服务器、设备
+- 已明确授权的验证性测试目标
+
+项目不覆盖:
+
+- 无归属证明、无授权的公网资产
+- 公共知名网站
+- 泛互联网画像、枚举、对外大规模探测
+
+## 2. 功能版图
+
+### 2.1 情报与入库
+
+- `08-threat-intel/source-map.yaml`
+  - 定义系统范围、来源、覆盖策略、输出目录、secure-code 主题
+- `08-threat-intel/repro-map.yaml`
+  - 定义系统到 repro family、浏览器要求、日志策略和报告模板的映射
+- `08-threat-intel/repro-profiles/`
+  - family 级和 advisory 级复现说明
+- `08-threat-intel/registry/`
+  - advisory、system、run、triage 的唯一真值层
+- `08-threat-intel/generated/`
+  - coverage matrix、latest ingest、dashboard 等人类可读产物
+
+### 2.2 本地实证与编排
+
+- `00-environments/catalog/`
+  - 记录系统、镜像、源码、依赖和健康检查的 catalog
+- `00-environments/profiles/`
+  - 记录具体版本或 current profile 的 compose / baseline / seed 参数
+- `scripts/lab/main.py`
+  - 唯一 lab CLI 入口
+- `scripts/lab/`
+  - `catalog`, `provision`, `compose`, `seed`, `baseline`, `attack`, `browser`, `evidence`, `render`, `queue`, `validators`
+
+### 2.3 攻击验证工具
+
+- `01-sql-injection/`
+  - `sqli-scanner.py`, `blind-sqli.py`, `sqli-exploit.go`
+- `02-xss/`
+  - `xss-fuzzer.py`, `xss-scanner.go`
+- `03-authentication/`
+  - `web-brute.py`, `jwt-cracker.py`, `session-lab.py`
+- `04-server-security/`
+  - `port-scanner.py`, `tls-scanner.py`, `site-scope-mapper.py`, `misconfig-lab.py`
+
+### 2.4 结果展示
+
+- `06-case-studies/generated-runs//`
+  - `report.md`, `report.html`, `timeline.mmd`, `assets/`, `logs/`
+- `08-threat-intel/generated/dashboard/`
+  - 静态前端工作台
+- `07-framework-security/`
+  - 系统级 README、INDEX、案例页,自动显示本地实证状态
+
+## 3. 数据流与自动化链路
+
+```mermaid
+flowchart LR
+  A["Threat Intel Sources"] --> B["registry/advisories"]
+  B --> C["repro-map + repro-profiles"]
+  C --> D["00-environments catalog/profiles"]
+  D --> E["scripts/lab run-case / run-batch"]
+  E --> F["generated-runs/"]
+  F --> G["registry/runs"]
+  G --> H["case pages / system INDEX"]
+  G --> I["dashboard JSON + local UI"]
+  H --> J["README / docs / PR"]
+  I --> J
+```
+
+## 4. 关键特性
+
+### 4.1 完整覆盖语义
+
+- 每条 advisory 至少进入 `registry/advisories`
+- 每条 advisory 必须有明确的实证状态
+- 状态只允许:
+  - `verified-real`
+  - `verified-synthetic`
+  - `blocked-artifact`
+  - `blocked-destructive`
+  - `triage-manual`
+
+### 4.2 浏览器证据强制
+
+- XSS、DOM XSS、Token 存储、前端路由绕过、前端配置暴露等浏览器类 case
+  - 必须生成截图
+  - 必须生成 DOM 快照
+  - 必须生成 console / network 证据
+  - 没有浏览器证据不得升级为 `verified-*`
+
+### 4.3 受控攻击语义
+
+- 默认模式是 `minimal-proof`
+- 只读探测、最小化注入、可审计回显、可回滚验证
+- 破坏性利用、越权下载真实数据、不可回滚行为默认禁用
+
+### 4.4 双展示面
+
+- 静态归档报告
+  - 适合证据留存、归档、PR 审阅
+- 本地前端工作台
+  - 适合实时查看进度、日志、失败原因、来源、思路、截图和原始 JSON
+
+### 4.5 自动化提交
+
+- `scripts/intel/run-hourly.sh`
+  - hotlane ingest + hotlane repro
+- `scripts/intel/run-nightly.sh`
+  - 常规 ingest + batch repro + render + validate + PR
+- `scripts/intel/run-weekly-reconcile.sh`
+  - reconcile + retry failures + rerender + validate + PR
+
+## 5. CLI 能力
+
+### 5.1 Intel CLI
+
+```bash
+python3 /Users/x/websafe/scripts/intel/main.py hotlane
+python3 /Users/x/websafe/scripts/intel/main.py ingest --since last-success
+python3 /Users/x/websafe/scripts/intel/main.py reconcile
+python3 /Users/x/websafe/scripts/intel/main.py render
+python3 /Users/x/websafe/scripts/intel/main.py validate
+python3 /Users/x/websafe/scripts/intel/main.py open-pr --dry-run
+```
+
+### 5.2 Lab CLI
+
+```bash
+python3 /Users/x/websafe/scripts/lab/main.py catalog sync
+python3 /Users/x/websafe/scripts/lab/main.py validate
+python3 /Users/x/websafe/scripts/lab/main.py run-case --case gitea--CVE-2025-68939
+python3 /Users/x/websafe/scripts/lab/main.py run-case --case nextjs--CVE-2025-29927 --dry-run
+python3 /Users/x/websafe/scripts/lab/main.py run-batch --limit 10
+python3 /Users/x/websafe/scripts/lab/main.py serve-dashboard --port 8734
+```
+
+## 6. 前端工作台当前目标
+
+前端不只是“一个结果页”,而是本地实验控制台与证据阅读器。它需要:
+
+- 快速定位系统 / advisory / repro profile
+- 折叠与展开 timeline、evidence、sources、raw JSON
+- 直接查看 compose、JSON、日志、截图、报告
+- 高亮失败原因、当前 blocker、利用思路、成功判据
+- 自动刷新生成数据,适配正在进行中的本地 run
+
+详细设计见:
+
+- [本地前端工作台设计文档](/Users/x/websafe/docs/frontend-dashboard-design.md)
diff --git a/scripts/intel/validators.py b/scripts/intel/validators.py
index bc40292b..4b082eda 100644
--- a/scripts/intel/validators.py
+++ b/scripts/intel/validators.py
@@ -84,6 +84,11 @@ def validate(source_map: Dict[str, Any]) -> List[str]:
         GENERATED_DIR / "dashboard" / "index.html",
         GENERATED_DIR / "dashboard" / "summary.json",
         GENERATED_DIR / "dashboard" / "systems.json",
+        GENERATED_DIR / "dashboard" / "runs.json",
+        GENERATED_DIR / "dashboard" / "advisories.json",
+        GENERATED_DIR / "dashboard" / "profiles.json",
+        GENERATED_DIR / "dashboard" / "assets" / "app.js",
+        GENERATED_DIR / "dashboard" / "assets" / "styles.css",
         ROOT / "08-threat-intel" / "registry" / "source-confidence.md",
     ]:
         if not path.exists():
diff --git a/scripts/lab/render.py b/scripts/lab/render.py
index 3d404d11..d07cd9cf 100644
--- a/scripts/lab/render.py
+++ b/scripts/lab/render.py
@@ -6,7 +6,8 @@ from pathlib import Path
 from typing import Any, Dict, List
 
 from lab.config import ADVISORIES_DIR, CASE_RUNS_DIR, DASHBOARD_DIR, RUNS_DIR
-from lab.utils import ensure_dir, isoformat, load_json_dir, now_utc, write_json, write_text
+from lab.repro import load_profiles
+from lab.utils import ensure_dir, isoformat, load_json_dir, now_utc, unique, write_json, write_text
 
 
 def mermaid_from_steps(run: Dict[str, Any]) -> str:
@@ -41,6 +42,112 @@ def _dashboard_ref(run: Dict[str, Any], ref: str) -> str:
         return ref
 
 
+def _artifact_kind(href: str) -> str:
+    suffix = Path(href).suffix.lower()
+    if suffix in {".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg"}:
+        return "image"
+    if suffix in {".json", ".log", ".txt", ".yaml", ".yml", ".md", ".mmd", ".html"}:
+        return "text"
+    return "link"
+
+
+def _artifact_item(run: Dict[str, Any], href: str, label: str | None = None) -> Dict[str, Any]:
+    return {
+        "href": href,
+        "label": label or Path(href).name,
+        "kind": _artifact_kind(href),
+    }
+
+
+def _artifact_group(run: Dict[str, Any], key: str, label: str, refs: List[str], use_dashboard_refs: bool = False) -> Dict[str, Any]:
+    items: List[Dict[str, Any]] = []
+    for ref in refs:
+        href = ref if use_dashboard_refs else _dashboard_ref(run, ref)
+        items.append(_artifact_item(run, href))
+    return {
+        "key": key,
+        "label": label,
+        "count": len(items),
+        "items": items,
+    }
+
+
+def _progress_counts(run: Dict[str, Any]) -> Dict[str, int]:
+    counts = {"completed": 0, "skipped": 0, "failed": 0, "blocked": 0, "planned": 0, "other": 0}
+    for item in run.get("timeline", []):
+        status = item.get("status", "other")
+        if status.startswith("blocked"):
+            counts["blocked"] += 1
+        elif status in counts:
+            counts[status] += 1
+        else:
+            counts["other"] += 1
+    return counts
+
+
+def _advisory_meta(advisory: Dict[str, Any]) -> Dict[str, Any]:
+    if not advisory:
+        return {}
+    return {
+        "canonical_id": advisory.get("canonical_id"),
+        "title": advisory.get("title"),
+        "summary": advisory.get("summary"),
+        "display_name": advisory.get("display_name"),
+        "system_id": advisory.get("system_id"),
+        "category": advisory.get("category"),
+        "severity": advisory.get("severity"),
+        "cvss_score": advisory.get("cvss_score"),
+        "exploit_status": advisory.get("exploit_status"),
+        "published_at": advisory.get("published_at"),
+        "updated_at": advisory.get("updated_at"),
+        "official_source_url": advisory.get("official_source_url"),
+        "secondary_source_urls": advisory.get("secondary_source_urls", []),
+        "aliases": advisory.get("aliases", []),
+        "secure_code_topics": advisory.get("secure_code_topics", []),
+        "verification_status": advisory.get("verification_status"),
+        "verification_mode": advisory.get("verification_mode"),
+        "artifact_mode": advisory.get("artifact_mode"),
+        "blocked_reason": advisory.get("blocked_reason"),
+        "browser_evidence": advisory.get("browser_evidence", {}),
+    }
+
+
+def _profile_meta(profile: Dict[str, Any]) -> Dict[str, Any]:
+    if not profile:
+        return {}
+    return {
+        "profile_id": profile.get("profile_id"),
+        "vuln_family": profile.get("vuln_family"),
+        "provisioning_mode": profile.get("provisioning_mode"),
+        "destructive_risk": profile.get("destructive_risk"),
+        "cleanup_policy": profile.get("cleanup_policy"),
+        "artifact_source": profile.get("artifact_source", {}),
+        "success_criteria": profile.get("success_criteria", []),
+        "seed_actions": profile.get("seed_actions", []),
+        "attack_actions": profile.get("attack_actions", []),
+        "browser_assertions": profile.get("browser_assertions", {}),
+        "allowed_target_types": profile.get("allowed_target_types", []),
+        "required_services": profile.get("required_services", []),
+    }
+
+
+def _reasoning_lines(advisory: Dict[str, Any], profile: Dict[str, Any]) -> List[str]:
+    notes: List[str] = []
+    if advisory.get("summary"):
+        notes.append(advisory["summary"])
+    for key in ("seed_actions", "attack_actions"):
+        for item in profile.get(key, []):
+            message = item.get("message")
+            if message:
+                notes.append(message)
+    for item in profile.get("success_criteria", []):
+        if item:
+            notes.append(item)
+    if advisory.get("blocked_reason"):
+        notes.append(f"Current blocker: {advisory['blocked_reason']}")
+    return unique(notes)
+
+
 def render_run(run: Dict[str, Any]) -> Dict[str, str]:
     run_dir = CASE_RUNS_DIR / run["run_id"]
     ensure_dir(run_dir / "assets")
@@ -205,8 +312,12 @@ def render_dashboard() -> Dict[str, str]:
     ensure_dir(DASHBOARD_DIR)
     advisory_records = load_json_dir(ADVISORIES_DIR)
     runs = load_json_dir(RUNS_DIR)
+    advisory_map = {item["canonical_id"]: item for item in advisory_records if item.get("canonical_id")}
+    profile_map = load_profiles()
     runs_dir = DASHBOARD_DIR / "runs"
+    assets_dir = DASHBOARD_DIR / "assets"
     ensure_dir(runs_dir)
+    ensure_dir(assets_dir)
     for item in runs:
         bundle_dir = Path(item.get("report_refs", {}).get("bundle_dir", ""))
         if not bundle_dir.exists():
@@ -265,6 +376,8 @@ def render_dashboard() -> Dict[str, str]:
     decorated_runs: List[Dict[str, Any]] = []
     for item in recent_runs:
         cloned = dict(item)
+        advisory = advisory_map.get(item["advisory_id"], {})
+        profile = profile_map.get(item["repro_profile_id"], {})
         cloned["dashboard_refs"] = {
             "report_html": f"./runs/{item['run_id']}/report.html",
             "report_md": f"./runs/{item['run_id']}/report.md",
@@ -274,6 +387,29 @@ def render_dashboard() -> Dict[str, str]:
         cloned["browser_links"] = [_dashboard_ref(item, ref) for ref in item.get("browser_refs", [])]
         cloned["container_links"] = [_dashboard_ref(item, ref) for ref in item.get("container_log_refs", [])]
         cloned["request_links"] = [_dashboard_ref(item, ref) for ref in item.get("request_log_refs", [])]
+        cloned["advisory_meta"] = _advisory_meta(advisory)
+        cloned["profile_meta"] = _profile_meta(profile)
+        cloned["reasoning_lines"] = _reasoning_lines(advisory, profile)
+        cloned["progress"] = _progress_counts(item)
+        cloned["artifact_groups"] = [
+            _artifact_group(
+                item,
+                "reports",
+                "Reports",
+                [
+                    cloned["dashboard_refs"]["report_html"],
+                    cloned["dashboard_refs"]["report_md"],
+                    cloned["dashboard_refs"]["timeline"],
+                    cloned["dashboard_refs"]["bundle"],
+                ],
+                use_dashboard_refs=True,
+            ),
+            _artifact_group(item, "compose", "Compose", item.get("compose_refs", [])),
+            _artifact_group(item, "browser", "Browser Evidence", item.get("browser_refs", [])),
+            _artifact_group(item, "container", "Container Logs", item.get("container_log_refs", [])),
+            _artifact_group(item, "requests", "Request Logs", item.get("request_log_refs", [])),
+        ]
+        cloned["artifact_groups"] = [group for group in cloned["artifact_groups"] if group["count"]]
         decorated_runs.append(cloned)
 
     summary = {
@@ -292,6 +428,7 @@ def render_dashboard() -> Dict[str, str]:
             "run_id": item["run_id"],
             "advisory_id": item["advisory_id"],
             "status": item.get("verification_status"),
+            "title": item.get("advisory_meta", {}).get("title"),
             "blocked_reason": item.get("blocked_reason"),
         }
         for item in decorated_runs
@@ -300,100 +437,1264 @@ def render_dashboard() -> Dict[str, str]:
     write_json(DASHBOARD_DIR / "summary.json", summary)
     write_json(DASHBOARD_DIR / "runs.json", decorated_runs)
     write_json(DASHBOARD_DIR / "systems.json", summary["systems"])
+    write_json(DASHBOARD_DIR / "advisories.json", {key: _advisory_meta(value) for key, value in advisory_map.items()})
+    write_json(DASHBOARD_DIR / "profiles.json", {key: _profile_meta(value) for key, value in profile_map.items()})
 
-    html_page = """
-
+    styles_css = """
+:root {
+  --bg: #07111f;
+  --panel: rgba(9, 18, 32, 0.86);
+  --panel-2: rgba(10, 24, 44, 0.92);
+  --panel-soft: rgba(18, 32, 56, 0.74);
+  --border: rgba(137, 171, 214, 0.22);
+  --text: #f7fafc;
+  --muted: #9fb3ca;
+  --accent: #5eead4;
+  --accent-2: #ffb86b;
+  --accent-3: #90cdf4;
+  --danger: #ff7b7b;
+  --warning: #ffd166;
+  --success: #6ee7a5;
+  --shadow: 0 24px 80px rgba(1, 7, 20, 0.45);
+  --radius: 20px;
+}
+
+* { box-sizing: border-box; }
+html, body { margin: 0; min-height: 100%; }
+body {
+  font-family: "IBM Plex Sans", "Avenir Next", "Segoe UI", sans-serif;
+  background:
+    radial-gradient(circle at top left, rgba(94, 234, 212, 0.15), transparent 28%),
+    radial-gradient(circle at top right, rgba(255, 184, 107, 0.18), transparent 22%),
+    linear-gradient(145deg, #050c16 0%, #08111f 44%, #0d1c31 100%);
+  color: var(--text);
+  overflow-x: hidden;
+}
+
+body::before {
+  content: "";
+  position: fixed;
+  inset: 0;
+  pointer-events: none;
+  background-image:
+    linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
+    linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px);
+  background-size: 32px 32px;
+  mask-image: radial-gradient(circle at center, black 36%, transparent 78%);
+  opacity: 0.28;
+}
+
+a { color: var(--accent); text-decoration: none; }
+a:hover { text-decoration: underline; }
+button, input, select {
+  font: inherit;
+}
+
+.dashboard-shell {
+  position: relative;
+  max-width: 1640px;
+  margin: 0 auto;
+  padding: 32px 24px 40px;
+}
+
+.hero {
+  position: sticky;
+  top: 0;
+  z-index: 20;
+  backdrop-filter: blur(18px);
+  background: linear-gradient(180deg, rgba(7, 17, 31, 0.94), rgba(7, 17, 31, 0.75));
+  border: 1px solid var(--border);
+  border-radius: 28px;
+  padding: 24px 24px 20px;
+  box-shadow: var(--shadow);
+}
+
+.hero-grid {
+  display: grid;
+  grid-template-columns: 1.6fr 1fr;
+  gap: 20px;
+  align-items: start;
+}
+
+.eyebrow {
+  display: inline-flex;
+  align-items: center;
+  gap: 8px;
+  color: var(--muted);
+  font-size: 0.88rem;
+  letter-spacing: 0.12em;
+  text-transform: uppercase;
+}
+
+.eyebrow::before {
+  content: "";
+  width: 10px;
+  height: 10px;
+  border-radius: 999px;
+  background: radial-gradient(circle, var(--accent), rgba(94, 234, 212, 0.15));
+  box-shadow: 0 0 24px rgba(94, 234, 212, 0.8);
+  animation: pulse 2.8s ease-in-out infinite;
+}
+
+.hero h1 {
+  margin: 12px 0 10px;
+  font-family: "IBM Plex Serif", "Iowan Old Style", Georgia, serif;
+  font-size: clamp(2rem, 4vw, 3.5rem);
+  line-height: 1.02;
+}
+
+.hero p {
+  margin: 0;
+  color: var(--muted);
+  max-width: 74ch;
+}
+
+.hero-actions {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+  margin-top: 18px;
+}
+
+.chip, .ghost-chip {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  gap: 8px;
+  border-radius: 999px;
+  border: 1px solid var(--border);
+  padding: 10px 14px;
+  background: rgba(255,255,255,0.06);
+  color: var(--text);
+}
+
+.ghost-chip {
+  background: rgba(255,255,255,0.04);
+}
+
+.hero-meta {
+  display: grid;
+  grid-template-columns: repeat(2, minmax(0, 1fr));
+  gap: 14px;
+}
+
+.meta-card, .glass-panel {
+  background: var(--panel);
+  border: 1px solid var(--border);
+  border-radius: var(--radius);
+  box-shadow: var(--shadow);
+}
+
+.meta-card {
+  padding: 18px;
+  min-height: 116px;
+}
+
+.meta-card strong {
+  display: block;
+  color: var(--muted);
+  font-size: 0.84rem;
+  letter-spacing: 0.08em;
+  text-transform: uppercase;
+}
+
+.meta-card span {
+  display: block;
+  margin-top: 10px;
+  font-size: 2rem;
+  font-weight: 700;
+}
+
+.workspace {
+  display: grid;
+  grid-template-columns: 420px minmax(0, 1fr);
+  gap: 20px;
+  margin-top: 22px;
+}
+
+.sidebar {
+  display: flex;
+  flex-direction: column;
+  gap: 18px;
+}
+
+.panel-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 12px;
+  margin-bottom: 16px;
+}
+
+.panel-header h2, .panel-header h3 {
+  margin: 0;
+  font-size: 1rem;
+  letter-spacing: 0.04em;
+  text-transform: uppercase;
+  color: var(--muted);
+}
+
+.glass-panel {
+  padding: 18px;
+  background:
+    linear-gradient(180deg, rgba(255,255,255,0.04), transparent 35%),
+    var(--panel);
+}
+
+.filters {
+  display: grid;
+  gap: 12px;
+}
+
+.filters label {
+  display: grid;
+  gap: 6px;
+  color: var(--muted);
+  font-size: 0.9rem;
+}
+
+.filters input, .filters select {
+  width: 100%;
+  background: rgba(255,255,255,0.05);
+  color: var(--text);
+  border: 1px solid rgba(159, 179, 202, 0.18);
+  border-radius: 14px;
+  padding: 12px 14px;
+}
+
+.run-list {
+  display: grid;
+  gap: 12px;
+  max-height: calc(100vh - 460px);
+  overflow: auto;
+  padding-right: 4px;
+}
+
+.run-card {
+  width: 100%;
+  text-align: left;
+  padding: 16px;
+  border-radius: 18px;
+  border: 1px solid rgba(159, 179, 202, 0.14);
+  background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.03));
+  color: var(--text);
+  cursor: pointer;
+  transition: transform 180ms ease, border-color 180ms ease, background 180ms ease;
+}
+
+.run-card:hover, .run-card.is-active {
+  transform: translateY(-1px);
+  border-color: rgba(94, 234, 212, 0.42);
+  background: linear-gradient(180deg, rgba(94, 234, 212, 0.14), rgba(255,255,255,0.05));
+}
+
+.run-card-top, .flex-row {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 12px;
+}
+
+.run-card h4 {
+  margin: 10px 0 8px;
+  font-size: 1rem;
+  line-height: 1.35;
+}
+
+.mini-muted {
+  color: var(--muted);
+  font-size: 0.86rem;
+}
+
+.status-pill {
+  display: inline-flex;
+  align-items: center;
+  gap: 7px;
+  border-radius: 999px;
+  padding: 6px 10px;
+  font-size: 0.82rem;
+  font-weight: 700;
+  text-transform: uppercase;
+  letter-spacing: 0.06em;
+  border: 1px solid transparent;
+}
+
+.status-pill::before {
+  content: "";
+  width: 8px;
+  height: 8px;
+  border-radius: 999px;
+  background: currentColor;
+  box-shadow: 0 0 16px currentColor;
+}
+
+.status-blocked-artifact, .status-blocked-destructive {
+  color: var(--danger);
+  background: rgba(255, 123, 123, 0.14);
+  border-color: rgba(255, 123, 123, 0.24);
+}
+
+.status-triage-manual, .status-suspected {
+  color: var(--warning);
+  background: rgba(255, 209, 102, 0.14);
+  border-color: rgba(255, 209, 102, 0.24);
+}
+
+.status-verified-real {
+  color: var(--success);
+  background: rgba(110, 231, 165, 0.14);
+  border-color: rgba(110, 231, 165, 0.24);
+}
+
+.status-verified-synthetic {
+  color: var(--accent-3);
+  background: rgba(144, 205, 244, 0.14);
+  border-color: rgba(144, 205, 244, 0.24);
+}
+
+.status-default {
+  color: var(--accent);
+  background: rgba(94, 234, 212, 0.14);
+  border-color: rgba(94, 234, 212, 0.24);
+}
+
+.detail-view {
+  display: grid;
+  gap: 18px;
+}
+
+.detail-hero {
+  padding: 22px;
+  overflow: hidden;
+  position: relative;
+}
+
+.detail-hero::after {
+  content: "";
+  position: absolute;
+  inset: auto -20% -55% 25%;
+  height: 220px;
+  background: radial-gradient(circle, rgba(94, 234, 212, 0.2), transparent 55%);
+  pointer-events: none;
+}
+
+.detail-headline {
+  margin: 8px 0 12px;
+  font-family: "IBM Plex Serif", "Iowan Old Style", Georgia, serif;
+  font-size: clamp(1.6rem, 3vw, 2.8rem);
+  line-height: 1.08;
+}
+
+.tag-row, .link-row, .artifact-row {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+.tag {
+  display: inline-flex;
+  align-items: center;
+  padding: 7px 10px;
+  border-radius: 999px;
+  background: rgba(255,255,255,0.06);
+  border: 1px solid rgba(159, 179, 202, 0.18);
+  color: var(--text);
+  font-size: 0.86rem;
+}
+
+.stat-grid {
+  display: grid;
+  grid-template-columns: repeat(4, minmax(0, 1fr));
+  gap: 12px;
+  margin-top: 18px;
+}
+
+.stat-card {
+  padding: 14px;
+  border-radius: 16px;
+  background: rgba(255,255,255,0.04);
+  border: 1px solid rgba(159, 179, 202, 0.16);
+}
+
+.stat-card strong {
+  display: block;
+  color: var(--muted);
+  font-size: 0.78rem;
+  text-transform: uppercase;
+  letter-spacing: 0.08em;
+}
+
+.stat-card span {
+  display: block;
+  margin-top: 10px;
+  font-size: 1.15rem;
+  font-weight: 700;
+}
+
+.detail-grid {
+  display: grid;
+  grid-template-columns: minmax(0, 1fr) 360px;
+  gap: 18px;
+}
+
+.stack {
+  display: grid;
+  gap: 18px;
+}
+
+.accordion {
+  overflow: hidden;
+}
+
+.accordion > summary {
+  list-style: none;
+  cursor: pointer;
+  padding: 18px 20px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 12px;
+}
+
+.accordion > summary::-webkit-details-marker { display: none; }
+.accordion > summary span {
+  font-size: 1rem;
+  text-transform: uppercase;
+  letter-spacing: 0.08em;
+  color: var(--muted);
+}
+
+.accordion .accordion-content {
+  padding: 0 20px 20px;
+  border-top: 1px solid rgba(159, 179, 202, 0.12);
+}
+
+.timeline-list {
+  display: grid;
+  gap: 12px;
+}
+
+.timeline-item {
+  display: grid;
+  grid-template-columns: 120px 180px minmax(0, 1fr);
+  gap: 12px;
+  padding: 12px 0;
+  border-bottom: 1px solid rgba(159, 179, 202, 0.12);
+}
+
+.timeline-item:last-child {
+  border-bottom: 0;
+}
+
+.timeline-step {
+  font-weight: 700;
+}
+
+.artifact-group {
+  margin-bottom: 14px;
+}
+
+.artifact-group h4 {
+  margin: 0 0 10px;
+  color: var(--muted);
+  font-size: 0.88rem;
+  text-transform: uppercase;
+  letter-spacing: 0.08em;
+}
+
+.artifact-button {
+  display: inline-flex;
+  align-items: center;
+  gap: 8px;
+  margin: 0 10px 10px 0;
+  padding: 10px 12px;
+  border-radius: 14px;
+  border: 1px solid rgba(159, 179, 202, 0.16);
+  background: rgba(255,255,255,0.05);
+  color: var(--text);
+  cursor: pointer;
+}
+
+.artifact-button:hover, .artifact-button.is-active {
+  border-color: rgba(94, 234, 212, 0.4);
+  background: rgba(94, 234, 212, 0.12);
+}
+
+.log-viewer {
+  min-height: 420px;
+  display: grid;
+  gap: 14px;
+}
+
+.viewer-toolbar {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  gap: 10px;
+  align-items: center;
+}
+
+.viewer-frame {
+  background: rgba(2, 8, 22, 0.88);
+  border: 1px solid rgba(159, 179, 202, 0.18);
+  border-radius: 16px;
+  min-height: 300px;
+  overflow: hidden;
+}
+
+.viewer-frame pre {
+  margin: 0;
+  padding: 18px;
+  max-height: 560px;
+  overflow: auto;
+  font-family: "IBM Plex Mono", "SFMono-Regular", "Menlo", monospace;
+  font-size: 0.88rem;
+  line-height: 1.6;
+  color: #d6e5f5;
+  white-space: pre-wrap;
+}
+
+.viewer-frame img {
+  display: block;
+  width: 100%;
+  height: auto;
+}
+
+.gallery {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+  gap: 14px;
+}
+
+.gallery button {
+  all: unset;
+  cursor: pointer;
+  border-radius: 18px;
+  overflow: hidden;
+  border: 1px solid rgba(159, 179, 202, 0.18);
+  background: rgba(255,255,255,0.04);
+}
+
+.gallery img {
+  display: block;
+  width: 100%;
+  aspect-ratio: 4 / 3;
+  object-fit: cover;
+}
+
+.gallery figcaption {
+  padding: 10px 12px 14px;
+  color: var(--muted);
+  font-size: 0.84rem;
+}
+
+.failure-callout {
+  padding: 16px 18px;
+  border-radius: 18px;
+  border: 1px solid rgba(255, 123, 123, 0.2);
+  background: rgba(255, 123, 123, 0.09);
+}
+
+.json-block {
+  background: rgba(2, 8, 22, 0.72);
+  border-radius: 16px;
+  border: 1px solid rgba(159, 179, 202, 0.14);
+  padding: 16px;
+  overflow: auto;
+  font-family: "IBM Plex Mono", "SFMono-Regular", monospace;
+  font-size: 0.84rem;
+  line-height: 1.55;
+  color: #c9d8e8;
+}
+
+.empty-state {
+  padding: 40px 24px;
+  text-align: center;
+  color: var(--muted);
+}
+
+.failure-feed {
+  display: grid;
+  gap: 10px;
+}
+
+.failure-item {
+  padding: 12px 14px;
+  border-radius: 16px;
+  background: rgba(255,255,255,0.04);
+  border: 1px solid rgba(159, 179, 202, 0.16);
+}
+
+.system-grid {
+  display: grid;
+  gap: 10px;
+}
+
+.system-card {
+  padding: 14px 16px;
+  border-radius: 16px;
+  background: rgba(255,255,255,0.04);
+  border: 1px solid rgba(159, 179, 202, 0.14);
+}
+
+.meter {
+  position: relative;
+  height: 10px;
+  border-radius: 999px;
+  background: rgba(255,255,255,0.08);
+  overflow: hidden;
+  margin-top: 10px;
+}
+
+.meter > span {
+  position: absolute;
+  inset: 0 auto 0 0;
+  width: var(--fill, 0%);
+  background: linear-gradient(90deg, var(--accent), var(--accent-2));
+  border-radius: inherit;
+}
+
+.sync-indicator {
+  display: inline-flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.sync-indicator strong {
+  color: var(--text);
+}
+
+.dot {
+  width: 10px;
+  height: 10px;
+  border-radius: 999px;
+  background: var(--accent);
+  box-shadow: 0 0 18px rgba(94, 234, 212, 0.8);
+}
+
+@keyframes pulse {
+  0%, 100% { transform: scale(1); opacity: 0.88; }
+  50% { transform: scale(1.35); opacity: 1; }
+}
+
+@media (max-width: 1280px) {
+  .workspace, .detail-grid, .hero-grid {
+    grid-template-columns: 1fr;
+  }
+
+  .stat-grid {
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+  }
+}
+
+@media (max-width: 760px) {
+  .dashboard-shell {
+    padding: 18px 14px 32px;
+  }
+
+  .hero {
+    position: static;
+  }
+
+  .stat-grid, .hero-meta {
+    grid-template-columns: 1fr;
+  }
+
+  .timeline-item {
+    grid-template-columns: 1fr;
+  }
+}
+"""
+    write_text(assets_dir / "styles.css", styles_css)
+
+    app_js = """
+const state = {
+  summary: null,
+  runs: [],
+  systems: [],
+  advisories: {},
+  profiles: {},
+  selectedRunId: null,
+  selectedArtifact: null,
+  filters: { search: "", system: "", status: "", family: "" },
+  autoRefresh: true,
+  refreshMs: 5000,
+  refreshHandle: null,
+};
+
+const $ = (id) => document.getElementById(id);
+const statusClass = (status) => `status-pill ${({
+  "blocked-artifact": "status-blocked-artifact",
+  "blocked-destructive": "status-blocked-destructive",
+  "triage-manual": "status-triage-manual",
+  "verified-real": "status-verified-real",
+  "verified-synthetic": "status-verified-synthetic",
+  "suspected": "status-suspected",
+  "completed": "status-verified-real",
+  "failed": "status-blocked-artifact",
+  "skipped": "status-triage-manual"
+})[status] || "status-default"}`;
+
+function escapeHtml(value) {
+  return String(value ?? "")
+    .replaceAll("&", "&")
+    .replaceAll("<", "<")
+    .replaceAll(">", ">")
+    .replaceAll('"', """);
+}
+
+function timeAgo(value) {
+  if (!value) return "-";
+  const diff = Date.now() - new Date(value).getTime();
+  if (Number.isNaN(diff)) return value;
+  const seconds = Math.floor(diff / 1000);
+  if (seconds < 60) return `${seconds}s ago`;
+  const minutes = Math.floor(seconds / 60);
+  if (minutes < 60) return `${minutes}m ago`;
+  const hours = Math.floor(minutes / 60);
+  if (hours < 24) return `${hours}h ago`;
+  const days = Math.floor(hours / 24);
+  return `${days}d ago`;
+}
+
+async function fetchJson(url) {
+  const response = await fetch(`${url}?t=${Date.now()}`, { cache: "no-store" });
+  if (!response.ok) {
+    throw new Error(`${url} -> ${response.status}`);
+  }
+  return response.json();
+}
+
+async function loadData(preserveSelection = true) {
+  $("syncState").innerHTML = `Refreshing${new Date().toLocaleTimeString()}`;
+  const previousRun = state.selectedRunId;
+  try {
+    const [summary, runs, systems, advisories, profiles] = await Promise.all([
+      fetchJson("./summary.json"),
+      fetchJson("./runs.json"),
+      fetchJson("./systems.json"),
+      fetchJson("./advisories.json"),
+      fetchJson("./profiles.json"),
+    ]);
+    state.summary = summary;
+    state.runs = runs;
+    state.systems = systems;
+    state.advisories = advisories;
+    state.profiles = profiles;
+    hydrateFilterOptions();
+
+    const hashRun = location.hash.startsWith("#run=") ? location.hash.replace("#run=", "") : null;
+    const selectedCandidate = preserveSelection ? (hashRun || previousRun) : hashRun;
+    if (selectedCandidate && runs.some((item) => item.run_id === selectedCandidate)) {
+      state.selectedRunId = selectedCandidate;
+    } else {
+      state.selectedRunId = runs[0]?.run_id || null;
+    }
+
+    renderDashboard();
+    $("syncState").innerHTML = `Live${summary.generated_at || new Date().toISOString()}`;
+  } catch (error) {
+    $("syncState").innerHTML = `Load Failed${escapeHtml(error.message)}`;
+    $("runList").innerHTML = `
Dashboard load failed: ${escapeHtml(error.message)}
`; + $("detailRoot").innerHTML = `
Unable to load dashboard data. Check generated JSON and local static server state.
`; + } +} + +function filteredRuns() { + return state.runs.filter((item) => { + if (state.filters.system && item.system_id !== state.filters.system) return false; + if (state.filters.status && item.verification_status !== state.filters.status) return false; + if (state.filters.family && item.repro_profile_id !== state.filters.family) return false; + if (!state.filters.search) return true; + const advisoryTitle = item.advisory_meta?.title || ""; + const haystack = [item.run_id, item.advisory_id, item.system_id, item.repro_profile_id, advisoryTitle] + .join(" ") + .toLowerCase(); + return haystack.includes(state.filters.search); + }); +} + +function renderMetrics() { + const metrics = [ + { label: "Advisories", value: state.summary?.advisory_count ?? 0 }, + { label: "Run Bundles", value: state.summary?.run_count ?? 0 }, + ...Object.entries(state.summary?.statuses || {}).map(([label, value]) => ({ label, value })), + ]; + $("metrics").innerHTML = metrics + .map((item) => `
${escapeHtml(item.label)}${escapeHtml(item.value)}
`) + .join(""); +} + +function renderSystemCoverage() { + $("systemCoverage").innerHTML = state.systems + .map((system) => { + const total = Math.max(system.total || 0, 1); + const verified = (system.verified_real || 0) + (system.verified_synthetic || 0); + const fill = Math.round((verified / total) * 100); + return ` +
+
+ ${escapeHtml(system.display_name || system.system_id)} + ${escapeHtml(system.browser_present || 0)}/${escapeHtml(system.browser_required || 0)} browser +
+
${escapeHtml(system.system_id)} · latest ${escapeHtml(system.latest_update || "-")}
+
+ real ${escapeHtml(system.verified_real || 0)} + synthetic ${escapeHtml(system.verified_synthetic || 0)} + blocked ${escapeHtml(system.blocked || 0)} + manual ${escapeHtml(system.manual || 0)} +
+
+
+ `; + }) + .join(""); +} + +function renderFailures() { + const failures = state.summary?.recent_failures || []; + $("failureFeed").innerHTML = failures.length + ? failures + .map((item) => ` +
+
+ ${escapeHtml(item.run_id)} + ${escapeHtml(item.status)} +
+
${escapeHtml(item.title || item.advisory_id)}
+
${escapeHtml(item.blocked_reason || "-")}
+
+ `) + .join("") + : `
No recent blockers.
`; +} + +function renderRunList() { + const filtered = filteredRuns(); + $("runCount").textContent = `${filtered.length} shown`; + $("runList").innerHTML = filtered.length + ? filtered + .map((item) => { + const active = item.run_id === state.selectedRunId ? "is-active" : ""; + const title = item.advisory_meta?.title || item.advisory_id; + const reasoning = item.reasoning_lines?.[0] || item.blocked_reason || ""; + return ` + + `; + }) + .join("") + : `
No runs match the current filters.
`; + + document.querySelectorAll("[data-run-id]").forEach((button) => { + button.addEventListener("click", () => { + state.selectedRunId = button.dataset.runId; + location.hash = `run=${state.selectedRunId}`; + renderRunList(); + renderDetail(); + }); + }); +} + +function renderDashboard() { + renderMetrics(); + renderSystemCoverage(); + renderFailures(); + renderRunList(); + renderDetail(); +} + +function setFilterListeners() { + [["searchInput", "search"], ["systemFilter", "system"], ["statusFilter", "status"], ["familyFilter", "family"]].forEach(([id, key]) => { + $(id).addEventListener("input", (event) => { + state.filters[key] = String(event.target.value || "").trim().toLowerCase(); + if (key !== "search") { + state.filters[key] = String(event.target.value || ""); + } + renderRunList(); + }); + }); +} + +function hydrateFilterOptions() { + const distinct = (items) => [...new Set(items.filter(Boolean))].sort(); + const patchOptions = (id, values) => { + const control = $(id); + const current = control.value; + control.innerHTML = control.dataset.base; + control.innerHTML += distinct(values).map((value) => ``).join(""); + control.value = current; + }; + patchOptions("systemFilter", state.runs.map((item) => item.system_id)); + patchOptions("statusFilter", state.runs.map((item) => item.verification_status)); + patchOptions("familyFilter", state.runs.map((item) => item.repro_profile_id)); +} + +function defaultArtifact(run) { + const preference = ["requests", "container", "browser", "compose", "reports"]; + for (const key of preference) { + const group = (run.artifact_groups || []).find((item) => item.key === key && item.items?.length); + if (!group) continue; + const preferredText = group.items.find((item) => item.kind === "text"); + return preferredText || group.items[0]; + } + return null; +} + +async function openArtifact(href, label, kind) { + state.selectedArtifact = { href, label, kind }; + document.querySelectorAll(".artifact-button").forEach((button) => { + button.classList.toggle("is-active", button.dataset.href === href); + }); + $("artifactLabel").textContent = label; + $("artifactOpen").href = href; + $("artifactMeta").textContent = href; + try { + if (kind === "image") { + $("artifactViewer").innerHTML = `${escapeHtml(label)}`; + return; + } + if (href.endsWith(".html")) { + $("artifactViewer").innerHTML = ``; + return; + } + const response = await fetch(`${href}?t=${Date.now()}`, { cache: "no-store" }); + if (!response.ok) throw new Error(`${href} -> ${response.status}`); + const text = await response.text(); + let formatted = text; + if (href.endsWith(".json")) { + try { + formatted = JSON.stringify(JSON.parse(text), null, 2); + } catch (_error) { + } + } + $("artifactViewer").innerHTML = `
${escapeHtml(formatted)}
`; + } catch (error) { + $("artifactViewer").innerHTML = `
Artifact load failed: ${escapeHtml(error.message)}
`; + } +} + +function renderDetail() { + const run = state.runs.find((item) => item.run_id === state.selectedRunId); + if (!run) { + $("detailRoot").innerHTML = `
Select a run to inspect full timeline, logs, sources, and reasoning.
`; + return; + } + + const advisory = run.advisory_meta || {}; + const profile = run.profile_meta || {}; + const screenshotItems = (run.artifact_groups || []) + .find((group) => group.key === "browser") + ?.items.filter((item) => item.kind === "image") || []; + + $("detailRoot").innerHTML = ` +
+
Local Verification Workspace
+
+ ${escapeHtml(run.verification_status)} +
+ ${escapeHtml(run.system_id)} + ${escapeHtml(run.repro_profile_id)} + ${escapeHtml(run.artifact_mode)} + ${escapeHtml(run.verification_mode)} +
+
+

${escapeHtml(advisory.title || run.advisory_id)}

+

${escapeHtml(advisory.summary || "No summary available.")}

+ +
+
Timeline Steps${escapeHtml(run.timeline?.length || 0)}
+
Artifacts${escapeHtml((run.artifact_groups || []).reduce((sum, group) => sum + group.count, 0))}
+
Browser${run.browser_evidence?.present ? "Ready" : "Missing"}
+
Finished${escapeHtml(timeAgo(run.finished_at))}
+
+
+ +
+
+
+ Progress Timeline${escapeHtml(run.timeline?.length || 0)} steps +
+
+ completed ${escapeHtml(run.progress?.completed || 0)} + blocked ${escapeHtml(run.progress?.blocked || 0)} + skipped ${escapeHtml(run.progress?.skipped || 0)} + failed ${escapeHtml(run.progress?.failed || 0)} +
+
+ ${(run.timeline || []).map((item) => ` +
+
${escapeHtml(item.at || "-")}
+
${escapeHtml(item.step || "-")}
+
+
${escapeHtml(item.status || "unknown")}
+
${escapeHtml(item.detail || "-")}
+
+
+ `).join("") || `
No timeline items available.
`} +
+
+
+ +
+ Attack Plan & Reasoning${escapeHtml(profile.vuln_family || "unknown")} +
+ ${run.blocked_reason ? `
Failure reason
${escapeHtml(run.blocked_reason)}
` : ""} +
+ destructive risk ${escapeHtml(profile.destructive_risk || "-")} + cleanup ${escapeHtml(profile.cleanup_policy || "-")} + targets ${(profile.allowed_target_types || []).join(", ") || "-"} +
+
+ ${(run.reasoning_lines || []).map((line) => `
${escapeHtml(line)}
`).join("")} +
+
+ ${(profile.success_criteria || []).map((line) => `${escapeHtml(line)}`).join("")} +
+
+
+ +
+ Evidence Explorer${escapeHtml((run.artifact_groups || []).length)} groups +
+ ${(run.artifact_groups || []).map((group) => ` +
+

${escapeHtml(group.label)} · ${escapeHtml(group.count)}

+
+ ${group.items.map((item) => ` + + `).join("")} +
+
+ `).join("") || `
No artifacts linked for this run.
`} + ${screenshotItems.length ? ` + + ` : ""} +
+
+ +
+ Live Log Viewer${state.selectedArtifact ? "active" : "idle"} +
+
+
+
+ ${escapeHtml(state.selectedArtifact?.label || "Select an artifact")} +
${escapeHtml(state.selectedArtifact?.href || "Artifacts and logs can be previewed here.")}
+
+
+ Open artifact + +
+
+
Select a report, log, JSON, screenshot, or timeline file to preview it here.
+
+
+
+
+ +
+
+ Sources & Fix Topics${escapeHtml((advisory.secondary_source_urls || []).length + (advisory.official_source_url ? 1 : 0))} links +
+
+ ${(advisory.aliases || []).map((alias) => `${escapeHtml(alias)}`).join("")} +
+
+ ${advisory.official_source_url ? `${escapeHtml(advisory.official_source_url)}` : `
No official source linked.
`} + ${(advisory.secondary_source_urls || []).map((ref) => `${escapeHtml(ref)}`).join("")} +
+
+ ${(advisory.secure_code_topics || []).map((topic) => `${escapeHtml(topic)}`).join("")} +
+
+
+ +
+ Run JSONraw +
${escapeHtml(JSON.stringify(run, null, 2))}
+
+ +
+ Advisory JSONraw +
${escapeHtml(JSON.stringify(advisory, null, 2))}
+
+ +
+ Profile JSONraw +
${escapeHtml(JSON.stringify(profile, null, 2))}
+
+
+
+ `; + + document.querySelectorAll(".artifact-button").forEach((button) => { + button.addEventListener("click", () => openArtifact(button.dataset.href, button.dataset.label, button.dataset.kind)); + }); + + $("refreshArtifact")?.addEventListener("click", () => { + if (state.selectedArtifact) { + openArtifact(state.selectedArtifact.href, state.selectedArtifact.label, state.selectedArtifact.kind); + } + }); + + if (!state.selectedArtifact || !(run.artifact_groups || []).some((group) => group.items.some((item) => item.href === state.selectedArtifact.href))) { + const artifact = defaultArtifact(run); + if (artifact) { + openArtifact(artifact.href, artifact.label, artifact.kind); + } + } else { + openArtifact(state.selectedArtifact.href, state.selectedArtifact.label, state.selectedArtifact.kind); + } +} + +function attachGlobalActions() { + $("searchInput").addEventListener("input", (event) => { + state.filters.search = String(event.target.value || "").trim().toLowerCase(); + renderRunList(); + }); + [["systemFilter", "system"], ["statusFilter", "status"], ["familyFilter", "family"]].forEach(([id, key]) => { + $(id).addEventListener("input", (event) => { + state.filters[key] = String(event.target.value || ""); + renderRunList(); + }); + }); + $("refreshDashboard").addEventListener("click", () => loadData(false)); + $("autoRefresh").addEventListener("change", (event) => { + state.autoRefresh = Boolean(event.target.checked); + startRefreshLoop(); + }); +} + +function startRefreshLoop() { + if (state.refreshHandle) { + clearInterval(state.refreshHandle); + state.refreshHandle = null; + } + if (!state.autoRefresh) return; + state.refreshHandle = setInterval(() => loadData(true), state.refreshMs); +} + +async function init() { + ["systemFilter", "statusFilter", "familyFilter"].forEach((id) => { + $(id).dataset.base = $(id).innerHTML; + }); + attachGlobalActions(); + await loadData(false); + startRefreshLoop(); + window.addEventListener("hashchange", () => loadData(false)); +} + +document.addEventListener("DOMContentLoaded", init); +""" + write_text(assets_dir / "app.js", app_js) + + html_page = """ + + - websafe dashboard - + + websafe authorized lab dashboard + -

websafe Local Lab Dashboard

-

LAB ONLY | AUTHORIZED TARGETS ONLY | 本地静态看板

-
-

System Coverage

- - - -
SystemTotalVerified RealVerified SyntheticBlockedManualBrowserLatest
-

Recent Runs

-
- - - - +
+
+
+
+
Authorized Lab Dashboard
+

本地攻防实证工作台

+

面向授权实验场景的本地静态前端。聚合 advisory、run bundle、日志、浏览器证据、失败原因、利用思路与源头信息,并支持可折叠细节与自动刷新。

+
+ + + Open Summary JSON +
+
+
+
+

Sync State

+
BootingLoading generated JSON
+
+
+
+
+
+ +
+ + +
+
Select a run to inspect full details.
+
+
- - - -
RunSystemAdvisoryStatusModeProfileFinishedArtifacts
- + """