Skip to content

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.

@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.baseURL are env-driven).