NodeJS Security Best Practices (Lengkap + Contoh Nyata Production)

NodeJS Security Best Practices (Lengkap + Contoh Nyata Production)

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.


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:

  1. Melindungi data
  2. Mencegah abuse
  3. Mengurangi blast radius saat breach terjadi
  4. 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. Authentication & Authorization yang Aman

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:

  • .env tidak 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.