NodeJS adalah teknologi backend yang cepat dan fleksibel, tetapi bukan platform yang aman secara default.
Banyak kasus kebocoran data, API abuse, dan server takeover terjadi bukan karena NodeJS buruk, melainkan karena konfigurasi keamanan yang diabaikan.
Kesalahan paling umum:
- Input tidak divalidasi
- Secret hardcoded
- Dependency tidak diaudit
- Server dijalankan sebagai root
- Tidak ada rate limiting
- Error stack trace bocor ke publik
Artikel ini membahas best practices keamanan NodeJS secara menyeluruh, mulai dari level kode, API, dependency, server, hingga arsitektur, lengkap dengan contoh nyata yang benar-benar digunakan di production.
Contents
- 1 1. Prinsip Dasar Keamanan NodeJS
- 2 2. Jangan Pernah Percaya Input User (WAJIB)
- 3 3. Lindungi dari SQL & NoSQL Injection
- 4 4. Authentication & Authorization yang Aman
- 5 5. Lindungi API dengan Rate Limiting
- 6 6. Jangan Bocorkan Error Internal
- 7 7. Gunakan Security Headers (Helmet)
- 8 8. CORS Configuration yang Ketat
- 9 9. Lindungi Environment Variable & Secret
- 10 10. Dependency Security (Sering Diabaikan)
- 11 11. Lindungi dari Prototype Pollution
- 12 12. File Upload Security
- 13 13. Jangan Jalankan NodeJS sebagai Root
- 14 14. HTTPS Wajib di Production
- 15 15. Logging & Monitoring Security
- 16 16. Security untuk High Traffic & SaaS
- 17 17. Checklist Keamanan NodeJS Production
- 18 18. Studi Kasus Nyata
- 19 Kesimpulan
- 20 Related Posts
1. Prinsip Dasar Keamanan NodeJS
Sebelum masuk ke teknis, pahami satu prinsip utama:
NodeJS tidak aman secara default. Keamanan adalah tanggung jawab developer.
Tujuan utama security:
- Melindungi data
- Mencegah abuse
- Mengurangi blast radius saat breach terjadi
- Menjaga stabilitas bisnis
2. Jangan Pernah Percaya Input User (WAJIB)
2.1 Contoh Kode Berbahaya
app.post('/login', (req, res) => {
const { email } = req.body;
db.query(`SELECT * FROM users WHERE email='${email}'`);
});
❌ Rentan SQL Injection
❌ Rentan NoSQL Injection
2.2 Validasi & Sanitasi Input
Gunakan library validation:
npm install joi
const Joi = require('joi');
const schema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().min(8).required()
});
app.post('/login', (req, res) => {
const { error } = schema.validate(req.body);
if (error) {
return res.status(400).json({ message: 'Invalid input' });
}
});
📌 Rule emas:
Semua input → validasi → baru diproses.
3. Lindungi dari SQL & NoSQL Injection
3.1 SQL Injection (Solusi Benar)
Gunakan parameterized query:
db.query(
'SELECT * FROM users WHERE email = ?',
[email]
);
3.2 NoSQL Injection (MongoDB)
❌ Salah:
User.findOne(req.body);
✅ Benar:
User.findOne({ email: req.body.email });
4.1 Jangan Simpan Password Polos
❌ Fatal:
password: "123456"
4.2 Gunakan Hashing (bcrypt)
npm install bcrypt
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);
Saat login:
await bcrypt.compare(inputPassword, storedHash);
4.3 JWT dengan Aman
❌ Salah:
- Secret pendek
- Token tanpa expiry
✅ Benar:
jwt.sign(
{ userId },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
📌 Gunakan refresh token untuk sesi panjang.
5. Lindungi API dengan Rate Limiting
Tanpa rate limit = undangan brute force.
npm install express-rate-limit
app.use(rateLimit({
windowMs: 15 * 60 * 1000,
max: 100
}));
Untuk endpoint sensitif:
max: 5 // login
6. Jangan Bocorkan Error Internal
6.1 Error Handling Berbahaya
res.status(500).send(err.stack);
❌ Memberi roadmap ke attacker.
6.2 Error Handling Aman
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({ message: 'Internal Server Error' });
});
7. Gunakan Security Headers (Helmet)
npm install helmet
const helmet = require('helmet');
app.use(helmet());
Melindungi dari:
- XSS
- Clickjacking
- MIME sniffing
8. CORS Configuration yang Ketat
❌ Salah:
app.use(cors());
✅ Benar:
app.use(cors({
origin: ['https://domainanda.com'],
methods: ['GET', 'POST']
}));
9. Lindungi Environment Variable & Secret
9.1 Jangan Hardcode Secret
❌:
const SECRET = '123456';
9.2 Gunakan .env dengan Aman
JWT_SECRET=super-secret-key
process.env.JWT_SECRET
🔒 Pastikan:
.envtidak di-commit- Permission file ketat
10. Dependency Security (Sering Diabaikan)
10.1 Audit Dependency Secara Rutin
npm audit
10.2 Hindari Dependency Tidak Perlu
Semakin banyak dependency:
- Attack surface makin besar
📌 Prinsip: less is safer
11. Lindungi dari Prototype Pollution
Pastikan:
- Validasi input JSON
- Update dependency
Gunakan:
Object.create(null)
untuk objek sensitif.
12. File Upload Security
12.1 Validasi File Upload
❌ Terima semua file
✅ Batasi:
if (!['image/png', 'image/jpeg'].includes(file.mimetype)) {
throw new Error('Invalid file');
}
12.2 Jangan Simpan di Root Server
Gunakan:
- Cloud storage
- Folder terisolasi
13. Jangan Jalankan NodeJS sebagai Root
Buat user khusus:
adduser nodeapp
Jalankan app sebagai user tersebut.
14. HTTPS Wajib di Production
Gunakan:
- Nginx + SSL
- Let’s Encrypt
Tanpa HTTPS:
- Token bisa dicuri
- Data bocor
15. Logging & Monitoring Security
Pantau:
- Login gagal
- Rate limit trigger
- Error abnormal
Gunakan:
- Centralized logging
- Alert otomatis
16. Security untuk High Traffic & SaaS
Tambahan wajib:
- Rate limit per user
- IP throttling
- API key rotation
- Tenant isolation
17. Checklist Keamanan NodeJS Production
✅ Input validation
✅ Password hashing
✅ JWT expiry
✅ Rate limiting
✅ Error handling aman
✅ Helmet
✅ CORS ketat
✅ HTTPS
✅ Dependency audit
✅ User non-root
18. Studi Kasus Nyata
Masalah
- API login diserang brute force
- Server overload
- Akun bocor
Solusi
- Rate limit login
- CAPTCHA
- Token expiry pendek
Hasil
- Serangan berhenti
- Server stabil
- Tidak ada kebocoran data
Kesimpulan
NodeJS bisa sangat aman, tetapi hanya jika keamanan diperlakukan sebagai bagian dari arsitektur, bukan fitur tambahan.
Keamanan bukan soal “tidak diserang”, tapi soal “siap saat diserang”.
Investasi di security = perlindungan bisnis jangka panjang.