Skip to content

Security audit β€” 2026-06-07#43

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

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

Conversation

@versila22

Copy link
Copy Markdown
Owner

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

Probed URL: https://limaimpro.duckdns.org/
Stack: React 18 + Vite + ShadCN (PWA via vite-plugin-pwa) / bun / PWA=yes
Backend: FastAPI (Python) on Railway β€” separate deployment
Counts: Critical=0 High=1 Medium=2 Low=1 Info=1

Findings

Sev Cat Title Location
High SAST CORS default allows external Lovable.app origin + allow_credentials=True backend/app/config.py:37,84-87
Medium SAST JWT access token stored in sessionStorage (XSS-accessible fallback) src/lib/api.ts:50-59
Medium DAST CSP style-src includes 'unsafe-inline' nginx.conf:18
Low SAST Lodash code injection (GHSA-r5fr-rjxr-66jc) via recharts transitive dep package.json (recharts β†’ lodash ≀4.17.22)
Info Infra vitest critical CVE β€” dev-only dependency, no production exposure package.json devDependencies

Top 3 fixes

  1. CORS default Lovable.app origin β€” Set FRONTEND_URL=https://limaimpro.duckdns.org explicitly in the Railway production environment, and remove the stale default from config.py:37.
  2. JWT in sessionStorage β€” Prefer SameSite=None; Secure cookie with the Partitioned attribute for Safari instead of sessionStorage; if sessionStorage is kept, add a strict nonce-based CSP to prevent token exfiltration via XSS.
  3. CSP unsafe-inline style β€” Replace 'unsafe-inline' on style-src with a nonce or hash; Tailwind CSS supports a strict-dynamic approach since v3.4.

Evidence (High only)

High β€” CORS default Lovable.app origin + allow_credentials

  • Location: backend/app/config.py:37 and :84-87
  • Snippet: FRONTEND_URL: str = "https://improv-cabaret-planner.lovable.app" β†’ inject_frontend_url_into_cors always appends this to CORS_ORIGINS
  • Combined with: allow_credentials=True in backend/app/main.py:160
  • Impact: If Railway does not override FRONTEND_URL, any page hosted on improv-cabaret-planner.lovable.app (a shared hosting platform) can make credentialed cross-origin requests to the production API and receive authenticated responses.
  • Fix: Set FRONTEND_URL=https://limaimpro.duckdns.org in Railway env; remove hardcoded lovable.app default from source.

Verified safe

  • No hardcoded secrets, API keys, or private keys found in tracked source files
  • No dangerouslySetInnerHTML, innerHTML=, eval(), or v-html sinks in frontend source
  • No postMessage handlers without origin checks
  • Nginx config: HSTS (1yr + includeSubDomains), X-Content-Type-Options, X-Frame-Options DENY, frame-ancestors none, Referrer-Policy all present
  • Backend SecurityHeadersMiddleware: full HSTS/nosniff/X-Frame/CSP/Permissions-Policy set
  • FastAPI /docs and /redoc disabled in production
  • JWT_SECRET/REFRESH_JWT_SECRET: startup validator raises error if default used outside dev
  • PWA: no VAPID private keys in client code; SW uses NetworkFirst for API; scope/start_url root-only
  • Sensitive path probing: all returned 403

Needs server-side verification

  • Confirm FRONTEND_URL is explicitly set in Railway production env (not defaulting to lovable.app)
  • Live response headers (CSP, HSTS, CORS) β€” egress proxy blocked direct curl from audit sandbox
  • TLS certificate and cipher suite config on actual origin server (Traefik Let's Encrypt)

Tools

ran=bun-audit, grep-secret-scan, openssl-tls-check; skipped=curl-DAST (egress proxy 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