Firebase Service — Keamanan & Hardening
Semua item di bawah telah diimplementasikan dan diverifikasi per audit keamanan 2026-05-29–2026-06-05.
Keamanan & Hardening
Autentikasi & Validasi Token
-
JWT wajib klaim
exp: Parser Firebase JWT dikonstruksi denganWithExpirationRequired()sehingga token yang tidak memiliki klaimexp— misalnya yang dibuat via tooling debug atau JWKS override di staging — ditolak secara tegas dan tidak pernah diterima sebagai valid tanpa batas waktu. -
Masking FCM token di error response: Helper
maskTokendipakai di seluruh error response yang menyertakanpush_token. Token FCM asli tidak pernah muncul di caller response maupun log storage — hanya versi tersamar yang tercatat. -
Masking penuh di endpoint list/lookup: Fungsi
toTokenResponse()menggunakan formatmaskTokenFull()(polaxxxx****xxxx) sehingga full FCM registration token tidak bisa diekstrak dari endpoint list maupun lookup meskipun caller memiliki API key internal yang valid. -
JWKS dibaca dengan batas ukuran: Response dari endpoint Google JWKS dibaca via
io.LimitReaderdengan batas 512 KB. Server JWKS yang misbehaving — termasuk override di lingkungan non-production — tidak bisa menguras memori proses firebase_service.
Input Validation & Pembatasan Body
-
Middleware body limit global:
maxBodySizeMiddlewaremenggunakanhttp.MaxBytesReader1 MB yang dibungkus di level mux, bukan per-handler. Seluruh POST endpoint (send, bulk send, broadcast, token register, prefs, auth) terlindungi seragam dari serangan body sangat besar tanpa perlu konfigurasi per-route. -
Batas token per request bulk send:
handleSendBulkmembatasi maksimum 500 token per request. Caller tidak bisa mengeksploitasi endpoint ini untuk menguras connection pool database atau FCM quota sekaligus via satu request besar. -
Batas pagination token list:
handleTokenListActivemeng-enforce limit maksimum 5000 terlepas dari nilai?limityang dikirim caller. Query?limit=1000000di-cap otomatis. -
Validasi format Operator User ID:
handleCancelBroadcastmemvalidasi format UUID untuk headerX-Operator-User-IDsebelum mencatat audit log. Audit trail tidak bisa diatribusikan ke user ID sembarang atau string tak berstruktur.
Broadcast Security & Idempotency
-
Transaksi DB dilepas sebelum fan-out FCM:
FetchAndLockReadyBroadcastmelakukan commit segera setelah status broadcast berubah kesending. Fan-out pengiriman FCM ke semua token berjalan di luar transaksi database, sehingga broadcast berskala besar tidak bisa mensaturasi connection pool. -
Override rate-limit wajib identitas operator: Field
override_reasonhanya diproses jika headerX-Operator-User-IDyang valid turut disertakan. Bypass rate limit tanpa identitas operator yang jelas tidak dimungkinkan; setiap penggunaan dicatat viaslog.Warnsebagai audit trail. -
Idempotency SETNX atomik: Idempotency middleware menggunakan operasi SETNX atomik Redis sebelum handler dieksekusi. Dua request concurrent dengan idempotency key yang sama tidak bisa keduanya meng-trigger pengiriman FCM — hanya satu yang dieksekusi, yang lain mendapat respons dari cache.
-
Fail-open idempotency dengan notifikasi eksplisit: Saat Redis tidak tersedia, middleware mengizinkan request berlanjut (fail-open) dan menambahkan header
X-Idempotency-Skipped: redis-errorpada respons disertaislog.Warn. Operator mengetahui kapan protection tidak aktif tanpa ada request yang diblokir secara diam-diam.
Information Disclosure Prevention
-
Error Google API tidak bocor ke caller: Saat FCM send failure atau Google OAuth failure, detail error dari Google API (termasuk Firebase project ID, service account info, dan quota information) hanya dicatat via
slog.Errordi sisi server. Caller hanya menerima pesan generik sepertifcm send failed (status 429)ataugoogle oauth failed (status 503). -
Endpoint
/readytanpa detail PostgreSQL: Saat koneksi database gagal,/readymengembalikan stringping_failedtanpa menyertakan hostname DSN, port, atau username. Infrastruktur monitoring tetap mendapat sinyal kesehatan tanpa mengekspos topologi database. -
Endpoint
/healthminimal:/healthhanya mengembalikan{service, status}. Fieldfirebase_configured,postgres_configured, danapp_envtelah dihapus dari response publik. Attacker tidak bisa memetakan state konfigurasi internal (apakah Firebase credentials dimuat, environment staging vs production) via endpoint unauthenticated ini.