Belajar Ruby on Rails - Security Best Practices
Episode 18 of 27

Belajar Ruby on Rails - Security Best Practices

Membedah keamanan Rails: perlindungan bawaan terhadap SQLi, XSS, CSRF, dan mass assignment, security headers, serta praktik audit dan hardening aplikasi

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

Pendahuluan

Setelah di episode 17 kalian bisa melihat ke dalam aplikasi lewat log, episode 18 membahas topik yang tidak boleh ditunda: keamanan. Rails memblokir banyak serangan secara default — tetapi hanya jika kalian memahami apa yang dilindungi dan di mana harus tetap waspada.

Mengapa episode ini penting? Karena aplikasi web adalah permukaan serangan publik: siapa pun di internet bisa mencoba menginjeksi SQL, mencuri session, atau mengirim form palsu. Kabar baiknya, Rails dirancang dengan keamanan sebagai default — episode ini menjelaskan mengapa default itu bekerja dan apa saja yang harus kalian jaga agar tetap aman.

SQL Injection (SQLi)

SQLi terjadi saat input pengguna disisipkan mentah ke query SQL. Contoh rentan:

RubyRENTAN: interpolasi manual
Post.where("title = '#{params[:title]}'")
# user kirim: x' OR 1=1 --

Rails melindungi dengan query parameterized — Active Record selalu mem-escape input:

RubyAMAN: parameterized query
Post.where(title: params[:title])
Post.where("title = ?", params[:title])          # placeholder ?
Post.where("title ILIKE ?", "%#{params[:q]}%")   # placeholder pada input

Aturan emas: gunakan ? placeholder untuk semua input; jangan pernah interpolasi user input ke SQL string. Hindari execute/sanitize_sql manual kecuali benar-benar diperlukan.

XSS (Cross-Site Scripting)

XSS terjadi saat input user dirender sebagai HTML tanpa escape. Rails meng-escape secara default: semua <%= %> di-escape. Hati-hati hanya saat kalian sengaja menonaktifkannya:

HTMLBANDINGKAN escape vs raw
<%= @post.body %>            <!-- AMAN: di-escape -->
<%= raw @post.body %>        <!-- RENTAN: di-render mentah -->
<%= sanitize @post.body %>   <!-- SANITIZE: HTML diizinkan tapi difilter -->
  • raw / html_safe menonaktifkan escape — jangan dipakai untuk user input.
  • sanitize mengizinkan HTML tertentu dengan whitelist tag — pakai untuk rich text (dengan rails-html-sanitizer yang selalu di-update).

CSRF (Cross-Site Request Forgery)

CSRF menipu browser korban yang sudah login agar mengirim request berbahaya. Rails memblokirnya dengan token CSRF:

HTMLToken CSRF di layout
<%= csrf_meta_tags %>

Semua form yang dibuat form_with otomatis menyertakan authenticity_token; protect_from_forgery (default aktif) memverifikasi token pada request non-GET. Yang harus kalian jaga:

  • Jangan memakai skip_forgery_protection tanpa alasan.
  • Untuk API token (episode 15), CSRF token tidak relevan karena bukan cookie session — itu salah satu alasan token auth lebih disukai untuk API.

Note

Pola yang benar: aplikasi web dengan session cookie → CSRF protection aktif. API yang memakai token di header → CSRF protection tidak diperlukan (tidak ada cookie yang di-forge). Mencampur keduanya butuh kehati-hatian ekstra.

Mass Assignment & Strong Params

Episode 8 sudah membahas ini dalam-dalam — ringkasnya: params.expect/permit memastikan hanya kolom yang di-whitelist yang bisa di-assign. Ingat kembali konsekuensinya:

RubyMengapa strong params menyelamatkan
# RENTAN: user bisa set admin=true via payload manual
@user.update(params[:user])
 
# AMAN: hanya field whitelist
@user.update(params.expect(user: [:name, :email]))

Jika tabel user punya kolom admin, payload POST /users dengan user[admin]=true akan mengeksekusi privilege escalation tanpa strong params.

Security Headers

Rails 8 menyediakan header keamanan di config/initializers/:

Rubyconfig/initializers/content_security_policy.rb
Rails.application.config.content_security_policy do |policy|
  policy.default_src :self
  policy.font_src :self, :https
  policy.img_src :self, :https, :data
  policy.object_src :none
  policy.script_src :self
  policy.style_src :self, :https
end

Header yang dilindungi Rails:

HeaderFungsi
X-Frame-OptionsMencegah clickjacking
X-Content-Type-OptionsMencegah MIME sniffing
Content-Security-Policy (CSP)Membatasi sumber script/asset
Referrer-PolicyMengontrol info yang dikirim via referrer

Cek header app kalian dengan curl -I http://localhost:3000 atau tool securityheaders.com.

Praktik Audit & Hardening

Checklist rutin yang menjaga app tetap aman:

  1. Brakeman — static analyzer Rails: bundle exec brakeman di CI.
  2. Dependency checkbundle audit untuk CVE (episode 19).
  3. Pindahkan secret ke Credentials — episode 16; pastikan tidak ada secret di kode.
  4. Review authorization — episode 9: setiap action sensitif punya authorize.
  5. Rate limit login & API — episode 20.
  6. Jangan expose version di headerconfig.action_dispatch.default_headers bersih.
  7. Escape output & parameterized query — aturan emas episode 18 ini.
Audit dengan Brakeman
bundle exec brakeman -q

Brakeman melaporkan kategori risiko dengan level severity — jadikan hasilnya checklist perbaikan, bukan dokumen yang dibiarkan menumpuk.

Common Pitfalls

  • raw / html_safe pada user input — XSS kembali hidup; gunakan sanitize untuk rich text.
  • skip_forgery_protection tanpa pemikiran — CSRF token hilang; jaga default aktif.
  • Interpolasi SQL manual"WHERE id = #{params[:id]}"; selalu ? placeholder.
  • render json: user polos — kolom sensitif (password_digest) bocor; gunakan serializer.
  • Secret di code/comments — jangan; gunakan Credentials.
  • Header keamanan tidak dicek — aktifkan CSP & pastikan default header aktif.

Penutup

Episode 18 membekali kalian keamanan Rails: parameterized queries melawan SQLi, escaping otomatis melawan XSS, CSRF tokens melawan request forgery, strong params melawan mass assignment, security headers, serta audit rutin dengan Brakeman.

Inti yang harus dibawa pulang:

  • SQLi: selalu ? placeholder, jangan interpolasi input ke SQL.
  • XSS: <%= %> otomatis escape; hindari raw pada user input.
  • CSRF: protect_forgery default; jangan skip tanpa alasan.
  • Mass assignment: params.expect adalah garis pertahanan terakhir.
  • Audit rutin: Brakeman + bundle audit + review authorization.

Di episode 19 selanjutnya kita akan membedah CVE & dependency management — contoh CVE-2026-66066 di Active Storage/vips, security releases Rails, dan praktik update rutin dengan bundle audit. Sampai jumpa di episode 19!