From 079b8b94929c4b01b1d9874e6bf9ed8a3957fea4 Mon Sep 17 00:00:00 2001 From: Ricearoni1245 Date: Sun, 1 Mar 2026 20:46:47 -0600 Subject: [PATCH] chore: root commit of OWSAP security testing/tightening --- .env | 7 +- .env.example | 5 + .gitea/workflows/deploy.yml | 15 +- .gitea/workflows/security.yml | 54 ++++ Caddyfile.dev | 2 + Caddyfile.prod | 2 + deploy/nginx/skymoneybudget.com.conf | 2 + docker-compose.yml | 4 +- scripts/backup.sh | 4 + scripts/restore.sh | 25 ++ .../A01-Broken-Access-Control.md | 62 +++++ .../A02-Security-Misconfiguration.md | 89 +++++++ .../A03-Software-Supply-Chain-Failures.md | 77 ++++++ .../A04-Cryptographic-Failures.md | 71 +++++ tests-results-for-OWASP/A05-Injection.md | 50 ++++ .../A06-Insecure-Design.md | 54 ++++ ...ntification-and-Authentication-Failures.md | 70 +++++ ...08-Software-and-Data-Integrity-Failures.md | 49 ++++ ...ecurity-Logging-and-Monitoring-Failures.md | 59 +++++ .../A10-Server-Side-Request-Forgery.md | 50 ++++ tests-results-for-OWASP/README.md | 40 +++ .../evidence-log-template.md | 70 +++++ .../post-deployment-verification-checklist.md | 107 ++++++++ .../residual-risk-backlog.md | 26 ++ web/package-lock.json | 244 ++++++++++-------- 25 files changed, 1131 insertions(+), 107 deletions(-) create mode 100644 .gitea/workflows/security.yml create mode 100644 tests-results-for-OWASP/A01-Broken-Access-Control.md create mode 100644 tests-results-for-OWASP/A02-Security-Misconfiguration.md create mode 100644 tests-results-for-OWASP/A03-Software-Supply-Chain-Failures.md create mode 100644 tests-results-for-OWASP/A04-Cryptographic-Failures.md create mode 100644 tests-results-for-OWASP/A05-Injection.md create mode 100644 tests-results-for-OWASP/A06-Insecure-Design.md create mode 100644 tests-results-for-OWASP/A07-Identification-and-Authentication-Failures.md create mode 100644 tests-results-for-OWASP/A08-Software-and-Data-Integrity-Failures.md create mode 100644 tests-results-for-OWASP/A09-Security-Logging-and-Monitoring-Failures.md create mode 100644 tests-results-for-OWASP/A10-Server-Side-Request-Forgery.md create mode 100644 tests-results-for-OWASP/README.md create mode 100644 tests-results-for-OWASP/evidence-log-template.md create mode 100644 tests-results-for-OWASP/post-deployment-verification-checklist.md create mode 100644 tests-results-for-OWASP/residual-risk-backlog.md diff --git a/.env b/.env index 44cfbf5..f65c354 100644 --- a/.env +++ b/.env @@ -32,4 +32,9 @@ EMAIL_REPLY_TO=support@skymoneybudget.com UPDATE_NOTICE_VERSION=1 UPDATE_NOTICE_TITLE=SkyMoney Update -UPDATE_NOTICE_BODY=We added email verification and account-delete confirmation \ No newline at end of file +UPDATE_NOTICE_BODY=We added email verification and account-delete confirmation +ALLOW_INSECURE_AUTH_FOR_DEV=false +JWT_ISSUER=skymoney-api +JWT_AUDIENCE=skymoney-web +AUTH_MAX_FAILED_ATTEMPTS=5 +AUTH_LOCKOUT_WINDOW_MS=900000 \ No newline at end of file diff --git a/.env.example b/.env.example index 54e16ef..3ba1ae1 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,7 @@ PORT=8080 CORS_ORIGIN=http://localhost:5173 CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173,https://skymoneybudget.com AUTH_DISABLED=false +ALLOW_INSECURE_AUTH_FOR_DEV=false SEED_DEFAULT_BUDGET=false ROLLOVER_SCHEDULE_CRON=0 6 * * * APP_ORIGIN=http://localhost:5173 @@ -21,8 +22,12 @@ ADMIN_DATABASE_URL=postgres://postgres:change-me@127.0.0.1:5432/postgres # Auth secrets (min 32 chars) JWT_SECRET=replace-with-32+-chars +JWT_ISSUER=skymoney-api +JWT_AUDIENCE=skymoney-web COOKIE_SECRET=replace-with-32+-chars COOKIE_DOMAIN=skymoneybudget.com +AUTH_MAX_FAILED_ATTEMPTS=5 +AUTH_LOCKOUT_WINDOW_MS=900000 # Email (verification + delete confirmation) SMTP_HOST=smtp.example.com diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 54d80d1..c8adbbd 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -8,12 +8,21 @@ jobs: deploy: runs-on: vps-host steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4.2.2 + + - name: Supply chain checks (production dependencies) + run: | + set -euo pipefail + cd api + npm ci + npm audit --omit=dev --audit-level=high + cd ../web + npm ci + npm audit --omit=dev --audit-level=high - name: Build Web run: | cd web - npm ci npm run build - name: Deploy with Docker Compose @@ -48,4 +57,4 @@ jobs: sudo docker-compose exec -T api npx prisma migrate deploy - name: Reload Nginx - run: sudo systemctl reload nginx \ No newline at end of file + run: sudo systemctl reload nginx diff --git a/.gitea/workflows/security.yml b/.gitea/workflows/security.yml new file mode 100644 index 0000000..84e7969 --- /dev/null +++ b/.gitea/workflows/security.yml @@ -0,0 +1,54 @@ +name: Security Tests + +on: + pull_request: + push: + branches: [main] + +jobs: + security-non-db: + runs-on: vps-host + steps: + - uses: actions/checkout@v4.2.2 + + - name: Setup Node + uses: actions/setup-node@v4.2.0 + with: + node-version: "20" + cache: "npm" + cache-dependency-path: api/package-lock.json + + - name: Install API dependencies + run: | + cd api + npm ci + + - name: Run OWASP security suite (non-DB) + run: | + cd api + SECURITY_DB_TESTS=0 npx vitest run -c vitest.security.config.ts + + security-db: + if: ${{ secrets.TEST_DATABASE_URL != '' }} + runs-on: vps-host + steps: + - uses: actions/checkout@v4.2.2 + + - name: Setup Node + uses: actions/setup-node@v4.2.0 + with: + node-version: "20" + cache: "npm" + cache-dependency-path: api/package-lock.json + + - name: Install API dependencies + run: | + cd api + npm ci + + - name: Run OWASP security suite (DB-backed) + env: + TEST_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }} + run: | + cd api + SECURITY_DB_TESTS=1 npx vitest run -c vitest.security.config.ts diff --git a/Caddyfile.dev b/Caddyfile.dev index bf130e8..e13498b 100644 --- a/Caddyfile.dev +++ b/Caddyfile.dev @@ -23,6 +23,8 @@ # Helpful headers, even in dev header { X-Content-Type-Options "nosniff" + X-Frame-Options "DENY" + Content-Security-Policy "frame-ancestors 'none'" Referrer-Policy "strict-origin-when-cross-origin" } } diff --git a/Caddyfile.prod b/Caddyfile.prod index 0e9fca0..aa15665 100644 --- a/Caddyfile.prod +++ b/Caddyfile.prod @@ -11,6 +11,8 @@ skymoneybudget.com { header { Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" X-Content-Type-Options "nosniff" + X-Frame-Options "DENY" + Content-Security-Policy "frame-ancestors 'none'" Referrer-Policy "strict-origin-when-cross-origin" } diff --git a/deploy/nginx/skymoneybudget.com.conf b/deploy/nginx/skymoneybudget.com.conf index 51c73e8..435b59d 100644 --- a/deploy/nginx/skymoneybudget.com.conf +++ b/deploy/nginx/skymoneybudget.com.conf @@ -17,6 +17,8 @@ server { # Security headers add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "DENY" always; + add_header Content-Security-Policy "frame-ancestors 'none'" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Static web app diff --git a/docker-compose.yml b/docker-compose.yml index 46250fb..a1e7163 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: volumes: - pgdata:/var/lib/postgresql/data ports: - - "5432:5432" + - "127.0.0.1:5432:5432" restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-app} -d ${POSTGRES_DB:-skymoney}"] @@ -47,7 +47,7 @@ services: depends_on: - postgres ports: - - "8081:8080" + - "127.0.0.1:8081:8080" restart: unless-stopped healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health || exit 1"] diff --git a/scripts/backup.sh b/scripts/backup.sh index a828b67..b489ba6 100644 --- a/scripts/backup.sh +++ b/scripts/backup.sh @@ -19,7 +19,11 @@ mkdir -p "$OUT_DIR" STAMP="$(date +%F_%H%M%S)" OUT_FILE="${OUT_DIR}/skymoney_${STAMP}.dump" +OUT_BASENAME="$(basename "$OUT_FILE")" +OUT_DIR_ABS="$(cd "$OUT_DIR" && pwd)" pg_dump "${BACKUP_DATABASE_URL:-$DATABASE_URL}" -Fc -f "$OUT_FILE" +(cd "$OUT_DIR_ABS" && sha256sum "$OUT_BASENAME" > "${OUT_BASENAME}.sha256") echo "Backup written to: $OUT_FILE" +echo "Checksum written to: ${OUT_FILE}.sha256" diff --git a/scripts/restore.sh b/scripts/restore.sh index 9b8588d..0a7df38 100644 --- a/scripts/restore.sh +++ b/scripts/restore.sh @@ -13,6 +13,26 @@ if [[ -z "${BACKUP_FILE:-}" ]]; then echo "BACKUP_FILE is required." exit 1 fi +if [[ ! -f "$BACKUP_FILE" ]]; then + echo "BACKUP_FILE does not exist: $BACKUP_FILE" + exit 1 +fi + +CHECKSUM_FILE="${BACKUP_FILE}.sha256" +if [[ ! -f "$CHECKSUM_FILE" ]]; then + echo "Missing checksum file: ${CHECKSUM_FILE}" + exit 1 +fi +EXPECTED_HASH="$(awk '{print $1; exit}' "$CHECKSUM_FILE")" +if [[ ! "$EXPECTED_HASH" =~ ^[A-Fa-f0-9]{64}$ ]]; then + echo "Invalid checksum format in: ${CHECKSUM_FILE}" + exit 1 +fi +ACTUAL_HASH="$(sha256sum "$BACKUP_FILE" | awk '{print $1}')" +if [[ "$ACTUAL_HASH" != "$EXPECTED_HASH" ]]; then + echo "Backup checksum verification failed for: ${BACKUP_FILE}" + exit 1 +fi if [[ -z "${DATABASE_URL:-}" ]]; then echo "DATABASE_URL is required." @@ -23,6 +43,11 @@ RESTORE_DB="${RESTORE_DB:-skymoney_restore_test}" RESTORE_URL="${RESTORE_DATABASE_URL:-}" ADMIN_URL="${ADMIN_DATABASE_URL:-$DATABASE_URL}" +if [[ ! "$RESTORE_DB" =~ ^[A-Za-z0-9_]+$ ]]; then + echo "RESTORE_DB must match ^[A-Za-z0-9_]+$" + exit 1 +fi + if [[ -z "$RESTORE_URL" ]]; then echo "RESTORE_DATABASE_URL is required (example: postgresql://user:pass@host:5432/${RESTORE_DB})." exit 1 diff --git a/tests-results-for-OWASP/A01-Broken-Access-Control.md b/tests-results-for-OWASP/A01-Broken-Access-Control.md new file mode 100644 index 0000000..538fa6b --- /dev/null +++ b/tests-results-for-OWASP/A01-Broken-Access-Control.md @@ -0,0 +1,62 @@ +# A01: Broken Access Control + +Last updated: March 1, 2026 + +## Findings + +1. Cross-account delete risk in `/account/confirm-delete`. +2. `AUTH_DISABLED` mode allows header-based impersonation (`x-user-id`) and must be tightly controlled. + +## Fixes implemented + +1. `/account/confirm-delete` is now session-bound: +- Lookup uses `req.userId`. +- Request `email` must match session user's email. +- Mismatch returns `403`. + +2. Insecure auth guard added: +- `AUTH_DISABLED=true` now requires `ALLOW_INSECURE_AUTH_FOR_DEV=true` unless `NODE_ENV=test`. + +3. `/admin/rollover` hardened: +- Still requires `AUTH_DISABLED=true`. +- Now also requires request IP to be internal/private. + +## Test coverage + +1. `api/tests/access-control.account-delete.test.ts` +- Verifies cross-account deletion attempt is denied (`403`). +- Verifies victim account is not deleted. + +2. `api/tests/auth.routes.test.ts` +- Verifies protected route rejects unauthenticated access. +- Verifies spoofed `x-user-id` is rejected when auth is enabled. +- Verifies login/session/logout behavior with CSRF handling. +- Verifies login lockout behavior. + +3. `api/tests/access-control.admin-rollover.test.ts` +- Verifies unauthenticated access to `/admin/rollover` is denied when `AUTH_DISABLED=false`. +- Verifies authenticated access still receives `403` when `AUTH_DISABLED=false`. +- Verifies `/admin/rollover` rejects non-internal client IP when `AUTH_DISABLED=true`. +- Verifies `/admin/rollover` allows internal client IP when `AUTH_DISABLED=true`. + +## Run commands + +From `api/`: + +```bash +npm test -- tests/auth.routes.test.ts tests/access-control.account-delete.test.ts tests/access-control.admin-rollover.test.ts +``` + +## Expected results + +1. All three test files pass. +2. No access granted to protected routes without valid auth cookie/JWT. +3. Spoofed `x-user-id` does not bypass auth when `AUTH_DISABLED=false`. +4. Cross-account delete attempt fails with `403`. +5. `/admin/rollover` remains inaccessible from public/non-internal clients. + +## Production configuration requirements + +1. `AUTH_DISABLED=false` +2. `ALLOW_INSECURE_AUTH_FOR_DEV=false` +3. Strong `JWT_SECRET` and `COOKIE_SECRET` diff --git a/tests-results-for-OWASP/A02-Security-Misconfiguration.md b/tests-results-for-OWASP/A02-Security-Misconfiguration.md new file mode 100644 index 0000000..a4b8c8d --- /dev/null +++ b/tests-results-for-OWASP/A02-Security-Misconfiguration.md @@ -0,0 +1,89 @@ +# A02: Security Misconfiguration + +Last updated: March 1, 2026 + +## Findings addressed + +1. SMTP transport debug logging enabled in all environments. +2. Production CORS had a fail-open branch when configured origins were empty. +3. Missing explicit anti-framing headers at edge. +4. Docker compose exposed Postgres/API on all host interfaces. + +## Fixes implemented + +1. SMTP transport hardening in API: +- `requireTLS` now respects config (`SMTP_REQUIRE_TLS`). +- SMTP debug/logger are disabled in production (`!isProd` only). + +2. CORS production behavior tightened: +- Removed fail-open branch for empty configured origins. +- Production now allows only explicitly configured origins. + +3. Edge header hardening: +- Added `X-Frame-Options: DENY`. +- Added `Content-Security-Policy: frame-ancestors 'none'`. + +4. Compose exposure reduction: +- Bound Postgres and API ports to localhost only. + +## Files changed + +1. `api/src/server.ts` +2. `Caddyfile.prod` +3. `Caddyfile.dev` +4. `deploy/nginx/skymoneybudget.com.conf` +5. `docker-compose.yml` + +## Verification + +### Automated security regression tests + +Command (A01 regression): + +```bash +cd api +npm test -- auth.routes.test.ts access-control.account-delete.test.ts +``` + +Verified output (provided from host run): + +- Test Files: `2 passed (2)` +- Tests: `6 passed (6)` +- Start time: `16:39:35` + +Command (A02 dedicated suite): + +```bash +cd api +npx vitest --run -c vitest.security.config.ts +``` + +Verified output: + +- Test Files: `1 passed (1)` +- Tests: `5 passed (5)` +- Suite: `tests/security-misconfiguration.test.ts` + +Coverage in dedicated suite: + +1. Production CORS allowlist enforcement (allowed origin accepted, denied origin does not receive allow headers). +2. SMTP production mailer options disable debug/logger. +3. Runtime CORS preflight headers validated for allowed origins (`allow-origin`, `allow-credentials`, `vary`). +4. Edge config files contain anti-framing headers (`X-Frame-Options`, `frame-ancestors` CSP). +5. `docker-compose.yml` binds Postgres/API ports to localhost only. + +### Expected operational checks after deploy + +1. Unauthenticated `GET /dashboard` returns `401`. +2. Spoofed `x-user-id` does not bypass auth when `AUTH_DISABLED=false`. +3. `/admin/rollover` remains inaccessible from public network. +4. Response headers include anti-framing policy. + +## Residual notes + +1. Keep production env pinned to: +- `AUTH_DISABLED=false` +- `ALLOW_INSECURE_AUTH_FOR_DEV=false` + +2. Keep CORS origins explicitly configured in production: +- `CORS_ORIGIN` and/or `CORS_ORIGINS`. diff --git a/tests-results-for-OWASP/A03-Software-Supply-Chain-Failures.md b/tests-results-for-OWASP/A03-Software-Supply-Chain-Failures.md new file mode 100644 index 0000000..4e06fce --- /dev/null +++ b/tests-results-for-OWASP/A03-Software-Supply-Chain-Failures.md @@ -0,0 +1,77 @@ +# A03: Software Supply Chain Failures + +Last updated: March 1, 2026 + +## Findings addressed + +1. Production dependency vulnerabilities were present in both API and web lockfiles. +2. Deploy pipeline had no explicit dependency vulnerability gate. + +## Fixes implemented + +1. Dependency remediation: +- Ran `npm audit fix` in `api` and `web`. +- Revalidated production dependencies are clean with `npm audit --omit=dev`. + +2. Pipeline hardening: +- Added supply-chain check step in deploy workflow: + - `npm ci` + `npm audit --omit=dev --audit-level=high` for API and web. +- Updated checkout action from broad major tag to explicit release tag `v4.2.2`. + +## Files changed + +1. `.gitea/workflows/deploy.yml` +2. `api/package-lock.json` +3. `web/package-lock.json` +4. `api/tests/software-supply-chain-failures.test.ts` +5. `api/vitest.security.config.ts` + +## Verification + +### Production dependency vulnerability scans + +Command: + +```bash +cd api +npm audit --omit=dev --audit-level=high +cd ../web +npm audit --omit=dev --audit-level=high +``` + +Verified output: + +- `found 0 vulnerabilities` (api) +- `found 0 vulnerabilities` (web) + +### Workflow policy verification (automated) + +Command: + +```bash +cd api +npx vitest run -c vitest.security.config.ts tests/software-supply-chain-failures.test.ts +``` + +Verified output: + +- Test Files: `1 passed (1)` +- Tests: `2 passed (2)` + +Coverage in policy suite: + +1. Deploy workflow includes dependency gate step for API and web. +2. Workflow requires `npm ci` and `npm audit --omit=dev --audit-level=high` for both projects. +3. `actions/checkout` remains pinned to an explicit release tag. + +## Residual risks (not yet fully eliminated) + +1. Base image tags are still mutable (`node:20-bookworm-slim`, `postgres:15`) and not digest-pinned. +2. `actions/checkout` is pinned to a release tag, not a full commit SHA. +3. No artifact signing/attestation verification (e.g., cosign/SLSA) in current deploy pipeline. + +## Recommended next hardening steps + +1. Pin container images by immutable digest in `Dockerfile`/`docker-compose.yml`. +2. Pin workflow actions to full commit SHAs. +3. Add SBOM generation and signature/attestation verification before deploy. diff --git a/tests-results-for-OWASP/A04-Cryptographic-Failures.md b/tests-results-for-OWASP/A04-Cryptographic-Failures.md new file mode 100644 index 0000000..a7e07d4 --- /dev/null +++ b/tests-results-for-OWASP/A04-Cryptographic-Failures.md @@ -0,0 +1,71 @@ +# A04: Cryptographic Failures + +Last updated: March 1, 2026 + +## Findings addressed + +1. Production origin could be configured as non-HTTPS. +2. JWT configuration did not explicitly constrain issuer/audience/algorithm. +3. Missing explicit env contract for JWT issuer/audience values. + +## Fixes implemented + +1. Production HTTPS origin enforcement: +- Added production guard requiring `APP_ORIGIN` to start with `https://`. + +2. JWT hardening in Fastify: +- Explicit signing algorithm set to `HS256`. +- JWT signing includes configured `iss` and `aud`. +- JWT verification enforces: + - allowed algorithm (`HS256`) + - allowed issuer + - allowed audience + +3. Env schema expanded: +- Added `JWT_ISSUER` and `JWT_AUDIENCE` with secure defaults: + - `skymoney-api` + - `skymoney-web` + +## Files changed + +1. `api/src/env.ts` +2. `api/src/server.ts` +3. `.env.example` +4. `api/tests/cryptographic-failures.test.ts` +5. `api/tests/cryptographic-failures.runtime.test.ts` +6. `api/vitest.security.config.ts` + +## Verification + +Commands: + +```bash +cd api +npx vitest run -c vitest.security.config.ts tests/cryptographic-failures.test.ts tests/cryptographic-failures.runtime.test.ts +``` + +Verified output: + +- Test Files: `2 passed (2)` +- Tests: `7 passed (7)` + +Dedicated A04 checks in `cryptographic-failures.test.ts`: + +1. Production env rejects non-HTTPS `APP_ORIGIN`. +2. JWT issuer/audience defaults resolve as expected. +3. Fastify JWT plugin is registered with explicit algorithm + issuer + audience constraints. + +Runtime adversarial checks in `cryptographic-failures.runtime.test.ts`: + +1. Token with invalid issuer is rejected (`401`). +2. Token with invalid audience is rejected (`401`). +3. Unsigned token (`alg=none`) is rejected (`401`). +4. Token with valid signature + expected issuer/audience is accepted on protected auth refresh route. + +## Required production env values + +1. `APP_ORIGIN=https://...` +2. `JWT_SECRET` strong 32+ chars +3. `COOKIE_SECRET` strong 32+ chars +4. `JWT_ISSUER=skymoney-api` (or your approved value) +5. `JWT_AUDIENCE=skymoney-web` (or your approved value) diff --git a/tests-results-for-OWASP/A05-Injection.md b/tests-results-for-OWASP/A05-Injection.md new file mode 100644 index 0000000..f739c72 --- /dev/null +++ b/tests-results-for-OWASP/A05-Injection.md @@ -0,0 +1,50 @@ +# A05: Injection + +Last updated: March 1, 2026 + +## Findings addressed + +1. API route used unsafe Prisma raw SQL helper (`$queryRawUnsafe`) for `/health/db`. +2. Restore script accepted unvalidated external inputs that could be abused for command/SQL injection scenarios during operational use. + +## Fixes implemented + +1. Replaced unsafe raw SQL helper: +- `app.prisma.$queryRawUnsafe("SELECT now() as now")` +- replaced with tagged, parameter-safe: +- `app.prisma.$queryRaw\`SELECT now() as now\`` + +2. Hardened `scripts/restore.sh` input handling: +- Added required file existence check for `BACKUP_FILE`. +- Added strict identifier validation for `RESTORE_DB` (`^[A-Za-z0-9_]+$`). + +## Files changed + +1. `api/src/server.ts` +2. `scripts/restore.sh` +3. `api/tests/injection-safety.test.ts` +4. `api/vitest.security.config.ts` + +## Verification + +Command: + +```bash +cd api +npx vitest run -c vitest.security.config.ts tests/injection-safety.test.ts +``` + +Verified output: + +- Test Files: `1 passed (1)` +- Tests: `2 passed (2)` + +Dedicated A05 checks in `injection-safety.test.ts`: + +1. Verifies no usage of `$queryRawUnsafe` / `$executeRawUnsafe` across API source files. +2. Executes `scripts/restore.sh` with adversarial `RESTORE_DB` input and verifies restore is rejected before DB commands execute. + +## Residual notes + +1. Main API query paths use Prisma query builder + zod input schemas (reduces SQL injection risk). +2. Operational scripts should remain restricted to trusted operators and environments. diff --git a/tests-results-for-OWASP/A06-Insecure-Design.md b/tests-results-for-OWASP/A06-Insecure-Design.md new file mode 100644 index 0000000..4e84506 --- /dev/null +++ b/tests-results-for-OWASP/A06-Insecure-Design.md @@ -0,0 +1,54 @@ +# A06: Insecure Design + +Last updated: March 1, 2026 + +## Findings addressed + +1. Sensitive email-token workflows did not enforce a cooldown between repeated code requests. +2. Verification and account-deletion flows needed tighter, route-specific throttling to reduce brute-force and abuse risk. + +## Fixes implemented + +1. Added explicit email-token cooldown guard in API: +- New helper `assertEmailTokenCooldown(userId, type, cooldownMs)`. +- Throws structured `429` error with code `EMAIL_TOKEN_COOLDOWN`. +- Sets `Retry-After` header when cooldown is active. + +2. Applied cooldown checks to both token issuance paths: +- `/auth/verify/resend` for signup verification codes. +- `/account/delete-request` for account deletion confirmation codes. + +3. Split and applied stricter rate-limit profiles for sensitive auth/account routes: +- `authRateLimit` on `/auth/register` and `/auth/login`. +- `codeVerificationRateLimit` on `/auth/verify` and `/account/confirm-delete`. +- `codeIssueRateLimit` on `/auth/verify/resend` and `/account/delete-request`. + +## Files changed + +1. `api/src/server.ts` +2. `api/tests/insecure-design.test.ts` +3. `api/vitest.security.config.ts` + +## Verification + +Command: + +```bash +cd api +npx vitest --run -c vitest.security.config.ts +``` + +Verified output: + +- Test Files: `4 passed (4)` +- Tests: `10 passed (10)` + +Dedicated A06 checks in `insecure-design.test.ts`: + +1. Runtime verification resend endpoint enforces cooldown (`/auth/register` issues token, then immediate `/auth/verify/resend` is blocked with `429` + `Retry-After`). +2. Runtime verification delete-request endpoint enforces cooldown (`/account/delete-request` second attempt returns `429` + `Retry-After`). +3. Runtime verification repeated invalid `/auth/verify` requests trigger route throttling (`429`). + +## Residual notes + +1. A06 runtime tests require PostgreSQL availability for user/token persistence paths. diff --git a/tests-results-for-OWASP/A07-Identification-and-Authentication-Failures.md b/tests-results-for-OWASP/A07-Identification-and-Authentication-Failures.md new file mode 100644 index 0000000..511023b --- /dev/null +++ b/tests-results-for-OWASP/A07-Identification-and-Authentication-Failures.md @@ -0,0 +1,70 @@ +# A07: Identification and Authentication Failures + +Last updated: March 1, 2026 + +## Findings addressed + +1. No explicit account lockout after repeated failed login attempts (brute-force risk). +2. Password policy for registration and password updates was too weak (length-only). + +## Fixes implemented + +1. Added login lockout controls: +- Tracks failed login attempts per normalized email in server memory. +- Locks login for a configurable window after threshold failures. +- Returns `429` with code `LOGIN_LOCKED` and `Retry-After` header during lockout. + +2. Added strong password policy: +- Minimum length `12`. +- Requires lowercase, uppercase, number, and symbol. +- Applied to: + - `/auth/register` password. + - `/me/password` new password. + +3. Added auth hardening configuration: +- `AUTH_MAX_FAILED_ATTEMPTS` (default: `5`) +- `AUTH_LOCKOUT_WINDOW_MS` (default: `900000`, 15 minutes) + +## Files changed + +1. `api/src/server.ts` +2. `api/src/env.ts` +3. `.env.example` +4. `api/tests/auth.routes.test.ts` +5. `api/tests/identification-auth-failures.test.ts` +6. `api/vitest.security.config.ts` + +## Verification + +Dedicated security suite command (executed): + +```bash +cd api +npx vitest --run -c vitest.security.config.ts +``` + +Verified output: + +- Test Files: `5 passed (5)` +- Tests: `12 passed (12)` + +Dedicated A07 checks in `identification-auth-failures.test.ts`: + +1. Runtime checks weak password rejection for registration and `/me/password` update flow. +2. Runtime checks lockout threshold/window behavior with configured `AUTH_MAX_FAILED_ATTEMPTS` and verifies `LOGIN_LOCKED` response + `Retry-After`. + +Runtime auth flow checks added in `auth.routes.test.ts`: + +1. Rejects weak passwords on registration. +2. Locks login after repeated failed attempts. + +Run this in an environment with PostgreSQL running to verify runtime behavior: + +```bash +cd api +npm test -- tests/auth.routes.test.ts tests/identification-auth-failures.test.ts +``` + +## Residual notes + +1. Current lockout state is in-memory per API instance; for horizontally scaled production, move lockout tracking to a shared store (Redis/DB) for consistent enforcement across instances. diff --git a/tests-results-for-OWASP/A08-Software-and-Data-Integrity-Failures.md b/tests-results-for-OWASP/A08-Software-and-Data-Integrity-Failures.md new file mode 100644 index 0000000..0db6d30 --- /dev/null +++ b/tests-results-for-OWASP/A08-Software-and-Data-Integrity-Failures.md @@ -0,0 +1,49 @@ +# A08: Software and Data Integrity Failures + +Last updated: March 1, 2026 + +## Findings addressed + +1. Backup/restore workflow did not verify backup artifact integrity before restoring. +2. Restores could proceed with tampered/corrupted dump files, risking silent data corruption. + +## Fixes implemented + +1. Added checksum artifact generation during backups: +- `scripts/backup.sh` now generates a SHA-256 checksum file next to each dump (`.sha256`). + +2. Added checksum verification before restore: +- `scripts/restore.sh` now requires `${BACKUP_FILE}.sha256`. +- Validates checksum format (64 hex chars). +- Computes runtime SHA-256 of backup file and blocks restore on mismatch. + +## Files changed + +1. `scripts/backup.sh` +2. `scripts/restore.sh` +3. `api/tests/software-data-integrity-failures.test.ts` +4. `api/vitest.security.config.ts` + +## Verification + +Command: + +```bash +cd api +npx vitest run -c vitest.security.config.ts tests/software-data-integrity-failures.test.ts +``` + +Verified output: + +- Test Files: `1 passed (1)` +- Tests: `2 passed (2)` + +Dedicated A08 checks in `software-data-integrity-failures.test.ts`: + +1. Executes `scripts/backup.sh` with stubbed `pg_dump` and verifies dump + `.sha256` artifact generation. +2. Executes `scripts/restore.sh` with tampered checksum and verifies restore is blocked before DB commands are invoked. + +## Residual notes + +1. This secures backup artifact integrity in operational scripts. +2. For CI/CD artifact integrity hardening, next step is attestation/signature verification for deployed build artifacts. diff --git a/tests-results-for-OWASP/A09-Security-Logging-and-Monitoring-Failures.md b/tests-results-for-OWASP/A09-Security-Logging-and-Monitoring-Failures.md new file mode 100644 index 0000000..96d74b2 --- /dev/null +++ b/tests-results-for-OWASP/A09-Security-Logging-and-Monitoring-Failures.md @@ -0,0 +1,59 @@ +# A09: Security Logging and Monitoring Failures + +Last updated: March 1, 2026 + +## Findings addressed + +1. Security-sensitive auth/account outcomes were not consistently logged as structured audit events. +2. Incident triage required better request correlation for failed auth/CSRF and account-deletion attempts. + +## Fixes implemented + +1. Added centralized structured security logging helper in API: +- `logSecurityEvent(req, event, outcome, details)` +- Includes request correlation fields (`requestId`, `ip`, `userAgent`). + +2. Added audit logging for critical security events: +- `auth.unauthenticated_request` (JWT auth failure) +- `csrf.validation` (CSRF check failure) +- `auth.register` success/blocked +- `auth.login` success/failure/blocked (including lockout cases) +- `auth.logout` success +- `auth.verify` success/failure +- `auth.verify_resend` success/failure/blocked +- `account.delete_request` success/failure/blocked +- `account.confirm_delete` success/failure/blocked + +3. Reduced sensitive data exposure in logs: +- Added email fingerprinting (`sha256` prefix) for event context instead of plain-text credentials. + +## Files changed + +1. `api/src/server.ts` +2. `api/tests/security-logging-monitoring-failures.test.ts` +3. `api/vitest.security.config.ts` + +## Verification + +Command: + +```bash +cd api +npx vitest run -c vitest.security.config.ts tests/security-logging-monitoring-failures.test.ts +``` + +Verified output: + +- Test Files: `1 passed (1)` +- Tests: `2 passed (2)` + +Dedicated A09 checks in `security-logging-monitoring-failures.test.ts`: + +1. Runtime check emits structured `auth.unauthenticated_request` security event for protected-route access failures. +2. Runtime check emits structured `csrf.validation` security event for CSRF failures. +3. Validates correlation fields (`requestId`, `ip`, `outcome`) are present in emitted security events. + +## Residual notes + +1. Event logs are currently emitted through app logs; ensure production log shipping/alerting (e.g., SIEM rules on repeated `auth.login` failure/blocked events). +2. Next step for A09 maturity is alert thresholds and automated incident notifications. diff --git a/tests-results-for-OWASP/A10-Server-Side-Request-Forgery.md b/tests-results-for-OWASP/A10-Server-Side-Request-Forgery.md new file mode 100644 index 0000000..d6d9c18 --- /dev/null +++ b/tests-results-for-OWASP/A10-Server-Side-Request-Forgery.md @@ -0,0 +1,50 @@ +# A10: Server-Side Request Forgery (SSRF) + +Last updated: March 1, 2026 + +## Findings addressed + +1. Production `APP_ORIGIN` previously enforced HTTPS but did not explicitly block localhost/private-network targets. +2. SSRF posture needed explicit verification that API runtime code does not introduce generic outbound HTTP clients for user-influenced targets. + +## Fixes implemented + +1. Hardened production `APP_ORIGIN` validation in env parsing: +- Requires valid URL format. +- Rejects localhost/private-network hosts: + - `localhost`, `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `169.254.0.0/16`, `::1`, `0.0.0.0`, `.local`. + +2. Added dedicated A10 verification tests: +- Rejects private/loopback `APP_ORIGIN` in production mode. +- Asserts API server source (`api/src/server.ts`) does not use generic outbound HTTP request clients (`fetch`, `axios`, `http.request`, `https.request`). + +## Files changed + +1. `api/src/env.ts` +2. `api/tests/server-side-request-forgery.test.ts` +3. `api/vitest.security.config.ts` + +## Verification + +Command: + +```bash +cd api +npx vitest run -c vitest.security.config.ts tests/server-side-request-forgery.test.ts +``` + +Verified output: + +- Test Files: `1 passed (1)` +- Tests: `3 passed (3)` + +Dedicated A10 checks in `server-side-request-forgery.test.ts`: + +1. Asserts production env parsing rejects multiple private/localhost `APP_ORIGIN` variants. +2. Asserts production env parsing accepts public HTTPS `APP_ORIGIN`. +3. Asserts API source code has no generic outbound HTTP client usage (`fetch`, `axios`, `http.request`, `https.request`) outside test scripts. + +## Residual notes + +1. Current API architecture has minimal outbound HTTP surface (primarily SMTP transport). +2. If future features add URL fetch/proxy/webhook integrations, enforce strict destination allowlists and network egress controls at implementation time. diff --git a/tests-results-for-OWASP/README.md b/tests-results-for-OWASP/README.md new file mode 100644 index 0000000..04207ea --- /dev/null +++ b/tests-results-for-OWASP/README.md @@ -0,0 +1,40 @@ +# OWASP Test Results + +Last updated: March 2, 2026 + +This directory is the source of truth for SkyMoney OWASP validation work. + +## Purpose + +- Track implemented security tests and hardening changes. +- Define exact pre-deploy and post-deploy verification steps. +- Keep release evidence (commands, outputs, timestamps, pass/fail). + +## Files + +- `A01-Broken-Access-Control.md`: Findings, fixes, and verification for OWASP A01. +- `A02-Security-Misconfiguration.md`: Findings, fixes, and dedicated verification suite for OWASP A02. +- `A03-Software-Supply-Chain-Failures.md`: Dependency and pipeline supply-chain findings/fixes/verification. +- `A04-Cryptographic-Failures.md`: Crypto/session token hardening findings/fixes/verification. +- `A05-Injection.md`: Injection sink remediation and script input hardening verification. +- `A06-Insecure-Design.md`: Abuse-resistance design hardening (cooldowns + tighter route throttling). +- `A07-Identification-and-Authentication-Failures.md`: Login lockout and strong-password policy hardening. +- `A08-Software-and-Data-Integrity-Failures.md`: Backup/restore checksum integrity controls. +- `A09-Security-Logging-and-Monitoring-Failures.md`: Structured security event auditing for auth/account flows. +- `A10-Server-Side-Request-Forgery.md`: SSRF hardening and outbound-request surface validation. +- `post-deployment-verification-checklist.md`: Production smoke checks after each deploy. +- `evidence-log-template.md`: Copy/paste template for recording each verification run. +- `residual-risk-backlog.md`: Open non-blocking hardening items tracked release-to-release. + +## Current status + +1. A01 complete: implemented and tested. +2. A02 complete: implemented and tested. +3. A03 complete (initial hardening): implemented and tested. +4. A04 complete: implemented and tested. +5. A05 complete: implemented and tested. +6. A06 complete: implemented and tested. +7. A07 complete: implemented and tested. +8. A08 complete: implemented and tested. +9. A09 complete: implemented and tested. +10. A10 complete: implemented and tested. diff --git a/tests-results-for-OWASP/evidence-log-template.md b/tests-results-for-OWASP/evidence-log-template.md new file mode 100644 index 0000000..04439d5 --- /dev/null +++ b/tests-results-for-OWASP/evidence-log-template.md @@ -0,0 +1,70 @@ +# OWASP Verification Evidence Log Template + +## Run metadata + +- Date: +- Environment: `local` | `staging` | `production` +- App/API version (git SHA): +- Operator: + +## Environment flags + +- `NODE_ENV`: +- `AUTH_DISABLED`: +- `ALLOW_INSECURE_AUTH_FOR_DEV`: + +## Commands executed + +1. +```bash +# command +``` +Output summary: + +2. +```bash +# command +``` +Output summary: + +3. +```bash +# command +``` +Output summary: + +## Results + +- A01 protected route unauthenticated check: `pass` | `fail` +- A01 spoofed header check: `pass` | `fail` +- A01 admin rollover exposure check: `pass` | `fail` +- A01 automated suite (`auth` + `account-delete` + `admin-rollover`): `pass` | `fail` +- A02 dedicated suite (`security-misconfiguration`): `pass` | `fail` +- A03 dedicated suite (`software-supply-chain-failures`): `pass` | `fail` +- A04 dedicated suites (`cryptographic-failures*`): `pass` | `fail` +- A05 dedicated suite (`injection-safety`): `pass` | `fail` +- A06 dedicated suite (`insecure-design`): `pass` | `fail` +- A07 dedicated suites (`auth.routes` + `identification-auth-failures`): `pass` | `fail` +- A08 dedicated suite (`software-data-integrity-failures`): `pass` | `fail` +- A09 dedicated suite (`security-logging-monitoring-failures`): `pass` | `fail` +- A10 dedicated suite (`server-side-request-forgery`): `pass` | `fail` +- Non-DB security suite (`SECURITY_DB_TESTS=0`): `pass` | `fail` +- DB security suite (`SECURITY_DB_TESTS=1`): `pass` | `fail` + +## Findings + +- New issues observed: +- Regressions observed: +- Follow-up tickets: + +## Residual Risk Review + +- Reviewed `residual-risk-backlog.md`: `yes` | `no` +- Items accepted for this release: +- Items escalated/blocked: + +## Sign-off + +- Security reviewer: +- Engineering owner: +- Decision: `approved` | `blocked` diff --git a/tests-results-for-OWASP/post-deployment-verification-checklist.md b/tests-results-for-OWASP/post-deployment-verification-checklist.md new file mode 100644 index 0000000..e747d29 --- /dev/null +++ b/tests-results-for-OWASP/post-deployment-verification-checklist.md @@ -0,0 +1,107 @@ +# Post-Deployment Verification Checklist + +Use this after every deploy (staging and production). + +## Preconditions + +1. Deployment completed successfully. +2. Migrations completed successfully. +3. Correct environment flags: +- `AUTH_DISABLED=false` +- `ALLOW_INSECURE_AUTH_FOR_DEV=false` +4. Test DB preflight (for DB-backed suites): +- `TEST_DATABASE_URL` points to a reachable PostgreSQL instance. +- Example quick check: +```bash +echo "$TEST_DATABASE_URL" +``` +Expected: +- single valid URL value +- host/port match the intended test database (for local runs usually `127.0.0.1:5432`) + +## A01 smoke checks + +Replace `${API_BASE}` with your deployed API base URL. + +### 1) Protected route requires auth + +```bash +curl -i "${API_BASE}/dashboard" +``` + +Expected: +- HTTP `401` +- response body includes `UNAUTHENTICATED` + +### 2) Spoofed identity header is ignored + +```bash +curl -i -H "x-user-id: spoofed-user-id" "${API_BASE}/dashboard" +``` + +Expected: +- HTTP `401` + +### 3) Admin rollover is not publicly callable + +```bash +curl -i -X POST "${API_BASE}/admin/rollover" \ + -H "Content-Type: application/json" \ + -d '{"dryRun":true}' +``` + +Expected: +- HTTP `403` + +## A09 smoke checks + +### 4) Security events are emitted for failed auth attempts + +Trigger a failed login attempt: + +```bash +curl -i -X POST "${API_BASE}/auth/login" \ + -H "Content-Type: application/json" \ + -d '{"email":"nonexistent@example.com","password":"WrongPass123!"}' +``` + +Expected: +- HTTP `401` +- API logs include a structured `securityEvent` for `auth.login` with `outcome=failure` +- log entry includes `requestId` + +## A10 smoke checks + +### 5) Production origin configuration is public and non-local + +Verify production env/config: + +- `APP_ORIGIN` uses public HTTPS host (not localhost/private IP ranges) + +Expected: +- API boots successfully with production env validation. + +## Automated regression checks + +Run in CI against a prod-like environment: + +```bash +cd api +npm test -- tests/auth.routes.test.ts tests/access-control.account-delete.test.ts tests/access-control.admin-rollover.test.ts +SECURITY_DB_TESTS=0 npx vitest run -c vitest.security.config.ts +SECURITY_DB_TESTS=1 npx vitest run -c vitest.security.config.ts +``` + +Expected: +- all tests pass + +Note: +- A06/A07 runtime suites require PostgreSQL availability. +- `SECURITY_DB_TESTS=0` runs non-DB security controls only. +- `SECURITY_DB_TESTS=1` includes DB-backed A06/A07 suites. + +## Sign-off + +1. Record outputs in `evidence-log-template.md`. +2. Review open residual risks in `residual-risk-backlog.md`. +3. Mark release security check as pass/fail. diff --git a/tests-results-for-OWASP/residual-risk-backlog.md b/tests-results-for-OWASP/residual-risk-backlog.md new file mode 100644 index 0000000..fa77569 --- /dev/null +++ b/tests-results-for-OWASP/residual-risk-backlog.md @@ -0,0 +1,26 @@ +# OWASP Residual Risk Backlog + +Last updated: March 2, 2026 + +Use this file to track non-blocking hardening items that remain after automated controls pass. + +## Open items + +| ID | OWASP | Residual risk | Status | +|---|---|---|---| +| RR-001 | A01 | Add explicit authorization integration tests for all future admin-only routes (deny-by-default coverage expansion). | Open | +| RR-002 | A02 | Add runtime CSP and full security-header verification from deployed edge stack (not only config checks). | Open | +| RR-003 | A03 | Add stronger supply-chain provenance controls (digest pinning, SLSA attestations, artifact signing). | Open | +| RR-004 | A04 | Add key rotation runbook validation and automated stale-key detection checks. | Open | +| RR-005 | A05 | Add static taint analysis or Semgrep policy bundle in CI for command/SQL injection sinks. | Open | +| RR-006 | A06 | Add abuse-case tests for account recovery and verification flows under distributed-IP pressure. | Open | +| RR-007 | A07 | Add MFA/WebAuthn roadmap tests once MFA is implemented; currently password+lockout only. | Open | +| RR-008 | A08 | Add signed backup manifests and restore provenance verification for operational artifacts. | Open | +| RR-009 | A09 | Add alerting pipeline assertions (SIEM/webhook delivery) in pre-prod smoke tests. | Open | +| RR-010 | A10 | Add egress firewall enforcement tests to complement application-layer SSRF guards. | Open | + +## Close criteria + +1. A concrete control is implemented and validated by an automated test or policy gate. +2. Evidence is attached in `evidence-log-template.md`. +3. Owning team marks item as Closed with date and link to implementation PR. diff --git a/web/package-lock.json b/web/package-lock.json index a86e035..7612dc1 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1114,9 +1114,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz", - "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", "cpu": [ "arm" ], @@ -1127,9 +1127,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz", - "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", "cpu": [ "arm64" ], @@ -1140,9 +1140,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz", - "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", "cpu": [ "arm64" ], @@ -1153,9 +1153,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz", - "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", "cpu": [ "x64" ], @@ -1166,9 +1166,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz", - "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", "cpu": [ "arm64" ], @@ -1179,9 +1179,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz", - "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", "cpu": [ "x64" ], @@ -1192,9 +1192,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz", - "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", "cpu": [ "arm" ], @@ -1205,9 +1205,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz", - "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", "cpu": [ "arm" ], @@ -1218,9 +1218,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz", - "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", "cpu": [ "arm64" ], @@ -1231,9 +1231,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz", - "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", "cpu": [ "arm64" ], @@ -1244,9 +1244,22 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz", - "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", "cpu": [ "loong64" ], @@ -1257,9 +1270,22 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz", - "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", "cpu": [ "ppc64" ], @@ -1270,9 +1296,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz", - "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", "cpu": [ "riscv64" ], @@ -1283,9 +1309,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz", - "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", "cpu": [ "riscv64" ], @@ -1296,9 +1322,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz", - "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", "cpu": [ "s390x" ], @@ -1309,9 +1335,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz", - "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", "cpu": [ "x64" ], @@ -1322,9 +1348,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz", - "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", "cpu": [ "x64" ], @@ -1334,10 +1360,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz", - "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", "cpu": [ "arm64" ], @@ -1348,9 +1387,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz", - "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", "cpu": [ "arm64" ], @@ -1361,9 +1400,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz", - "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", "cpu": [ "ia32" ], @@ -1374,9 +1413,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz", - "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", "cpu": [ "x64" ], @@ -1387,9 +1426,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz", - "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", "cpu": [ "x64" ], @@ -2081,13 +2120,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -2282,9 +2321,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -3785,9 +3824,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -4196,9 +4235,9 @@ } }, "node_modules/rollup": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", - "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -4211,28 +4250,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.2", - "@rollup/rollup-android-arm64": "4.53.2", - "@rollup/rollup-darwin-arm64": "4.53.2", - "@rollup/rollup-darwin-x64": "4.53.2", - "@rollup/rollup-freebsd-arm64": "4.53.2", - "@rollup/rollup-freebsd-x64": "4.53.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.2", - "@rollup/rollup-linux-arm-musleabihf": "4.53.2", - "@rollup/rollup-linux-arm64-gnu": "4.53.2", - "@rollup/rollup-linux-arm64-musl": "4.53.2", - "@rollup/rollup-linux-loong64-gnu": "4.53.2", - "@rollup/rollup-linux-ppc64-gnu": "4.53.2", - "@rollup/rollup-linux-riscv64-gnu": "4.53.2", - "@rollup/rollup-linux-riscv64-musl": "4.53.2", - "@rollup/rollup-linux-s390x-gnu": "4.53.2", - "@rollup/rollup-linux-x64-gnu": "4.53.2", - "@rollup/rollup-linux-x64-musl": "4.53.2", - "@rollup/rollup-openharmony-arm64": "4.53.2", - "@rollup/rollup-win32-arm64-msvc": "4.53.2", - "@rollup/rollup-win32-ia32-msvc": "4.53.2", - "@rollup/rollup-win32-x64-gnu": "4.53.2", - "@rollup/rollup-win32-x64-msvc": "4.53.2", + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" } },