Skip to content

Security audit β€” 2026-06-15#63

Open
versila22 wants to merge 1 commit into
mainfrom
security-audit-2026-06-15
Open

Security audit β€” 2026-06-15#63
versila22 wants to merge 1 commit into
mainfrom
security-audit-2026-06-15

Conversation

@versila22

Copy link
Copy Markdown
Owner

Pentest mini-report β€” versila22/lima-app β€” 2026-06-15

Probed URL: https://limaimpro.duckdns.org/
Stack: React 18 / Vite 7 / FastAPI + SQLAlchemy (Python) / PWA=no
Counts: Critical=0 High=4 Medium=3 Low=1 Info=1

Findings

Sev Cat Title Location
High SAST Default FRONTEND_URL auto-injected into CORS with allow_credentials=True backend/app/config.py:37,84-87
High SAST Hardcoded admin seed password in production startup code backend/app/main.py:54
High SCA vitest <3.2.6 β€” arbitrary file read/exec via UI server (GHSA-5xrq-8626-4rwp) package.json devDeps
High SCA serialize-javascript ≀7.0.2 β€” RCE via malicious RegExp (GHSA-5c6j-r48x-rmvq) package.json devDeps
Medium DAST Unauthenticated /health/db + /health/migrations expose DB URL prefix and full stack trace backend/app/main.py:202,224
Medium SCA 6 moderate npm vulns: postcss, @rollup/plugin-terser, brace-expansion, react-routerΓ—2, workbox-build package.json
Medium SCA 3 further high npm devDep vulns: @babel/plugin-transform-modules-systemjs, esbuild, fast-uri package.json
Low Infra nginx CSP: style-src includes 'unsafe-inline' nginx.conf:10
Info Infra TLS 1.0/1.1 disabled; TLS 1.2+1.3 confirmed enabled host:443

Top 3 fixes

  1. CORS default FRONTEND_URL β€” Set FRONTEND_URL explicitly in Railway production env vars (e.g. https://limaimpro.duckdns.org) so improv-cabaret-planner.lovable.app default is never injected.
  2. Seed admin password β€” Replace hardcoded "Admin1234!" with a startup check that reads SEED_ADMIN_PASSWORD env var; never commit passwords to source.
  3. Health endpoint auth β€” Add Depends(require_admin) to /health/db and /health/migrations, or strip DB URL + traceback from HTTP responses.

Evidence (High findings)

CORS default FRONTEND_URL auto-injection β€” backend/app/config.py:37,84-87

FRONTEND_URL: str = "https://improv-cabaret-planner.lovable.app"  # default if env unset
def inject_frontend_url_into_cors(self):
    if self.FRONTEND_URL and self.FRONTEND_URL not in self.CORS_ORIGINS:
        self.CORS_ORIGINS = list(self.CORS_ORIGINS) + [self.FRONTEND_URL]

Impact: If FRONTEND_URL is not set in Railway production, a potentially-uncontrolled Lovable.app subdomain gets credentialed CORS access. An attacker who acquires that subdomain can exfiltrate user sessions.
Fix: Explicitly set FRONTEND_URL=https://limaimpro.duckdns.org in all production environments.

Hardcoded admin seed password β€” backend/app/main.py:54

{"email": "admin@lima-impro.fr", "app_role": "admin", "password": "Admin1234!", …}

Impact: On a fresh DB deploy, admin account is created with a well-known password visible in git history.
Fix: Seed from SEED_ADMIN_PASSWORD env var or generate a random password printed once to startup logs.

vitest <3.2.6 β€” GHSA-5xrq-8626-4rwp

"vitest": "^3.2.4" β†’ resolves to 3.2.4 (patched: β‰₯3.2.6)

Impact: If Vitest UI server (--ui) runs on a CI host reachable from the network, arbitrary files can be read and executed.
Fix: npm install vitest@latest

serialize-javascript ≀7.0.2 β€” GHSA-5c6j-r48x-rmvq

serialize-javascript ≀7.0.2 β€” RCE via crafted RegExp.flags / Date.prototype.toISOString()

Impact: Build-time RCE if serialized user-controlled input reaches this package.
Fix: Upgrade transitive deps or pin serialize-javascript β‰₯8.0.0.

Verified safe

  • No XSS sinks (innerHTML / dangerouslySetInnerHTML / eval) in frontend source
  • No secrets committed to source (VITE_* env files contain only public API URL)
  • JWT: non-default secret enforced in non-dev mode by validator (config.py:63-70)
  • Cookies: httpOnly + Secure on HTTPS + SameSite=none (security.py:119-131)
  • CORS: explicit allowlist, no wildcard; allow_credentials=True correctly paired with explicit origins
  • Admin routes protected by require_admin dependency
  • Rate limiting: slowapi applied globally
  • Security headers middleware: HSTS 1y, nosniff, X-Frame-Options DENY, CORP, COOP, strict CSP on API
  • nginx: HSTS, nosniff, DENY framing, Referrer-Policy, Permissions-Policy all set
  • TLS 1.0/1.1 disabled; TLS 1.2+1.3 enabled
  • No .env/.git files exposed (403 on all probed paths)

Needs server-side verification

  • Actual FRONTEND_URL value in Railway production environment
  • CORS allow_credentials + origin list in live API responses (DAST blocked from this network)
  • Admin seed account: confirm admin@lima-impro.fr password was changed post first-deploy

Tools

ran=npm-audit, grep-secret-scan, openssl-tls-check; skipped=DAST-curl (Anthropic egress gateway blocks target hosts β€” HTTP 403 host_not_allowed)


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant