Security¶
Findings¶
F-1: Auth-redirect may be missing (HIGH if true — VERIFY)¶
nuxt.config.js does not register an auth middleware globally; pages don't seem to declare middleware: 'auth' per spot-checks. Verify: try visiting /dashboard without a token. If no redirect, unauthenticated visitors can hit protected page chrome (though API calls will 401).
Fix: add router.middleware: ['auth', 'axios'] in nuxt.config.js, OR per-page middleware: 'auth'. @nuxtjs/auth ships an auth middleware that redirects unauthenticated requests to the configured login path.
F-2: Token in localStorage / userdetail cookie (MEDIUM)¶
@nuxtjs/auth's local strategy default stores the token in localStorage + a non-httpOnly cookie. The user record is also in the userdetail cookie. Both XSS-readable.
Fix: BE-side, switch to httpOnly cookies for the auth token. Drop the userdetail cookie; rely on /me.
F-3: No server-side logout (MEDIUM)¶
auth.strategies.local.endpoints.logout: false means the FE doesn't call any BE logout endpoint. Tokens remain valid until the BE token format expires (which, per BE audit, is "never").
Fix: add a POST /logout BE endpoint that revokes the token; FE calls it before clearing state.
F-4: Role gating UI-only (MEDIUM)¶
The Navbar hides nav items by role_type but a knowledgeable user can navigate by URL. Whether that exposes data depends on BE enforcement. If the BE doesn't check role_type consistently per-handler, the role gating is cosmetic.
Fix: audit BE handlers (designer-api/routes/routes.js) for consistent role checks; consider a requireRole(...) middleware (BE side) — see ../designer-api/security.md.
F-5: 3rd-party CDN scripts in <head> without SRI (LOW)¶
nuxt.config.js head:
{ src: 'https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js', type: 'text/javascript' }
No integrity / crossorigin attributes. If the CDN is compromised, the script can execute arbitrary JS in designer staff browsers.
Fix: pin via SRI: integrity="sha384-..." crossorigin="anonymous". Or self-host.
F-6: No CSP (MEDIUM)¶
Nuxt doesn't set CSP by default. Whether CSP is configured depends on the nginx layer in the Dockerfile-built image. No in-repo CSP config observed.
Fix: configure CSP in nginx config; minimum: restrict script-src to self + known CDNs.
F-7: Bootstrap-Vue v2 ↔ Bootstrap v5 mismatch (LOW; UX, not security)¶
Loading two incompatible Bootstrap versions can cause unexpected DOM mutations. Less a security finding than a UX risk; mentioned here because it affects auth-related UI (modals, dropdowns) where consistent behaviour matters.
F-8: Polotno editor localStorage design persistence (LOW)¶
The Polotno editor persists in-progress designs to localStorage. PII risk: designs may contain customer brand assets, draft copy, internal notes. Designer staff sharing browsers could leak. (Internal tool — moderate risk; document.)
F-9: bcryptjs in client deps (LOW)¶
bcryptjs is in the FE's package.json. If used client-side, it suggests passwords are hashed in the browser — usually a sign of a misunderstood security model (the server should hash). Verify whether bcryptjs is actually used in this FE; if not, remove.
F-10: Hot-loaded jQuery via Bootstrap bundle (LOW)¶
The CDN Bootstrap 5 bundle pulls in jQuery indirectly. jQuery has a track record of XSS vectors. Audit any v-html / innerHTML usage in pages.
Outcomes-based¶
- OWASP A02 / A05 / A07 — auth posture (token storage, no expiry, no real logout)
- OWASP A05 — missing CSP, missing SRI
- OWASP A01 Broken Access Control — role gating UI-only
Recommendations¶
| Priority | Action |
|---|---|
| HIGH | Verify F-1 (auth redirect); fix if absent |
| HIGH | Add server-side logout (F-3) |
| MEDIUM | Add CSP via nginx (F-6) |
| MEDIUM | Add SRI to CDN scripts (F-5) |
| MEDIUM | Migrate to httpOnly cookie auth (F-2, BE coord) |
| LOW | Audit BE role-check coverage (F-4) |
| LOW | Remove/document bcryptjs FE dep (F-9) |
| LOW | Self-host critical scripts to remove CDN dependency (F-5) |
What's not a finding¶
- CSRF: token in header (Bearer), not cookie auth. CSRF not exploitable.
- SQL injection / XSS via user input: BE concern, not FE; the FE renders mostly server-provided text.
- Lovable.dev script: not present here (only in
admin_console_R). - Hardcoded secrets: none in FE source (
process.env.APP_TYPE,process.env.baseURLare env-driven).