Belajar Ruby - Security Best Practices
Series/Belajar Ruby/Episode 15
Episode 15 of 23

Belajar Ruby - Security Best Practices

Episode ini membahas keamanan aplikasi Ruby: kerentanan umum seperti SQL injection, command injection, XSS, dan unsafe deserialization, serta alat keamanan Brakeman dan bundler-audit serta penanganan secrets melalui environment variables.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Setelah berhasil membangun REST API di episode 14, pertanyaan berikutnya adalah: apakah aplikasi kalian aman? Keamanan sering dianggap sebagai lapisan terakhir, padahal justru harus dipikirkan sejak awal. Episode 15 ini membahas security best practices dalam pengembangan Ruby.

Kita akan membedah kerentanan umum yang sering ditemukan di aplikasi Ruby — SQL injection, command injection, XSS, dan unsafe deserialization — lalu mengenal dua alat keamanan penting: Brakeman untuk static analysis dan bundler-audit untuk memeriksa gem yang rentan. Terakhir, kita bahas cara menangani secrets melalui environment variables.

SQL Injection dan Command Injection

SQL Injection

SQL injection terjadi ketika input pengguna disisipkan langsung ke dalam string SQL. Bila kalian menulis kueri dengan interpolasi string, penyerang bisa menyuntikkan SQL berbahaya:

RubyContoh rentan SQL injection
user = params["username"]
User.where("name = '#{user}'")

Bila user berisi '; DROP TABLE users; --, kueri di atas bisa merusak tabel. Cara aman: gunakan placeholder parameter. ActiveRecord mengamankan otomatis saat kalian memakai sintaks parameterized:

RubyKueri aman dengan placeholder
User.where("name = ?", params["username"])
User.where(name: params["username"])

User.where("name = ?", ...) mengganti nilai parameter dengan aman tanpa interpolasi langsung. Prinsipnya: jangan pernah menempelkan input mentah ke string SQL. Data pengguna hanya boleh masuk sebagai parameter terikat.

Command Injection

Command injection mirip dengan SQL injection, tetapi targetnya adalah shell sistem. Menjalankan perintah sistem dengan input pengguna yang terinterpolasi sangat berbahaya:

RubyJangan lakukan ini
system("ls #{params["folder"]}")

Bila folder berisi ; rm -rf /, shell akan mengeksekusi perintah setelah titik koma. Gunakan bentuk array agar argumen tidak diterjemahkan oleh shell:

RubyBentuk array yang aman
system("ls", params["folder"])

system("ls", params["folder"]) menjalankan perintah tanpa melewati shell, sehingga karakter shell tidak pernah dievaluasi. Untuk kebutuhan yang kompleks, gunakan library seperti Open3 dan validasi input terlebih dahulu.

XSS dan Unsafe Deserialization

XSS (Cross-Site Scripting)

XSS terjadi ketika data pengguna dirender sebagai HTML tanpa escaping. Di Rails, ERB meng-escape output otomatis dengan sintaks <%= %>, selama kalian tidak menandainya sebagai raw:

RubyEscaping di ERB
<%= user.comment %>
<%== user.comment %>

Baris pertama di-escape aman oleh Rails, sedangkan <%== %> melewatkan escaping dan memicu XSS bila isinya input pengguna. Aturan sederhana: jangan pernah menampilkan input mentah ke browser tanpa sanitasi, dan pastikan Content-Security-Policy aktif di header response.

Unsafe Deserialization

Deserialization dari data yang tidak dipercaya adalah celah serius. Marshal.load dan YAML.load dapat mengeksekusi kode saat memuat objek berbahaya:

RubyMemuat data dengan aman
data = Marshal.load(payload)
safe = YAML.safe_load(payload)

Marshal.load tidak boleh dipakai untuk data dari pengguna. Gunakan format aman seperti JSON untuk pertukaran data, atau YAML.safe_load yang menolak objek selain tipe dasar. Sebagai aturan: deserialize hanya data yang kalian produksi sendiri.

Tools Keamanan: Brakeman dan bundler-audit

Brakeman: Static Analysis

Brakeman adalah static security scanner khusus Rails. Ia membaca source code dan melaporkan kerentanan tanpa menjalankan aplikasi:

Menjalankan Brakeman
gem install brakeman
brakeman --quiet

brakeman --quiet menghasilkan laporan berwarna dengan ringkasan peringatan dan file yang bermasalah. Integrasikan Brakeman ke CI dengan --exit-on-warn agar build gagal ketika ada peringatan baru. Semakin sering dijalankan, semakin cepat kerentanan ditemukan.

bundler-audit: Memeriksa Gem Rentan

Kerentanan juga bisa bersembunyi di gem pihak ketiga. bundler-audit memeriksa Gemfile.lock terhadap database advisories:

Audit dependency
gem install bundler-audit
bundle audit check --update

bundle audit check --update memperbarui database advisory lalu melaporkan gem dengan versi rentan beserta referensi CVEs. Jadwalkan audit ini di CI pada setiap perubahan dependency, bukan hanya sekali-sekali.

Secrets dan Environment Variables

Jangan pernah menulis kunci API, password database, atau token ke dalam source code. Simpan semuanya di environment variables, dan baca dengan ENV:

RubyMembaca secrets dari environment
db_password = ENV["DATABASE_PASSWORD"]
raise "DATABASE_PASSWORD belum diatur" if db_password.nil?

ENV["DATABASE_PASSWORD"] mengambil nilai dari environment. Di pengembangan, gunakan gem seperti dotenv dengan file .env yang masuk gitignore; di production, pasang secrets langsung di environment host atau vault. Rails sendiri menyediakan bin/rails credentials untuk menyimpan secrets terenkripsi.

Warning

Keamanan adalah proses, bukan status. Kombinasi Brakeman, bundler-audit, parameterized query, dan secrets di environment variables menutup sebagian besar celah umum, tetapi tetap lakukan penetration test dan pantau advisories secara berkala.

Penutup

Inti yang harus dibawa pulang:

  • SQL injection dicegah dengan parameterized query, bukan interpolasi string.
  • Command injection dicegah dengan bentuk array di system dan exec.
  • XSS dicegah dengan escaping output dan Content-Security-Policy.
  • Marshal.load dan YAML.unsafe_load tidak boleh untuk data tak tepercaya.
  • Brakeman memindai source code Rails untuk kerentanan statis.
  • bundler-audit memeriksa gem rentan dari Gemfile.lock.
  • Secrets selalu lewat environment variables, bukan source code.

Di episode 16 kita akan mendalami penanganan data yang aman: encoding UTF-8 dan transkoding string, validasi dan sanitasi input, strong params di Rails, hashing password dengan bcrypt, serta prinsip least privilege. Keamanan dari sisi data melengkapi fondasi yang kita bangun sekarang.