chore: root commit of OWSAP security testing/tightening
This commit is contained in:
5
.env
5
.env
@@ -33,3 +33,8 @@ EMAIL_REPLY_TO=support@skymoneybudget.com
|
|||||||
UPDATE_NOTICE_VERSION=1
|
UPDATE_NOTICE_VERSION=1
|
||||||
UPDATE_NOTICE_TITLE=SkyMoney Update
|
UPDATE_NOTICE_TITLE=SkyMoney Update
|
||||||
UPDATE_NOTICE_BODY=We added email verification and account-delete confirmation
|
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
|
||||||
@@ -4,6 +4,7 @@ PORT=8080
|
|||||||
CORS_ORIGIN=http://localhost:5173
|
CORS_ORIGIN=http://localhost:5173
|
||||||
CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173,https://skymoneybudget.com
|
CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173,https://skymoneybudget.com
|
||||||
AUTH_DISABLED=false
|
AUTH_DISABLED=false
|
||||||
|
ALLOW_INSECURE_AUTH_FOR_DEV=false
|
||||||
SEED_DEFAULT_BUDGET=false
|
SEED_DEFAULT_BUDGET=false
|
||||||
ROLLOVER_SCHEDULE_CRON=0 6 * * *
|
ROLLOVER_SCHEDULE_CRON=0 6 * * *
|
||||||
APP_ORIGIN=http://localhost:5173
|
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)
|
# Auth secrets (min 32 chars)
|
||||||
JWT_SECRET=replace-with-32+-chars
|
JWT_SECRET=replace-with-32+-chars
|
||||||
|
JWT_ISSUER=skymoney-api
|
||||||
|
JWT_AUDIENCE=skymoney-web
|
||||||
COOKIE_SECRET=replace-with-32+-chars
|
COOKIE_SECRET=replace-with-32+-chars
|
||||||
COOKIE_DOMAIN=skymoneybudget.com
|
COOKIE_DOMAIN=skymoneybudget.com
|
||||||
|
AUTH_MAX_FAILED_ATTEMPTS=5
|
||||||
|
AUTH_LOCKOUT_WINDOW_MS=900000
|
||||||
|
|
||||||
# Email (verification + delete confirmation)
|
# Email (verification + delete confirmation)
|
||||||
SMTP_HOST=smtp.example.com
|
SMTP_HOST=smtp.example.com
|
||||||
|
|||||||
@@ -8,12 +8,21 @@ jobs:
|
|||||||
deploy:
|
deploy:
|
||||||
runs-on: vps-host
|
runs-on: vps-host
|
||||||
steps:
|
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
|
- name: Build Web
|
||||||
run: |
|
run: |
|
||||||
cd web
|
cd web
|
||||||
npm ci
|
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
- name: Deploy with Docker Compose
|
- name: Deploy with Docker Compose
|
||||||
|
|||||||
54
.gitea/workflows/security.yml
Normal file
54
.gitea/workflows/security.yml
Normal file
@@ -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
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
header {
|
header {
|
||||||
X-Content-Type-Options "nosniff"
|
X-Content-Type-Options "nosniff"
|
||||||
X-Frame-Options "DENY"
|
X-Frame-Options "DENY"
|
||||||
|
Content-Security-Policy "frame-ancestors 'none'"
|
||||||
|
Referrer-Policy "strict-origin-when-cross-origin"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ skymoneybudget.com {
|
|||||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||||
X-Content-Type-Options "nosniff"
|
X-Content-Type-Options "nosniff"
|
||||||
X-Frame-Options "DENY"
|
X-Frame-Options "DENY"
|
||||||
|
Content-Security-Policy "frame-ancestors 'none'"
|
||||||
|
Referrer-Policy "strict-origin-when-cross-origin"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Serve static SPA
|
# Serve static SPA
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ server {
|
|||||||
# Security headers
|
# Security headers
|
||||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||||
add_header X-Content-Type-Options "nosniff" 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;
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
|
||||||
# Static web app
|
# Static web app
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- pgdata:/var/lib/postgresql/data
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "127.0.0.1:5432:5432"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-app} -d ${POSTGRES_DB:-skymoney}"]
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-app} -d ${POSTGRES_DB:-skymoney}"]
|
||||||
@@ -47,7 +47,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
ports:
|
ports:
|
||||||
- "8081:8080"
|
- "127.0.0.1:8081:8080"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health || exit 1"]
|
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health || exit 1"]
|
||||||
|
|||||||
@@ -19,7 +19,11 @@ mkdir -p "$OUT_DIR"
|
|||||||
|
|
||||||
STAMP="$(date +%F_%H%M%S)"
|
STAMP="$(date +%F_%H%M%S)"
|
||||||
OUT_FILE="${OUT_DIR}/skymoney_${STAMP}.dump"
|
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"
|
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 "Backup written to: $OUT_FILE"
|
||||||
|
echo "Checksum written to: ${OUT_FILE}.sha256"
|
||||||
|
|||||||
@@ -13,6 +13,26 @@ if [[ -z "${BACKUP_FILE:-}" ]]; then
|
|||||||
echo "BACKUP_FILE is required."
|
echo "BACKUP_FILE is required."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
if [[ -z "${DATABASE_URL:-}" ]]; then
|
||||||
echo "DATABASE_URL is required."
|
echo "DATABASE_URL is required."
|
||||||
@@ -23,6 +43,11 @@ RESTORE_DB="${RESTORE_DB:-skymoney_restore_test}"
|
|||||||
RESTORE_URL="${RESTORE_DATABASE_URL:-}"
|
RESTORE_URL="${RESTORE_DATABASE_URL:-}"
|
||||||
ADMIN_URL="${ADMIN_DATABASE_URL:-$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
|
if [[ -z "$RESTORE_URL" ]]; then
|
||||||
echo "RESTORE_DATABASE_URL is required (example: postgresql://user:pass@host:5432/${RESTORE_DB})."
|
echo "RESTORE_DATABASE_URL is required (example: postgresql://user:pass@host:5432/${RESTORE_DB})."
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
62
tests-results-for-OWASP/A01-Broken-Access-Control.md
Normal file
62
tests-results-for-OWASP/A01-Broken-Access-Control.md
Normal file
@@ -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`
|
||||||
89
tests-results-for-OWASP/A02-Security-Misconfiguration.md
Normal file
89
tests-results-for-OWASP/A02-Security-Misconfiguration.md
Normal file
@@ -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`.
|
||||||
@@ -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.
|
||||||
71
tests-results-for-OWASP/A04-Cryptographic-Failures.md
Normal file
71
tests-results-for-OWASP/A04-Cryptographic-Failures.md
Normal file
@@ -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)
|
||||||
50
tests-results-for-OWASP/A05-Injection.md
Normal file
50
tests-results-for-OWASP/A05-Injection.md
Normal file
@@ -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.
|
||||||
54
tests-results-for-OWASP/A06-Insecure-Design.md
Normal file
54
tests-results-for-OWASP/A06-Insecure-Design.md
Normal file
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
50
tests-results-for-OWASP/A10-Server-Side-Request-Forgery.md
Normal file
50
tests-results-for-OWASP/A10-Server-Side-Request-Forgery.md
Normal file
@@ -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.
|
||||||
40
tests-results-for-OWASP/README.md
Normal file
40
tests-results-for-OWASP/README.md
Normal file
@@ -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.
|
||||||
70
tests-results-for-OWASP/evidence-log-template.md
Normal file
70
tests-results-for-OWASP/evidence-log-template.md
Normal file
@@ -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`
|
||||||
@@ -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.
|
||||||
26
tests-results-for-OWASP/residual-risk-backlog.md
Normal file
26
tests-results-for-OWASP/residual-risk-backlog.md
Normal file
@@ -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.
|
||||||
244
web/package-lock.json
generated
244
web/package-lock.json
generated
@@ -1114,9 +1114,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
|
||||||
"integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==",
|
"integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1127,9 +1127,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==",
|
"integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1140,9 +1140,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==",
|
"integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1153,9 +1153,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
|
||||||
"integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==",
|
"integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1166,9 +1166,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==",
|
"integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1179,9 +1179,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
|
||||||
"integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==",
|
"integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1192,9 +1192,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
|
||||||
"integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==",
|
"integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1205,9 +1205,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
|
||||||
"integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==",
|
"integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1218,9 +1218,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==",
|
"integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1231,9 +1231,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==",
|
"integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1244,9 +1244,22 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==",
|
"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": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -1257,9 +1270,22 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==",
|
"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": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -1270,9 +1296,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==",
|
"integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -1283,9 +1309,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==",
|
"integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -1296,9 +1322,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==",
|
"integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -1309,9 +1335,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==",
|
"integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1322,9 +1348,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==",
|
"integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1334,10 +1360,23 @@
|
|||||||
"linux"
|
"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": {
|
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==",
|
"integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1348,9 +1387,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==",
|
"integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1361,9 +1400,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==",
|
"integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -1374,9 +1413,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==",
|
"integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1387,9 +1426,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==",
|
"integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2081,13 +2120,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
|
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
|
||||||
"version": "9.0.5",
|
"version": "9.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
||||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^2.0.1"
|
"brace-expansion": "^2.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
@@ -2282,9 +2321,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
|
||||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -3785,9 +3824,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -4196,9 +4235,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.53.2",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
|
||||||
"integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==",
|
"integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.8"
|
"@types/estree": "1.0.8"
|
||||||
@@ -4211,28 +4250,31 @@
|
|||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.53.2",
|
"@rollup/rollup-android-arm-eabi": "4.59.0",
|
||||||
"@rollup/rollup-android-arm64": "4.53.2",
|
"@rollup/rollup-android-arm64": "4.59.0",
|
||||||
"@rollup/rollup-darwin-arm64": "4.53.2",
|
"@rollup/rollup-darwin-arm64": "4.59.0",
|
||||||
"@rollup/rollup-darwin-x64": "4.53.2",
|
"@rollup/rollup-darwin-x64": "4.59.0",
|
||||||
"@rollup/rollup-freebsd-arm64": "4.53.2",
|
"@rollup/rollup-freebsd-arm64": "4.59.0",
|
||||||
"@rollup/rollup-freebsd-x64": "4.53.2",
|
"@rollup/rollup-freebsd-x64": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.53.2",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.53.2",
|
"@rollup/rollup-linux-arm-musleabihf": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.53.2",
|
"@rollup/rollup-linux-arm64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.53.2",
|
"@rollup/rollup-linux-arm64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-loong64-gnu": "4.53.2",
|
"@rollup/rollup-linux-loong64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-ppc64-gnu": "4.53.2",
|
"@rollup/rollup-linux-loong64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.53.2",
|
"@rollup/rollup-linux-ppc64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-riscv64-musl": "4.53.2",
|
"@rollup/rollup-linux-ppc64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.53.2",
|
"@rollup/rollup-linux-riscv64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.53.2",
|
"@rollup/rollup-linux-riscv64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.53.2",
|
"@rollup/rollup-linux-s390x-gnu": "4.59.0",
|
||||||
"@rollup/rollup-openharmony-arm64": "4.53.2",
|
"@rollup/rollup-linux-x64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.53.2",
|
"@rollup/rollup-linux-x64-musl": "4.59.0",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.53.2",
|
"@rollup/rollup-openbsd-x64": "4.59.0",
|
||||||
"@rollup/rollup-win32-x64-gnu": "4.53.2",
|
"@rollup/rollup-openharmony-arm64": "4.59.0",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.53.2",
|
"@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"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user