package main

import (
	"bytes"
	"fmt"
	"html/template"
)

// render mengeksekusi template dan mengembalikan string hasilnya.
func render(t *template.Template, data any) string {
	var buf bytes.Buffer
	if err := t.Execute(&buf, data); err != nil {
		panic(err)
	}
	return buf.String()
}

func main() {
	// Payload XSS yang sama ditempatkan pada lima konteks berbeda.
	const lima = `1. body: <p>{{.}}</p>
2. attr: <p data-info="{{.}}">isi</p>
3. css : <p style="color: {{.}}">isi</p>
4. js  : <script>var payload = {{.}};</script>
5. url : <a href="{{.}}">isi</a>
`

	t := template.Must(template.New("lima").Parse(lima))
	payload := `<script>alert('xss')</script>`

	fmt.Println("=== payload yang sama, lima konteks ===")
	fmt.Println(render(t, payload))

	// Skema URL berbahaya disaring menjadi #ZgotmplZ.
	fmt.Println("=== skema javascript: pada atribut URL ===")
	tTautan := template.Must(template.New("tautan").Parse(`<a href="{{.}}">klik</a>`))
	fmt.Println(render(tTautan, "javascript:alert(1)"))

	// Tipe penanda tepercaya mematikan pengaman pada konteksnya.
	fmt.Println("=== tipe tepercaya: HTML, JS, dan URL ===")
	const raw = `aman: {{.Markup}}
konfigurasi: <script>var k = {{.Konfig}};</script>
tautan: <a href="{{.Tautan}}">buka</a>`
	tRaw := template.Must(template.New("raw").Parse(raw))
	data := map[string]any{
		"Markup": template.HTML(`<b>markup dari editor tepercaya</b>`),
		"Konfig": template.JS(`{versi: 2}`),
		"Tautan": template.URL(`https://example.com/?q=go&halaman=1`),
	}
	fmt.Println(render(tRaw, data))
}
