SECURITY_AUDIT.md
Garuda Chain Ecosystem — Audit Keamanan & Rekomendasi
| Metadata |
|
| Versi dokumen |
1.0.0 |
| Tipe |
Internal assessment (bukan audit eksternal formal) |
| Scope |
Wallet, API, Bridge, Smart Contracts, Storage |
| Terakhir diperbarui |
2026-07-04 |
| Status audit eksternal |
⏳ Pending (SEC-013) |
1. Executive Summary
Garuda Chain memiliki fondasi keamanan smart contract yang solid (OpenZeppelin, ReentrancyGuard, AccessControl, pausable, bridge limits). Lapisan aplikasi (API, Wallet) memiliki celah operasional yang perlu ditangani sebelum skala jutaan pengguna.
| Area |
Rating |
Ringkasan |
| Smart Contracts |
🟢 Baik |
OZ patterns, limits, pausable — audit eksternal pending |
| API Authentication |
🟡 Cukup |
Wallet auth bagus; beberapa endpoint write tanpa auth |
| Wallet Key Management |
🔴 Risiko tinggi |
Plaintext private key di sessionStorage |
| Data Storage |
🟡 Cukup |
JSON files, PII tidak terenkripsi at rest |
| Bridge Security |
🟡 Cukup |
Relayer terpusat — inherent trust model |
| Infrastructure |
🟢 Baik |
TLS, rate limit, Helmet — CORS perlu diperketat |
| Admin Console |
🟡 Cukup |
API key di sessionStorage, no 2FA |
Temuan kritis (P0): 2 · Tinggi (P1): 6 · Sedang (P2): 8 · Rendah (P3): 5
2. Metodologi
Assessment berdasarkan:
- Review kode sumber (
apps/api, apps/wallet, contracts/)
- Threat model existing:
docs/security/threat-model.md
- OWASP API Security Top 10
- Best practices Web3 wallet security
- Tidak termasuk: penetration test aktif, formal verification
3. Smart Contract Security
3.1 Kekuatan
| Kontrol |
Implementasi |
| Reentrancy |
ReentrancyGuard di Staking, PayHub, Bridge, NFT |
| Access control |
AccessControl + role constants di semua kontrak |
| Emergency pause |
Pausable + GarudaSecurityCouncil |
| Bridge limits |
Daily limit 5M GDC, per-recipient inbound limit |
| Idempotency |
outboundLocked, inboundProcessed mappings |
| Treasury |
Embedded MultiSig 3-of-5 |
| Community claims |
EIP-712 + nonce replay protection |
| Token mint |
MINTER_ROLE gated |
3.2 Temuan
| ID |
Severity |
Temuan |
Rekomendasi |
| SC-001 |
P1 |
Relayer RELAYER_ROLE dapat mint unlimited via releaseInbound |
Audit eksternal; monitoring anomali mint; multi-sig relayer |
| SC-002 |
P1 |
Tidak ada timelock untuk DEFAULT_ADMIN_ROLE |
Deploy TimelockController untuk admin ops |
| SC-003 |
P2 |
Validator registry tidak sinkron dengan Besu IBFT |
Dokumentasi operasional; governance untuk IBFT set |
| SC-004 |
P2 |
Staking reward solvency — manual depositRewards() |
On-chain balance check + alert jika reward pool rendah |
| SC-005 |
P2 |
SimpleDEX tanpa oracle protection |
Rate limit bridge; monitor pool manipulation |
| SC-006 |
P3 |
Upgrade via redeploy (bukan proxy) |
Acceptable untuk saat ini; dokumentasi migration path |
| SC-007 |
P1 |
Audit eksternal belum dilakukan |
Jadwalkan audit sebelum Horizon 3 |
3.3 Residual Risks (dari threat model)
- HSM belum deployed untuk validator keys (SEC-014)
- Formal verification pending (SEC-015)
4. API Security
4.1 Kekuatan
| Kontrol |
Status |
| Helmet security headers |
✅ |
| Rate limiting (GET/POST) |
✅ |
| Wallet EIP-191 auth |
✅ Production |
| Admin API key |
✅ |
| RPC method allowlist |
✅ |
| Body size limit (15MB) |
✅ KYC upload |
| Trust proxy |
✅ |
4.2 Temuan
| ID |
Severity |
Endpoint / Area |
Temuan |
Rekomendasi |
| API-001 |
P0 |
POST /bridge/relay, /process, /track |
Trigger relayer tanpa auth |
Require admin key atau HMAC relayer token |
| API-002 |
P0 |
POST /graphql |
Tidak ada auth |
Disable di prod atau add auth + depth limit |
| API-003 |
P1 |
POST /validators/applications |
Write ke disk tanpa auth |
Rate limit ketat + captcha + honeypot |
| API-004 |
P1 |
CORS default * |
CSRF-like abuse dari origin manapun |
CORS_ORIGIN restrict ke domain Garuda |
| API-005 |
P1 |
Rate limit bypass luas |
/garuda-pay/*, /community/*, /accounts/* unthrottled |
Per-endpoint + per-IP limits |
| API-006 |
P1 |
ALLOW_OPEN_ADMIN=true |
Admin terbuka di dev |
Pastikan tidak pernah di production env |
| API-007 |
P2 |
JSON file writeFileSync |
Race condition corrupt data |
File lock atau migrasi DB |
| API-008 |
P2 |
Operator key sprawl |
DEPLOYER_PRIVATE_KEY, BRIDGE_*, CLAIM_SIGNER_* |
Vault/HSM; key rotation policy |
| API-009 |
P2 |
Tidak ada input validation library |
Ad-hoc regex checks |
Zod schema per route |
| API-010 |
P2 |
GraphQL introspection |
Schema exposure |
Disable introspection di production |
| API-011 |
P3 |
Error messages |
Mungkin leak internal paths |
Sanitize error responses |
| API-012 |
P3 |
No API automated tests |
Regresi security tidak terdeteksi |
Vitest security test suite |
4.3 Wallet Auth (Positif)
Implementasi apps/api/src/auth/walletAuth.ts:
- Message canonical: address + action + timestamp + body hash
- 5 menit TTL
- Body hash dengan sorted keys (prevent tampering)
verifyMessage ethers
Rekomendasi tambahan: nonce per-action (selain check-in) untuk prevent replay dalam window TTL.
5. Wallet Security
5.1 Kekuatan
| Kontrol |
Status |
| Encrypted at rest (PBKDF2 120k + AES-GCM) |
✅ lib/storage.ts |
| Auto-lock idle 5 menit |
✅ hooks/useAutoLock.ts |
| Wallet-signed API requests |
✅ lib/walletAuth.ts |
| Mnemonic backup encrypted |
✅ |
| No private key in URL |
✅ |
5.2 Temuan
| ID |
Severity |
Area |
Temuan |
Rekomendasi |
| WAL-001 |
P0 |
sessionStorage |
Plaintext { address, privateKey } 12h TTL |
Memory-only unlock; session token opaque |
| WAL-002 |
P1 |
React props |
privateKey di-prop ke banyak screen |
Context dengan secure getter; clear on unmount |
| WAL-003 |
P1 |
XSS surface |
Tidak ada CSP documented |
Strict CSP via Cloudflare Pages _headers |
| WAL-004 |
P1 |
KYC draft |
PII di sessionStorage (kycDraft.ts) |
Server-side draft atau encrypt |
| WAL-005 |
P2 |
Profile photos |
Base64 di localStorage |
Size limit + optional server upload |
| WAL-006 |
P2 |
Single bundle |
1.2MB JS — large attack surface |
Code splitting |
| WAL-007 |
P3 |
Auto-lock vs sessionStorage |
Lock UI tapi key masih di session |
Clear sessionStorage on lock |
5.3 Threat: XSS → Full Compromise
Jika attacker inject script di wallet origin:
1. Read sessionStorage → private key
2. Read localStorage → encrypted wallet (brute-force jika password lemah)
3. Sign transactions
Mitigasi prioritas: CSP strict + hilangkan plaintext key dari sessionStorage.
6. Admin Monitor Security
| ID |
Severity |
Temuan |
Rekomendasi |
| ADM-001 |
P1 |
Admin key di sessionStorage |
Short-lived JWT + httpOnly cookie (BFF) |
| ADM-002 |
P2 |
No 2FA |
TOTP untuk admin login |
| ADM-003 |
P2 |
No session expiry |
Auto-logout 8 jam |
| ADM-004 |
P3 |
KYC PII di browser |
Expected untuk review; audit log access |
7. Bridge Security
| ID |
Severity |
Temuan |
Rekomendasi |
| BRG-001 |
P1 |
Custodial relayer model |
Document trust assumptions; proof-of-reserves publik |
| BRG-002 |
P1 |
Hot wallet relayer di ETH/BSC/Polygon |
Multi-sig relayer; balance alerts |
| BRG-003 |
P2 |
Shared vault address cross-chain |
Per-chain vault isolation |
| BRG-004 |
P2 |
Rate oracle dari DEX |
TWAP + circuit breaker |
| BRG-005 |
P2 |
transferId includes Date.now() |
Client-coordinated UUID; server validation |
| BRG-006 |
P3 |
Legacy bridge scanning |
Deprecate setelah migration complete |
8. Data & Privacy
| ID |
Severity |
Temuan |
Rekomendasi |
| DAT-001 |
P1 |
KYC PII di plain JSON files |
Encrypt at rest; PostgreSQL + S3 KMS |
| DAT-002 |
P1 |
No automated backup test |
Monthly restore drill |
| DAT-003 |
P2 |
CS images di filesystem |
S3 dengan access control |
| DAT-004 |
P2 |
No data retention policy |
Auto-purge rejected KYC setelah N hari |
| DAT-005 |
P3 |
Address lowercase normalization |
Consistent — sudah baik |
Compliance note: KYC Level 2 menyimpan data identitas — perlu kebijakan retensi sesuai regulasi Indonesia (UU PDP).
9. Infrastructure Security
| Kontrol |
Status |
Rekomendasi |
| TLS (Caddy/Cloudflare) |
✅ |
Maintain cert auto-renewal |
| Firewall VPS |
✅ |
Restrict admin ports |
| Docker isolation |
✅ |
Non-root containers |
| Secrets in env vars |
🟡 |
Migrate to Vault |
| RPC rate limit |
✅ |
WAF layer di Cloudflare |
| DDoS protection |
🟡 |
Cloudflare proxy untuk RPC publik |
| Log aggregation |
✅ Loki |
Alert on anomaly |
| Incident response |
✅ docs/security/incident-response.md |
Drill quarterly |
10. Explorer Security
| Area |
Assessment |
| Attack surface |
Rendah — read-only, no auth, no client storage |
| Server env |
RPC URLs tidak exposed ke client |
| SSRF |
RPC proxy server-side only — OK |
11. Action Plan (Prioritas)
| # |
Action |
Owner |
Target |
| 1 |
Auth pada bridge relay/process/track |
Backend |
Staging |
| 2 |
CORS restrict |
DevOps |
Staging → Prod |
| 3 |
CSP headers wallet |
Frontend |
Cloudflare |
| 4 |
Rate limit validator applications |
Backend |
Staging |
| 5 |
GraphQL auth atau disable mutation |
Backend |
Staging |
Short-term (Horizon 1–2)
| # |
Action |
| 6 |
Wallet: remove plaintext key from sessionStorage (POC) |
| 7 |
API Vitest security tests |
| 8 |
Zod validation layer |
| 9 |
Operator key inventory + rotation doc |
| 10 |
Schedule external smart contract audit |
Medium-term (Horizon 2–4)
| # |
Action |
| 11 |
PostgreSQL + encrypted PII |
| 12 |
Admin 2FA |
| 13 |
Vault/HSM for operator keys |
| 14 |
Bridge multi-sig relayer |
| 15 |
Penetration test API + Wallet |
12. Compliance Checklist
| Requirement |
Status |
| Privacy policy published |
✅ docs/legal/privacy.md |
| Terms of service |
✅ docs/legal/terms.md |
| Bug bounty program |
✅ docs/security/bug-bounty.md |
| Incident response plan |
✅ |
| KYC data handling policy |
⏳ Perlu dokumen retensi |
| External security audit |
⏳ Pending |
| SOC 2 / ISO 27001 |
❌ Not started |
13. Referensi