Skip to content

Security audit β€” 2026-06-18#66

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

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

Conversation

@versila22

Copy link
Copy Markdown
Owner

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

Probed URL: https://limaimpro.duckdns.org/
Stack: React 18 (Vite + SWC) + FastAPI (Python) + PostgreSQL / npm / PWA=yes
Counts: Critical=0 High=2 Medium=1 Low=1 Info=2

Findings

Sev Cat Title Location
High SAST Hardcoded admin credentials in production seed backend/app/main.py:52
High DAST CSP style-src 'unsafe-inline' enables style injection nginx.conf:14
Medium SCA react-router-dom 6.30.3 open redirect via // paths (GHSA-2j2x-hqr9-3h42) package.json β†’ PROD dep
Low Infra nginx add_header in /assets/ suppresses all parent security headers nginx.conf:28-31
Info SAST Default JWT secret visible in source (validator blocks prod use) backend/app/config.py:7
Info SCA dev-only high/critical vulns: vitest (critical), vite (high), babel (high) package.json devDependencies

Top 3 fixes

  1. Hardcoded admin credentials β€” Move _SEED_MEMBERS admin entry to a one-shot CLI script; never commit plaintext passwords for real accounts.
  2. react-router-dom open redirect β€” Run npm audit fix to upgrade react-router-dom past 6.30.3.
  3. nginx header inheritance β€” Repeat all add_header security directives inside the /assets/ location block, or extract them into an include security_headers.conf.

Evidence (High only)

High β€” Hardcoded admin credentials in production seed

  • Location: backend/app/main.py:52
  • Snippet: {"email": "admin@lima-impro.fr", "app_role": "admin", "password": "Admin1234!", ...}
  • Context: _ensure_seed_data() runs at every startup; creates admin account if DB is empty (no env-guard).
  • Impact: Attacker can authenticate as admin on any fresh or re-initialised deployment using known credentials.
  • Fix: Remove plaintext credentials from source; seed via env-injected script or one-time migration with a generated password.

High β€” CSP style-src 'unsafe-inline'

  • Location: nginx.conf:14
  • Snippet: style-src 'self' 'unsafe-inline'
  • Impact: Allows any inline style on the page; attacker-controlled style injection (e.g., CSS-based data exfiltration) remains unblocked.
  • Fix: Replace 'unsafe-inline' with a build-time hash list or nonce; Tailwind's JIT output is static and hashable.

Verified safe

  • No secrets found by grep scan (no raw API keys, tokens, private keys in tracked files)
  • Cookies set with httponly=True, secure=True (HTTPS), samesite="none" (needed for cross-domain API)
  • FastAPI docs (/docs, /redoc) disabled in production via settings.is_development
  • HSTS max-age=31536000; includeSubDomains present in backend SecurityHeadersMiddleware and nginx
  • X-Frame-Options: DENY present in both nginx and backend middleware
  • X-Content-Type-Options: nosniff present
  • .git/ and .env* paths all returned 403 (not exposed)
  • TLS 1.0 and 1.1 disabled; TLS 1.2 + 1.3 enabled
  • TLS cert valid (issued 2026-06-18, expires 2026-07-18)
  • Default JWT secret blocked at startup by model_validator in config.py
  • No dangerouslySetInnerHTML, eval, innerHTML sinks in frontend
  • Prototype pollution surfaces (lodash.merge) not present; no direct lodash usage
  • VAPID_PRIVATE not in client bundle
  • SW scope /, handler NetworkFirst (API), not caching auth tokens in SW
  • No CORS reflection: allow_credentials=True paired with explicit allow_origins list (not wildcard)

Needs server-side verification

  • Effective HTTP response headers (CSP, HSTS, X-Frame-Options) on live site β€” DAST blocked by network policy in audit environment (403 host_not_allowed)
  • Cookie Secure and SameSite flags as seen by browser (need live request)
  • Rate-limiting effectiveness on /auth/login (slowapi configured but untested remotely)
  • Whether CORS_ORIGINS in prod env matches expected list (only default visible in source)

Tools

ran=npm-audit, grep-secret-scan, openssl-tls-check; skipped=curl-http-headers (network policy blocked outbound to target host), yarn-audit (not installed), pnpm-audit (no pnpm lockfile in this repo)


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