Skip to content

Security: JdCpuWiz/wiz3dtools

Security

SECURITY.md

Security Audit Findings

Audit performed: 2026-03-14. All findings from automated + manual review of the codebase.


Status Key

  • πŸ”΄ Open
  • 🟑 In Progress
  • βœ… Fixed
  • ⏸ Deferred

Critical

C1 β€” Command Injection in PDF Processing

Status: βœ… Fixed File: packages/backend/src/services/pdf.service.ts lines 25, 84 Issue: execAsync() called with shell string containing user-controlled file path. A crafted filename with shell metacharacters (;, &&, |) could execute arbitrary commands on the server. Fix: Replace execAsync(commandString) with spawn() using argument arrays β€” no shell interpretation. Breaking risk: Low β€” internal change only.


C2 β€” SQL Injection Risk in suggestSku()

Status: βœ… Fixed File: packages/backend/src/models/product.model.ts line ~83 Issue: excludeId interpolated directly into SQL string (AND id != ${excludeId}). Currently safe due to parseInt, but not parameterized β€” violates defense-in-depth. Fix: Use $2 parameterized query. Breaking risk: None.


C3 β€” Weak Password Validation

Status: βœ… Fixed File: packages/backend/src/controllers/users.controller.ts lines 50-54 Issue: Password reset only checks length >= 1. Trivially weak passwords accepted. Fix: Enforce minimum 12 characters. Breaking risk: Low β€” only affects new password creation.


High

H1 β€” No Rate Limiting on Login / API Routes

Status: βœ… Fixed File: packages/backend/src/index.ts, packages/backend/src/routes/auth.routes.ts Issue: Only upload endpoint has rate limiting. Login endpoint open to brute-force. All API routes open to DoS. Fix: Global rate limit on /api/* (100 req/15min); strict limit on /api/auth/login (10 req/15min). Breaking risk: Low.


H2 β€” CORS Open to All Origins

Status: βœ… Fixed File: packages/backend/src/index.ts line ~27 Issue: origin: true allows any website to make credentialed requests to the API (CSRF vector). Fix: Restrict to known frontend domains via CORS_ORIGIN env var. Breaking risk: Low-Medium β€” must set env var correctly for production domain.


H3 β€” JWT Expiry Too Long (7 Days)

Status: βœ… Fixed (interim) File: packages/backend/src/services/auth.service.ts line ~22 Issue: Stolen tokens valid for a full week. No refresh token mechanism. Fix: Reduced to 24h. Full refresh token implementation deferred. Breaking risk: Low β€” users log in again after 24h of inactivity.


H4 β€” JWT Secret Not Validated for Strength

Status: βœ… Fixed File: packages/backend/src/services/auth.service.ts lines 14-18 Issue: Only checks JWT_SECRET exists, not that it's cryptographically strong. Fix: Enforce minimum 32-character length at startup. Breaking risk: Low β€” startup check only; existing strong secrets unaffected.


H5 β€” No HTTPS / HSTS

Status: βœ… Fixed File: infrastructure/docker/nginx.conf Issue: Only HTTP. Tokens and data transmitted in plaintext. No HSTS header. Fix: Add SSL cert (Let's Encrypt), redirect HTTP β†’ HTTPS, add HSTS header. Breaking risk: Medium β€” requires cert setup; misconfiguration takes site down.


H6 β€” No Content-Security-Policy Header

Status: βœ… Fixed File: infrastructure/docker/nginx.conf Issue: No CSP β€” XSS attacks can load external scripts freely. Fix: Add CSP header allowing self + Google Fonts CDN + inline styles. Breaking risk: Medium β€” Poppins font (Google CDN) needs explicit font-src allowance.


H7 β€” JWT Stored in localStorage (XSS Risk)

Status: βœ… Fixed File: packages/frontend/src/context/AuthContext.tsx, packages/backend/src/controllers/auth.controller.ts Issue: localStorage is readable by any JavaScript on the page. XSS attack can steal JWT. Fix: JWT now stored in HttpOnly wiz3d_token cookie (SameSite=Strict, Secure in production). AuthContext restored via /api/auth/me on mount. api.ts uses withCredentials: true. Logout clears cookie server-side via POST /api/auth/logout. Breaking risk: High β€” full auth flow refactor.


H8 β€” File Upload MIME Type Validation Client-Controlled

Status: βœ… Fixed File: packages/backend/src/middleware/upload.middleware.ts lines 27-35 Issue: MIME type check uses file.mimetype which comes from the client and can be spoofed. A malicious file could be uploaded disguised as a PDF. Fix: Validate actual file magic bytes (%PDF) after upload, reject and delete if invalid. Breaking risk: Low β€” only affects malformed/malicious uploads.


H9 β€” Stack Traces Exposed in Non-Production

Status: βœ… Fixed File: packages/backend/src/middleware/error-handler.ts line ~58 Issue: err.message returned to client in non-production environments, leaking internal details. Fix: Always return generic error message to client; log details server-side only. Breaking risk: None.


Medium

M1 β€” No Input Validation on Request Bodies

Status: βœ… Fixed Issue: All controllers pass req.body directly to services without schema validation. Allows over-posting, type confusion, excessively long strings. Fix: Zod validation schemas added to all 8 controllers (auth, users, queue, upload, customer, product, sales-invoice, color). Invalid input returns 400 with field-level error messages. Breaking risk: Low β€” rejects invalid input that currently passes through.


M2 β€” No CSRF Protection

Status: βœ… Fixed Issue: No CSRF tokens on state-changing endpoints. Mitigated partially by Bearer token auth but not fully if CORS is open. Fix: CSRF token (48-char hex) embedded in JWT payload, returned in login/register/me response body. Frontend stores in React state only; sends as X-CSRF-Token header on all POST/PUT/PATCH/DELETE. requireAuth middleware validates token on mutating requests. Breaking risk: Low-Medium.


M3 β€” No Audit Logging

Status: βœ… Fixed Issue: No persistent log of sensitive actions (user creation, invoice changes, status updates). Console logs are ephemeral. Fix: Added audit_logs table (migration 018); logs actor, action, resource, detail, timestamp on: user create/update/delete/reset-password, invoice create/delete/send/ship/send-to-queue. Breaking risk: None β€” additive only.


M4 β€” No Session Timeout / Activity Monitoring

Status: βœ… Fixed Issue: Tokens valid 7 days with no activity-based expiry. Fix: 30min idle timer in AuthContext; 60-second countdown warning modal before auto-logout. Breaking risk: Low.


M5 β€” No Database Connection SSL

Status: βœ… Fixed File: packages/backend/src/config/database.ts Issue: No ssl option in pg pool config. If DB is remote, credentials/data sent in plaintext. Fix: Enable ssl: { rejectUnauthorized: false } for production. Breaking risk: Low β€” config-only change.


M6 β€” Upload Directory Path Not Validated

Status: βœ… Fixed File: packages/backend/src/middleware/upload.middleware.ts Issue: UPLOAD_DIR env var used without path traversal validation. Fix: Resolve and validate path stays within expected root at startup. Breaking risk: None.


M7 β€” No Email Format Validation on Customer

Status: βœ… Fixed Issue: Customer email stored without format validation. Malformed emails silently saved. Fix: Validate email format in customer create/update controller. Breaking risk: Low β€” rejects invalid emails on write.


M8 β€” No Rate Limiting on Password Reset

Status: βœ… Fixed File: packages/backend/src/routes/users.routes.ts Issue: Admin password reset endpoint has no rate limiting. Fix: Add rate limiter to password reset route (5 req/15min). Breaking risk: None.


M9 β€” No Logging of Auth Failures

Status: βœ… Fixed File: packages/backend/src/services/auth.service.ts Issue: Failed login attempts not logged β€” brute-force attacks invisible. Fix: Log failed attempts with timestamp and username (not password). Breaking risk: None.


Low / Info

L1 β€” Missing Security Headers

Status: βœ… Fixed Fix: Added Referrer-Policy and Permissions-Policy to nginx (both server and static file location blocks).

L2 β€” Dependency Versions Use Caret Ranges

Status: βœ… Fixed (audit) Fix: Ran npm audit fix β€” patched multer (3 high DoS CVEs). Caret ranges remain; audit should be run regularly.

L3 β€” Ollama Model Name Not Whitelisted

Status: βœ… Fixed Fix: Validate OLLAMA_MODEL against an allowlist at startup; exits if not recognized.


Fix Order

Immediate (zero/low breaking risk)

  • C1 β€” Command injection
  • C2 β€” suggestSku parameterization
  • C3 β€” Password minimum length
  • H1 β€” Rate limiting
  • H4 β€” JWT secret strength check
  • H8 β€” PDF magic byte validation
  • H9 β€” Error handler message leak

Careful (test before deploying)

  • H2 β€” CORS restriction
  • H5 β€” HTTPS / HSTS
  • H6 β€” Content-Security-Policy

Plan properly

  • H3 β€” JWT expiry (24h)
  • H7 β€” JWT β†’ HttpOnly cookies
  • M1 β€” Input validation (Zod)
  • M2 β€” CSRF protection
  • M3 β€” Audit logging

There aren't any published security advisories