Mengeraskan keamanan CatatanKu: mengelola secrets dengan benar, menerapkan sandboxing per platform, dan membangun secure IPC dengan validasi input serta prinsip least privilege di semua lapisan aplikasi

Sejauh ini CatatanKu tumbuh fitur demi fitur: data lokal, sinkronisasi, update. Namun setiap fitur menambah permukaan serangan. Aplikasi desktop berbahaya justru karena dianggap remeh: ia berjalan native di sistem pengguna, mengakses filesystem, menyimpan data pribadi, dan (mulai episode 13) mengunduh serta menjalankan biner baru. Satu celah di sini bisa berarti pencurian data atau eksekusi kode di mesin pengguna.
Episode ini membangun model keamanan CatatanKu secara sadar: pengelolaan secrets, sandboxing per platform, dan secure IPC. Ini bukan episode "terakhir yang dibaca setelah semua selesai" — keputusan keamanan di episode ini memengaruhi arsitektur yang sudah kita bangun (IPC di episode 2, storage di episode 8, update di episode 13).
Aplikasi desktop menyimpan beberapa jenis rahasia: token API, key enkripsi, credential sinkronisasi. Aturan pertama: jangan pernah menaruhnya di kode, config file plaintext, atau repo. Tiga lapis penyimpanan dari terburuk ke terbaik:
| Tempat | Risiko |
|---|---|
| Hardcode di source code | Terbaca siapa pun yang punya akses repo/binary |
| Config file plaintext | Terbaca malware/file reader |
| OS keychain / secure storage | Enkripsi terikat user & OS (episode 19) |
Di episode 19 kita akan membangun penyimpanan kredensial penuh dengan keychain. Untuk episode ini, prinsip yang harus dipegang:
1. Jangan pernah hardcode secrets di frontend/kode UI
2. Gunakan OS keychain atau secure storage untuk persisten
3. Secrets yang dibutuhkan saat build (signing, API) hidup di CI secret manager
4. Setiap secret punya scope minimal: key untuk catatan ≠ key untuk akun cloudSandboxing menjawab pertanyaan: jika aplikasi ini dikompromi, seberapa jauh penyerang bisa bergerak? Semakin kecil izin, semakin kecil kerusakan. Per platform, pendekatannya berbeda:
Windows → tidak ada sandbox universal; gunakan izin minimum +
AppContainer/MSIX untuk store apps
macOS → App Sandbox (enforced oleh Mac App Store); izin per
capability: files, network, keychain
Linux → Flatpak sandbox, AppArmor/SELinux profile, atau
user namespace; izin per aksesContoh praktis di macOS App Sandbox — aplikasi hanya bisa mengakses apa yang diizinkan:
com.apple.security.app-sandbox → true
com.apple.security.files.user-selected.read-write → file yang dipilih user saja
com.apple.security.network.client → keluar (update & sinkronisasi)
com.apple.security.network.server → false (tidak menerima koneksi)Di Linux, Flatpak memaksa model ini:
[Context]
filesystems=xdg-documents;xdg-config; # hanya folder tertentu
sockets=wayland;x11; # display saja
devices=none;
features=devel; # tanpa akses device
[Environment]
GTK_USE_PORTAL=1Prinsip yang sama berlaku di ketiga framework: akses diberikan per kemampuan, bukan all-or-nothing. Renderer/webview, khususnya, harus dianggap tidak tepercaya sampai terbukti aman.
Note
Sandbox bukan "fitur yang menambah beban" — ini biaya wajib dari aplikasi native. Di Windows, aplikasi tanpa sandboxing menyerahkan seluruh izin user kepada setiap bug memory-safety. Semakin besar target (kantor, perusahaan), semakin penting model ini.
IPC (episode 2) adalah jembatan UI ↔ backend — dan setiap command adalah pintu masuk potensial. Empat praktik wajib:
1. Least privilege — ekspos hanya command yang benar-benar dipakai UI. Jangan ekspos "eksekusi shell umum" hanya karena suatu hari mungkin berguna.
2. Validasi semua input — command adalah API publik bagi webview. Tipe, panjang, format, dan range wajib divalidasi di sisi backend, bukan dipercaya dari frontend:
#[tauri::command]
fn create_note(title: String, content: String) -> Result<Note, String> {
if title.trim().is_empty() {
return Err("judul tidak boleh kosong".into());
}
if title.len() > 200 || content.len() > 1_000_000 {
return Err("ukuran melebihi batas".into());
}
save_note(title.trim(), content)
}3. Konteks pemanggil — jika command membuka file atau mengubah state sensitif, pertimbangkan siapa yang berhak memanggilnya (window mana, URL apa). Tauri punya permission/capability per window; Electron memakai sender validation.
4. Jangan menerima path/jalur sembarang — ulangi pelajaran episode 7: path selalu relatif dan divalidasi terhadap direktori basis.
Mental model yang paling penting: webview/renderer adalah zona tidak tepercaya. Konten apa pun yang sampai ke sana — HTML dari sumber eksternal, atau input pengguna yang dirender — bisa menjadi vektor. Konsekuensinya:
invoke/ipcRenderer dianggap input publik → divalidasi backend.innerHTML tanpa sanitasi.Inti yang harus dibawa pulang:
Di episode 15 selanjutnya kita memastikan CatatanKu tidak rusak saat berkembang: testing desktop apps — unit, integration, dan E2E UI testing dengan Playwright. Sampai jumpa di episode 15!