Files

7.0 KiB

Security

Reporting

Report vulnerabilities to andikadebiputra@gmail.com. Please do not open public issues for security problems.

We aim to acknowledge within 48 hours and to ship a fix or mitigation for critical issues within 7 days.


Supply Chain — Known Advisories (as of 2026-05-15)

Backend (composer audit)

  • No vulnerability advisories.
  • laragear/webauthn is marked abandoned. Replacement: laravel/passkeys. Migration planned for a separate change since the public surface differs.

Frontend root (npm audit)

  • No vulnerabilities.

Mobile (mobile/, npm audit)

  • 4 moderatepostcss < 8.5.10 (GHSA-qx2v-qp2m-jg93, XSS via unescaped </style> in CSS output).
  • Path: transitively pulled by expo@expo/cli@expo/metro-configpostcss.
  • Reachability: the vulnerable code path is in dev build tooling, not the runtime bundle shipped to devices. End-user impact is low.
  • Fix requires bumping Expo SDK (breaking change). Tracked separately.

CI runs composer audit --abandoned=ignore on every push and will fail on new vulnerabilities.


Defense in Depth

Authentication

  • 2FA — email OTP (6 digit) with optional trust-device cookie (UUID + secret hashed, 30 days). Verify endpoint rate-limited 5/min.
  • Passkey (WebAuthn) — via laragear/webauthn, FIDO2-compliant. Login flow is challenge-bound.
  • Social OAuth — Google, Facebook, GitHub via Socialite. Callback explicitly refuses identity-overwrite when an email is already linked to a different provider id.
  • Captcha — Google reCAPTCHA v2/v3 toggleable per environment.

Authorization

  • Spatie permission/role system with active-permission gate — a permission can be disabled centrally without revoking it from each role.
  • Granular tab permissions — 85 named permissions covering every settings tab in Global Settings and Mobile Settings. CheckTabPermission middleware enforces access; @cantab/@managetab Blade directives available for views.
  • Impersonation guarded against: self-impersonate, Developer role, inactive users, and nested loop. Tracked in Cache for the target user awareness banner and audit logged via ImpersonationStatusChanged event.

Network & Boundary

  • IP access controlIpAccessControl middleware with:
    • Global blacklist
    • Admin route whitelist (/users*, /roles*, /permissions*, /system-config*, /backups*, /admin/*)
    • Auto-block IPs that exceed configurable burst threshold (24h cooldown). Sends Telegram firewall alert.
    • HSTS toggle (HTTPS only).
  • Security headersSecurityHeaders middleware sets X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, Referrer-Policy: strict-origin-when-cross-origin, Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), X-XSS-Protection, and (when HTTPS + opt-in) Strict-Transport-Security: max-age=31536000; includeSubDomains; preload.
  • Rate limit — Per-endpoint throttle: /login (5/min), /2fa verify (5/min), /forgot-password, /api/v1/login (10/min), /api/v1/register (5/min), /api/v1/otp/send (5/min), /api/v1/otp/verify (10/min). Per-IP buckets isolated.
  • Single-session enforcement — optional; logs out previous device when user logs in elsewhere.

Passwords & Sessions

  • Bcrypt 12 rounds in production (4 in test for speed).
  • Password policy (App\Services\Auth\PasswordPolicyService): min/max length, mixed-case, digit, symbol, expiry, history reuse blocker (configurable N).
  • Password history stored hashed in password_histories; reuse of last N raises validation error.
  • Sessions stored in Redis. Admins can revoke sessions per user from /system-settings/session-manager.

Data Integrity

  • Foreign keys — all audit (created_by/updated_by) → users(id) ON DELETE SET NULL. Owned data (password_histories, user_consents, user_trusted_devices, model_has_*, role_has_permissions) → ON DELETE CASCADE. Cascade behavior is locked in by tests/Feature/Database/CascadeIntegrityTest.php.
  • Composite indexes on hot lookups (password_histories(user_id, created_at), system_setting_revisions(key, created_at), notifications(notifiable, read_at)).
  • Soft deletes — User, Role, Permission. Restore + force-delete flows tested.

Data Retention

Semua data time-sensitive memiliki kebijakan retensi otomatis yang dijalankan oleh scheduler harian:

Tabel Retensi Mekanisme
otp_codes Setelah expired OtpCode::prunable()expires_at < now()
user_trusted_devices Setelah expired UserTrustedDevice::prunable()expires_at < now()
ai_healing_logs 90 hari AiHealingLog::prunable()created_at
password_histories 365 hari PasswordHistory::prunable()created_at
mobile_error_logs 90 hari MobileErrorLog::prunable()occurred_at
ai_usage_logs 90 hari AiUsageLog::prunable()created_at
mobile_sync_logs 30 hari MobileSyncLog::prunable()synced_at
notifications 30 hari Notification::prunable()created_at
activity_log 365 hari activitylog:clean via Spatie config
telescope_entries 48 jam telescope:prune --hours=48
dashboard_widget_preferences Dihapus saat user dihapus FK ON DELETE CASCADE ke users

Scheduler berjalan: model:prune pukul 03:00, telescope:prune pukul 03:05, activitylog:clean harian. Sesuai prinsip data minimization UU PDP No. 27/2022.

Audit & Forensics

  • Spatie ActivityLog on User, Role, Permission, SystemSetting.
  • System config revisions — separate system_setting_revisions table captures actor, IP, user agent on every change.
  • ActivityFormatter redacts sensitive keys (password, remember_token, secret, key, token, 2fa_secret) from displayed diffs.

Error Handling & Monitoring

  • Custom exception classesApp\Exceptions\{SystemConfig,BackupOperation,Monitoring}Exception with factory methods, allowing specific handlers rather than generic \Exception catches.
  • Sentry — production error reporting; sample rates set in .env.
  • Health endpointGET /api/health reports DB, Redis, storage, queue; returns 503 only when any check fails, 200 for warn (e.g. disk >90%).

Quality Gate

Check Tool Threshold
Unit + feature tests Pest 4 All passing
Static analysis Larastan level 5 + baseline No new errors
Code style Laravel Pint All files PSR-12 compliant
Dependency audit composer audit 0 vulnerabilities
N+1 regression Pest (Query Log) Bounded query count

CI workflow: .github/workflows/ci.yml.


Disclosure Timeline (template)

T+0       Report received
T+48h     Acknowledgement sent
T+7d      Patch landed (critical) / ETA shared (others)
T+30d     Coordinated disclosure window ends