From 7727794d5d7c1cef1850d704748c5d4ce474ddc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Jacq?= <266385973+versila22@users.noreply.github.com> Date: Sat, 27 Jun 2026 05:07:52 +0200 Subject: [PATCH] security: daily pentest 2026-06-27 (+ cleanup reports older than 2026-06-06) --- security/pentest-2026-06-27.md | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 security/pentest-2026-06-27.md diff --git a/security/pentest-2026-06-27.md b/security/pentest-2026-06-27.md new file mode 100644 index 0000000..cc6c03b --- /dev/null +++ b/security/pentest-2026-06-27.md @@ -0,0 +1,47 @@ +# Pentest mini-report — versila22/lima-app — 2026-06-27 + +**Probed URL:** https://limaimpro.duckdns.org/ +**Stack:** Vite + React SPA / npm+bun / PWA=yes (VitePWA + workbox, auto-update) +**Backend:** Python/FastAPI on Railway (separate service) +**Counts:** Critical=0 High=0 Medium=2 Low=1 Info=2 + +## Findings + +| Sev | Cat | Title | Location | +|---|---|---|---| +| Medium | SAST | CSP `style-src unsafe-inline` | nginx.conf:20 | +| Medium | Infra | High/Critical dep vulns in build/CI toolchain | package.json (vitest, undici, serialize-javascript) | +| Low | Infra | Python backend deps unscanned | backend/requirements.txt | +| Info | Infra | DAST blocked — HTTP headers/TLS/file probes not verified remotely | limaimpro.duckdns.org | +| Info | PWA | API cache NetworkFirst, 1h TTL on authenticated routes | vite.config.ts:runtimeCaching | + +## Top 3 fixes +1. **CSP unsafe-inline** — Replace `style-src 'self' 'unsafe-inline'` with a nonce or hash-based policy in nginx.conf; Tailwind CSS supports nonce via the `nonce` option. +2. **Update build deps** — Run `npm update vitest undici serialize-javascript` to clear CVSS-9.8 vitest RCE and undici header-injection/TLS-bypass vulns in CI/dev. +3. **Scan Python deps** — Add `pip-audit` step to CI for the FastAPI backend (python-jose, passlib, fastapi, httpx, etc.). + +## Evidence (Critical/High only) +_None — no Critical or High confirmed findings._ + +## Verified safe +- No XSS sinks in frontend source (no `dangerouslySetInnerHTML`, `innerHTML=`, `eval()`) +- No hardcoded secrets or API keys in committed source files +- Nginx serves strong security headers: HSTS (1y + includeSubDomains), X-Frame-Options: DENY, nosniff, Referrer-Policy, Permissions-Policy +- CSP in nginx blocks `script-src` to `'self'` only — no unsafe-eval +- PWA workbox SW uses NetworkFirst for API (no stale-auth-response risk); no VAPID keys in client +- Backend `validate_jwt_secret` validator hard-fails startup if `JWT_SECRET` equals the default in non-dev mode — weak-secret-in-prod prevented +- Backend CORS reads `CORS_ORIGINS` from env; `allow_credentials=True` combined with explicit origins (not wildcard) — safe +- FastAPI docs (`/docs`, `/redoc`) disabled in production via `settings.is_development` guard +- Backend SecurityHeadersMiddleware adds HSTS, nosniff, X-Frame-Options, strict API CSP +- Rate-limiting via slowapi on all API endpoints +- PWA manifest scope/start_url both `/` — no scope escalation + +## Needs server-side verification +- Actual HTTP response headers on limaimpro.duckdns.org (DAST blocked by proxy) — confirm HSTS, nosniff, CSP are served +- TLS version support (TLS 1.0/1.1 enabled?) and cipher suite strength — check with `testssl.sh` or SSL Labs +- .env/.git/* file exposure on deployed host +- Railway backend API (`api-production-e15b.up.railway.app`) CORS reflection test with `Origin: https://attacker.example` +- Python dependency audit: `pip install pip-audit && pip-audit -r backend/requirements.txt` + +## Tools +ran=npm-audit, grep-secret-scan; skipped=pnpm-audit (not PM), yarn-audit (not PM), curl-DAST (proxy blocked outbound to target), openssl-tls-check (proxy blocked), pip-audit (not installed)