Junix ID — PT Jalur Utama Nusantara
Junix
Security Transparency

Security Changelog.

Every hardening we ship, in chronological order. Buyers, auditors and peer engineers use this page to gauge how quickly we address findings and how the surface evolves.

1 HIGH5 MEDIUM3 LOWTotal 9
Round 2 hardening — CSV, legacy accounts, cookie-only auth
2026-08-01
MEDIUMSEC-101CSV formula-injection defence in Consent Export

Cells starting with =, +, -, @, tab or CR are prefixed with a single quote so spreadsheet formulas cannot execute on auditors’ machines.

MEDIUMSEC-102Legacy passwordless accounts cannot be silently claimed

Accounts with no passwordHash now return HTTP 409 with code:'recovery_required' and are routed through /forgot-password to prove ownership before binding a password.

LOWSEC-103Recovery endpoint no longer leaks account existence

POST /api/auth/recover returns an identical JSON shape whether the email exists or not; unknown emails receive a decoy code that never validates.

LOWSEC-104Roadmap vote/comment enforce session expiry

Both endpoints now use the shared requireSession helper so expired sessions are rejected and cleaned up, matching every other API route.

LOWSEC-105Cookie-only client auth

Client pages no longer store the bearer token in localStorage; auth flows through the HttpOnly junix_token cookie. Bearer remains supported server-side for integrations.

Round 1 hardening — auth, rate limits, PII, framing
2026-07-31
HIGHSEC-001Passwordless sign-in replaced with scrypt-hashed password auth

POST /api/auth/signin now requires an 8+ char password meeting the shared policy (mixed classes, no long runs, blocklist). Timing-safe scrypt compare, 30-day session TTL, expired-session cleanup, 8/min rate limit.

MEDIUMSEC-002LLM endpoints rate-limited and payload-capped

/api/chat, /api/compliance-chat, /api/playground, /api/deal-room, /api/briefing all funnel through per-IP token buckets (30 or 10/min) plus 20-message / 4000-char caps so no anonymous request can drain the billing key.

MEDIUMSEC-003Deal Room and Briefing gated + consent required

Sales tools now require an authenticated session, capture the caller as createdByEmail, and refuse contact.email input without an explicit consent:true flag. The /deal/[id] viewer enforces creator-or-buyer ownership via the HttpOnly cookie.

MEDIUMSEC-004Clickjacking closed and CORS narrowed

next.config.js now emits X-Frame-Options: SAMEORIGIN, CSP frame-ancestors 'self', X-Content-Type-Options: nosniff and Referrer-Policy; CORS Allow-Headers is Content-Type, Authorization instead of *.

Reporting security findings

Responsible disclosure is welcomed. Please email security@junix.id or open a private issue via the Junix Trust Center. We acknowledge within one business day and publish resolved findings on this page.