Skip to content

Fix: Reflected XSS di halaman kategori potensi - #1784

Open
pandigresik wants to merge 1 commit into
rilis-devfrom
fix/xss_reflected
Open

pandigresik wants to merge 1 commit into
rilis-devfrom
fix/xss_reflected

Conversation

@pandigresik

@pandigresik pandigresik commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Pull Request: Fix: Reflected XSS di halaman kategori potensi

Description

Halaman publik kategori potensi (GET /potensi/{slug}) menulis parameter slug dari URL langsung ke dalam blok <script> tanpa escape. Karakter kutip tunggal pada slug menutup string JavaScript dan menjalankan skrip di origin situs. PR ini memasukkan slug ke JavaScript dengan @json dan mengkodekan nilainya dengan encodeURIComponent saat dipakai di URL API.

Changes made:

  1. View: themes/opendk/default/resources/views/pages/potensi/index.blade.php menyimpan slug sebagai var slug = @json($slug ?? '');, menggantikan {!! $slug ?? '' !!} di dalam string JavaScript.
  2. View: URL request ke API memakai encodeURIComponent(slug) sehingga karakter seperti &, #, ?, dan = tidak mengubah query string.
  3. Test: tests/Feature/Frontend/PotensiPublicTest.php menambahkan test regresi escapes the category slug rendered inside the potensi page script yang mengirim payload x'-alert(1)-' dan memastikan payload mentah tidak muncul di halaman.
  4. Test: beforeEach pada file yang sama kini membuat atau memperbarui NavMenu bernama Potensi dengan URL /potensi. Dua test navigasi sebelumnya bergantung pada data seeder (#) yang tidak dikendalikan test.

Reason for change:

  • Point 1: Slug berasal dari segmen URL yang bisa diisi siapa saja, dan halaman dirender walaupun kategorinya tidak ditemukan, sehingga input sembarang sampai ke view.
  • Point 2: @json memakai JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT, sehingga <, >, &, ', dan " tidak bisa keluar dari string JavaScript.
  • Point 3: Admin tidak bisa menulis slug langsung. Slug kategori dibuat otomatis dari nama_kategori oleh trait Sluggable, dan TipePotensiRequest hanya memvalidasi nama_kategori.

Impact of change:

✅ Keamanan: Payload pada slug tidak lagi bisa menjalankan skrip di halaman publik.
✅ Admin tidak terdampak: Perubahan hanya di halaman publik dan tidak mengubah cara kategori dibuat.
✅ Test lebih stabil: Dua test navigasi tidak lagi bergantung pada nilai seeder yang berbeda antar database.

Related Issue

#1781

Closes #1781

Steps to Reproduce

Before fix (problem):

  1. Buka halaman publik /potensi/x'-alert(1)-' (URL-encoded: /potensi/x%27-alert%281%29-%27)
  2. Halaman dirender dan blok <script> memuat filter[tipe.slug]=x'-alert(1)-'
  3. Browser memproses kutip tunggal sebagai penutup string JavaScript
  4. Skrip alert(1) dieksekusi di origin situs
  5. ❌ Kode sembarang berjalan di halaman publik

After fix (solution):

  1. Buka halaman publik /potensi/x'-alert(1)-'
  2. Halaman dirender dengan var slug = "x'-alert(1)-'";
  3. Request API memakai encodeURIComponent(slug) di query string
  4. Tidak ada skrip yang dieksekusi
  5. ✅ Halaman menampilkan hasil kosong atau pesan "Data tidak ditemukan", tanpa eksekusi skrip

Testing on related features:

  • Halaman /potensi (semua kategori) ✅ test displays all potensi page lulus
  • Halaman /potensi/{slug} dengan slug valid ✅ test displays potensi by category page lulus
  • Halaman detail /potensi/{kategori}/{id} ✅ test displays potensi detail page lulus
  • Menu navigasi dan API /api/frontend/v1/website ✅ dua test navigasi lulus setelah setup data di beforeEach

Checklist

  • I have complied with script writing rules
  • I have followed pull request review process
  • I have created unit test/integration test to verify the fix
  • Manual testing has been done in development environment
  • No console errors or warnings (belum diperiksa di browser)
  • Code has been reviewed by at least 1 person

Technical Details

Technical Explanation

Sebelum perubahan:

url: '{!! $urlApi !!}/potensi?filter[tipe.slug]={!! $slug ?? '' !!}&include=tipe&page[number]=' + page,

Sesudah perubahan:

var slug = @json($slug ?? '');
...
url: '{!! $urlApi !!}/potensi?filter[tipe.slug]=' + encodeURIComponent(slug) + '&include=tipe&page[number]=' + page,

Pemeriksaan yang sudah dilakukan:

  • json_encode dengan flag HEX menghasilkan &, <, ', dan " untuk karakter berbahaya.
  • @json di Laravel memakai encoding options default JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT.

Configuration changes

Tidak ada perubahan konfigurasi.

Dependencies added

No new dependencies

Testing

Manual Testing

  • Buka /potensi/x'-alert(1)-' dan pastikan tidak ada dialog alert
  • Buka /potensi/{slug} untuk kategori yang ada dan pastikan daftar potensi tampil
  • Pindah halaman (pagination) pada kategori dan pastikan request API tetap benar
  • Regression: test halaman /potensi, kategori, dan detail lulus

Automated Testing

  • Feature - escapes the category slug rendered inside the potensi page script (regresi, sebelumnya gagal)
  • Feature - displays all potensi page at /potensi successfully
  • Feature - displays potensi by category page at /potensi/{slug} successfully
  • Feature - displays potensi detail page at /potensi/{kategori}/{id} successfully
  • Feature - ensures nav_menus table contains /potensi for Potensi menu
  • Feature - returns /potensi in the website api navmenus data
  • Playwright / browser test belum dijalankan

Hasil: tests/Feature/Frontend/PotensiPublicTest.php 6/6 lulus (dijalankan 4 kali berturut-turut).

Screenshots / Video

simplescreenrecorder-2026-10-28_06.23.14.mp4

Breaking Changes

None

Migration Guide

Not required

References


Additional notes:

  • Commit 87c87f5c ("perbaikan xss") sudah berisi perubahan ini di branch fix/xss_reflected.
  • Perubahan .env.testing dan .phpunit.cache/test-results di working tree tidak termasuk dalam PR ini.
  • Pint melaporkan masalah format pada banyak file yang tidak terkait; file dalam PR ini tidak termasuk daftar tersebut.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI PR Review sedang antri di server...

Proses review akan segera dimulai di background — hasil akan muncul sebagai komentar setelah selesai.
Powered by CrewAI · PR #1784

@pandigresik pandigresik changed the title perbaikan xss Fix: Reflected XSS di halaman kategori potensi Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant