# OA Backend — Security Audit Audit of the standalone Java (Spring Boot) OA backend after functional tests reached 100% (42/42, see `../oa-itest.sh`). Scope: injection, XSS, secrets, authn/authz, transport, CORS, password storage. ## Summary | Class | Status | Notes | |---|---|---| | SQL injection | **Safe** | All persistence via Spring Data derived queries (parameterized). No `@Query`, no `createQuery`, no native SQL, no string-concatenated queries anywhere. | | XSS (stored/reflected) | **Safe** | Frontend has **zero** `v-html` / `innerHTML` / `eval` / `new Function`. Vue + Element Plus escape all interpolated text by default. Form/flow JSON is rendered as data, never as HTML. | | Hardcoded secrets | **Safe** | No API keys, tokens, or secrets embedded in source. | | Mass assignment | **Safe** | Controllers bind explicit `record` DTOs, never JPA entities directly. | | Password storage | **Hardened** | Upgraded from unsalted SHA-256 to **salted PBKDF2-HMAC-SHA256** (120k iterations, per-user 16-byte salt), constant-time verify. See `common/PasswordUtil`. | | Error handling | **Safe** | Uniform `ApiResp` envelope via `@RestControllerAdvice`; no stack traces leaked to clients. | | Transport (CORS) | **Dev-scoped** | `/api/**` allows `localhost:*` / `127.0.0.1:*` only — appropriate for local dev; must be locked to the real origin for production. | ## Remaining hardening (documented as "later phase", acceptable for the current single-tenant demo) 1. **Token lifecycle** — opaque in-memory bearer tokens with no expiry and no persistence across restarts. For production: signed/JWT or server-side sessions with TTL + refresh + revocation list. 2. **Authorization enforcement** — most endpoints don't *require* a valid token; an unauthenticated caller falls back to the demo user `我(当前用户)`. This is intentional so the demo runs without a login gate. For production: a filter that rejects unauthenticated/under-privileged calls on mutating routes, plus RBAC using the existing `SysRole` / `SysUserRole` tables. 3. **Rate limiting / lockout** — no brute-force protection on `/auth/login`. Add attempt throttling + temporary lockout. 4. **HTTPS** — served over plain HTTP on :8090 for local dev; terminate TLS at a reverse proxy (or enable Spring SSL) in production. 5. **CORS lockdown** — replace the `localhost:*` dev pattern with the deployed frontend origin(s). 6. **Audit log** — workflow actions are traced (`FlowTrace`), but there is no security/access audit log; add one for production compliance. ## What was fixed in this pass - `common/PasswordUtil` rewritten to salted PBKDF2 (was unsalted SHA-256), with a legacy-hash fallback in `matches()` for backward compatibility. Re-seeded users now store `pbkdf2$$$`. Verified: login `admin/123456` → success; wrong password → 401. - CORS origin patterns documented and scoped (see `config/CorsConfig`). ## Verdict No exploitable vulnerabilities found in the audited classes (injection, XSS, secrets, mass-assignment). Password storage is now industry-standard salted KDF. The remaining items are deployment-hardening tasks expected of a demo moving to production, all tracked above.