5 คะแนน โดย GN⁺ 2026-02-26 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • เพื่อป้องกัน การโจมตี XSS ซึ่งเป็นช่องโหว่สำคัญของเว็บ Firefox จึงรองรับ Sanitizer API ที่เป็นมาตรฐาน เป็นรายแรก
  • หากใช้เมธอด setHTML() แทน innerHTML แบบเดิม ระบบจะทำ การ sanitize HTML ที่ไม่น่าเชื่อถือโดยอัตโนมัติก่อนแทรกลง DOM เพื่อลบสคริปต์อันตราย
  • นักพัฒนาสามารถควบคุมองค์ประกอบและแอตทริบิวต์ที่อนุญาตได้ผ่าน การตั้งค่าแบบกำหนดเอง หากค่าตั้งต้นเข้มงวดเกินไปหรือไม่เพียงพอ
  • ฟีเจอร์นี้ของ Firefox เมื่อใช้งานร่วมกับ Trusted Types จะช่วยยกระดับความปลอดภัยของเว็บโดยรวม และทำให้นักพัฒนาป้องกัน XSS ได้แม้ไม่มีทีมความปลอดภัยเฉพาะทาง

ช่องโหว่ XSS และแนวทางรับมือของ Firefox

  • Cross-site scripting (XSS) เกิดขึ้นเมื่อผู้โจมตีสามารถแทรก HTML หรือ JavaScript ตามอำเภอใจผ่านเนื้อหาที่ผู้ใช้ป้อนเข้ามา
    • ผู้โจมตีอาจใช้สิ่งนี้เพื่อเฝ้าดูการโต้ตอบของผู้ใช้หรือขโมยข้อมูล
    • XSS ถูกจัดอยู่ใน 3 อันดับแรกของช่องโหว่เว็บ (CWE-79) มาเกือบ 10 ปี
  • Firefox ขับเคลื่อนมาตรฐาน Content-Security-Policy (CSP) มาตั้งแต่ปี 2009 เพื่อเสริมการป้องกัน XSS
    • CSP จำกัดทรัพยากรที่เว็บไซต์สามารถโหลดและรันได้
    • อย่างไรก็ตาม เนื่องจากต้องปรับโครงสร้างเว็บไซต์เดิมและต้องมีการทบทวนความปลอดภัยอย่างต่อเนื่อง จึงมี ข้อจำกัดในการนำไปใช้ในวงกว้าง

บทบาทของ Sanitizer API และ setHTML()

  • Sanitizer API มอบวิธีมาตรฐานสำหรับแปลง HTML อันตรายให้เป็นรูปแบบที่ปลอดภัย
    • ในโค้ดตัวอย่าง องค์ประกอบ <img src="x" onclick="alert('XSS')"> จะถูกลบออก และจะเหลือเพียง <h1>Hello my name is</h1>
  • เมธอด setHTML() จะทำกระบวนการ sanitize โดยอัตโนมัติขณะทำการแทรก HTML จึงรับประกัน พฤติกรรมที่ปลอดภัยเป็นค่าเริ่มต้น
    • เพียงแค่แทนที่การกำหนดค่า innerHTML เดิมด้วย setHTML() ก็สามารถสร้าง การป้องกัน XSS ที่แข็งแกร่ง ได้
  • หาก ค่าตั้งต้น เข้มงวดเกินไปหรือหย่อนเกินไป นักพัฒนาสามารถกำหนดองค์ประกอบ HTML และแอตทริบิวต์ที่อนุญาตได้ผ่าน การตั้งค่าแบบกำหนดเอง
    • สามารถใช้เครื่องมือ Sanitizer API playground เพื่อทดลองได้

การทำงานร่วมกับ Trusted Types

  • Trusted Types API ช่วยควบคุมการ parse และการแทรก HTML จากส่วนกลาง เพื่อเพิ่มชั้นความปลอดภัยอีกระดับ
    • เมื่อใช้ setHTML() ก็สามารถบังคับใช้นโยบาย Trusted Types ได้อย่างง่ายดาย
    • นโยบายที่เข้มงวดสามารถอนุญาตเฉพาะ setHTML() และบล็อกวิธีแทรกที่เสี่ยงอื่น ๆ เพื่อช่วย ป้องกันการถดถอยของ XSS ในอนาคต

ผลด้านความปลอดภัยที่ดีขึ้นใน Firefox 148

  • Firefox 148 รองรับทั้ง Sanitizer API และ Trusted Types ทำให้ ระดับความปลอดภัยพื้นฐานสูงขึ้นอย่างมาก
  • นักพัฒนาสามารถ ป้องกัน XSS ได้ด้วยการเปลี่ยนโค้ดเพียงเล็กน้อย โดยไม่ต้องมีนโยบายความปลอดภัยที่ซับซ้อนหรือทีมความปลอดภัยแยกต่างหาก
  • คาดว่าการนำมาตรฐานนี้มาใช้จะช่วย ขยายสภาพแวดล้อมเว็บที่ปลอดภัย ไปยังทุกเบราว์เซอร์

สรุป

  • Firefox 148 รองรับการให้เว็บดีเวลอปเปอร์ บล็อกการโจมตี XSS ได้ง่ายขึ้น ผ่าน เมธอด setHTML() และ Sanitizer API
  • ฟีเจอร์นี้ช่วยอุดข้อจำกัดของ CSP และเป็นจุดเปลี่ยนในการผลักดัน วิธีแทรก HTML ที่ปลอดภัยเป็นค่าเริ่มต้น ให้กลายเป็นมาตรฐานเว็บ
  • เมื่อทำงานร่วมกับ Trusted Types ก็จะช่วยให้รักษาความปลอดภัยระยะยาวและ ป้องกันการถดถอยของ XSS ได้
  • โดยสรุป Firefox กำลังเป็นผู้นำการเปลี่ยนผ่านสู่ สภาพแวดล้อมเว็บที่มีความปลอดภัยเป็นค่าเริ่มต้น

2 ความคิดเห็น

 
huiya 2026-02-26

โอ้ แบบนี้จำเป็นจริง ๆ นะครับ ถ้ารองรับได้ในทุกเบราว์เซอร์ก็น่าจะดีมากเลย

 
GN⁺ 2026-02-26
ความคิดเห็นจาก Hacker News
  • ฟีเจอร์แบบนี้ทำให้รู้สึก ไม่ค่อยสบายใจ อยู่เสมอ
    เพราะมีทั้งเมธอดที่ปลอดภัยแม้จะส่งอินพุตจากผู้ใช้เข้าไปตามตรง และเมธอดที่ไม่ปลอดภัยปะปนกันอยู่ แต่ดูจากชื่ออย่างเดียวแยกได้ยาก
    ตามอุดมคติแล้ว ฟังก์ชันที่อันตรายควรมีชื่อที่บอกความเสี่ยงให้ชัดเจนตั้งแต่แรก
    อีกอย่าง แนวคิดเรื่องการ “sanitize” HTML เองก็คลุมเครือ และตัดสินได้ยากว่าแท้จริงแล้วปลอดภัยหรือไม่

    • เป็นความจริงที่คำว่า “ปลอดภัย” มีความหมายไม่ชัดเจน แต่เป้าหมายในที่นี้คือ XSS-safe
      คือการลบองค์ประกอบหรือแอตทริบิวต์ที่สามารถรันสคริปต์ได้ และตรรกะนี้ทำงานอยู่ภายในเอนจินของเบราว์เซอร์ จึงจัดการได้แม่นยำกว่าพวก sanitizer แบบอิงสตริง
      ดูรายละเอียดได้ใน เอกสาร MDN ของ setHTML
    • จริง ๆ แล้วมีการแยกไว้อย่างชัดเจนอยู่แล้ว
      elementNode.textContent ปลอดภัยแม้ใช้กับอินพุตที่ไม่น่าเชื่อถือ แต่ elementNode.innerHTML ไม่ใช่
      ตัวแรกจะ escape ทุกอักขระ ส่วนตัวหลังไม่ escape อะไรเลย
      ยังมีความเห็นด้วยว่า “HTML sanitization” เป็นปัญหาที่แก้ให้สมบูรณ์ไม่ได้โดยพื้นฐาน
      ดูการถกเถียงที่เกี่ยวข้องได้ใน คอมเมนต์นี้
      API แบบนี้ไม่ควรผ่านตั้งแต่ขั้นตอนเสนอด้วยซ้ำ
    • ไม่ควรออกแบบให้ใช้ innerHTML ปนกับ setHTML แต่ควรถอด innerHTML ออกไปเลย และถ้าต้องการพฤติกรรมแบบเดิมก็ค่อยใช้ setHTMLUnsafe
    • ถ้านักพัฒนาเว็บสามารถปิดใช้งาน API รุ่นเก่า อย่าง innerHTML ได้ด้วยการตั้งค่าระดับ global ก็น่าจะดี
      แต่ถ้าทำแบบนั้น เว็บไซต์อาจใช้งานไม่ได้บนเบราว์เซอร์รุ่นเก่า
    • ถ้าส่งหน้าเพจมาพร้อมเฮดเดอร์ Content-Security-Policy: require-trusted-types-for 'script' ก็จะบล็อกการส่งสตริงธรรมดาเข้าเมธอดที่ไม่มี sanitizer ได้
  • ถ้าตามตัวอย่าง ผู้ใช้สามารถแทรกแท็กอย่าง <h1> หรือ <br> เข้าไปในชื่อผู้ใช้ได้ ต่อให้บล็อกการรันสคริปต์ไว้ ก็ยังคงเกิด การฉีดมาร์กอัปตามอำเภอใจ ได้อยู่ดี
    ยังอาจใช้แท็ก <style> ไปเปลี่ยน CSS ได้ด้วย เช่น เปลี่ยนหน้าตาของหน้าโปรไฟล์ PayPal
    ก็เลยอดสงสัยไม่ได้ว่ามีใครต้องการแบบนี้จริงหรือ

    • ถึงอย่างนั้น มันก็อาจมีประโยชน์ในกรณีอย่างฟอรัมที่อยากให้ผู้ใช้เขียน Markdown ได้
      สามารถเพิ่มชั้นป้องกันด้วยการนำ HTML ที่สร้างจาก Markdown ไปจำกัดอีกครั้งด้วย sanitizer เพื่ออนุญาตเฉพาะบางแท็ก
    • ถ้าเป็นกรณีแบบนั้น ก็ควรใช้ innerText หรือ textContent แทน innerHTML
      setHTML มีไว้ใช้แทน innerHTML
    • ถ้าการตั้งค่าเริ่มต้นของ setHTML() เข้มงวดเกินไปหรือหลวมเกินไป นักพัฒนาก็สามารถให้ การตั้งค่าแบบกำหนดเอง เพื่อระบุองค์ประกอบ HTML และแอตทริบิวต์ที่อนุญาตได้โดยตรง
    • แค่ CSS อย่างเดียวก็สร้างความเสี่ยงด้านความปลอดภัยได้ ดังนั้นก็ยังต้องระวังอยู่ดี
      ดูการถกเถียงที่เกี่ยวข้องได้ในเธรดนี้
    • ตัวอย่างเช่น
      .setHTML("<h1>Hello</h1>", new Sanitizer({}))
      
      แบบนี้จะลบทุกองค์ประกอบออกหมด
      สุดท้ายแล้วฝั่งแบ็กเอนด์ก็ยังคงต้อง sanitize ชื่อผู้ใช้ด้วยวิธีมาตรฐาน และตอนแสดงผลก็ต้องทำ HTML escape
      ตาม RFC 2119 นี่เป็นข้อกำหนดระดับ “SHOULD”
  • ยินดีที่เห็นฟีเจอร์นี้ออกมา แต่กว่าที่ การรองรับของเบราว์เซอร์ จะครอบคลุมเพียงพอคงต้องใช้เวลา
    ตรวจสอบสถานะการรองรับได้ที่ Can I use

    • เหมือน API อื่นของเบราว์เซอร์ อาจใช้เวลาหลายปี หรือถ้าตั้งเป้าเฉพาะเวอร์ชันล่าสุดก็อาจใช้เวลาไม่กี่เดือน
      ระหว่างนั้นก็ใช้ polyfill แทนได้
  • พาดหัวค่อนข้างชวนให้เข้าใจเกินจริงนิดหน่อย
    จริง ๆ แล้วก็น่าจะทำ sanitization ได้ด้วยฟังก์ชันตรวจสอบอินพุตก่อนส่งให้ innerHTML ไม่ใช่หรือ
    เพียงแต่ความพยายามแบบนี้สุดท้ายก็ดูเหมือน การประดิษฐ์ล้อใหม่
    อีกทั้งบน Firefox รุ่นเก่า hacks.mozilla.org ยังเปิดไม่ได้เลย และบน Pale Moon หรือ SeaMonkey นั้น MDN ก็แสดงผลเพี้ยน
    เหมือนกับว่า “คาร์เทลเบราว์เซอร์” กำลังทำลายเว็บ

    • คำพูดที่ว่า “แก้ได้ด้วยฟังก์ชันตรวจสอบอินพุต” ก็ไม่ต่างจากการบอกว่า “ภาษา C ก็ปลอดภัยด้านหน่วยความจำได้ถ้าไม่มีบั๊ก”
      และยังเป็นข้ออ้างที่ไม่ได้คำนึงถึงปัญหา parser differential ด้วย
  • ถ้าใช้ Sanitizer API ผิดวิธี มันอาจกลายเป็น footgun ได้
    โดยเฉพาะเวลาที่ใช้โหมด “remove” ต้องระวังให้มาก
    ส่วนตัวคิดว่าควรใช้แค่ setText ไปเลย และไม่เปิดให้ผู้ใช้ใส่ HTML ได้เลยจะดีกว่า

    • ถ้าใช้ Sanitizer แบบ allowlist ความเสี่ยงก็จะลดลง แต่ตราบใดที่ใช้ setHTML ก็จะไม่เกิด XSS
    • แต่ถ้าผู้เขียนหน้าเพจจำเป็นต้องเพิ่ม HTML ก้อนใหญ่ ๆ จะทำอย่างไร
      เมื่อดูจากความเป็นจริงที่ innerHTML ถูกใช้บ่อย ก็ยากจะตัดมันออกไปทั้งหมด
    • ตรงกันข้าม API แบบนี้อาจทำให้คนเข้าใจผิดว่า “ปลอดภัย 100%” และยิ่งอันตรายกว่าเดิมก็ได้
  • น่าประทับใจที่ตอนนี้ทุกแง่มุมของการเข้าถึงเครือข่ายถูกควบคุมอย่างเหมาะสมแล้ว ทำให้ ห่วงโซ่ความปลอดภัย ย้ายจากการเชื่อถือโค้ดไปสู่การเชื่อถือการตั้งค่าโฮสต์
    และค่าเริ่มต้นก็ถูกตั้งมาให้ปลอดภัยด้วย

  • สิ่งที่ผมอยากได้จริง ๆ คือ <sandbox> element ที่สามารถ รันโค้ดอันตรายได้อย่างปลอดภัย
    ไม่ใช่การไปแก้ไขโค้ดอันตราย แต่เป็นการเปิดให้มันทำงานในสภาพแวดล้อมที่แยกขาด
    iframe มีข้อจำกัดตรงที่มันไม่สามารถไหลไปพร้อมกับ DOM ได้ และในยุคที่ AI กับคอนเทนต์แบบไดนามิกเพิ่มมากขึ้น เราต้องการ การห่อหุ้มที่ประกอบได้

  • ผมชอบชื่อ setHTMLUnsafe มาก
    ฟีเจอร์ด้านความปลอดภัยมักล้มเหลวถ้าต้องให้ผู้พัฒนา opt-in เอง
    ทางที่ได้ผลกว่าคือทำให้ “เส้นทางที่อันตรายดูอันตรายสมชื่อ”

  • ชื่อ set_html() เข้าใจได้ตรงไปตรงมา กว่า inner_html มาก
    API ของ JavaScript ช่างสะเปะสะปะจริง ๆ และสักวันคงต้องมีการจัดระเบียบใหม่
    การถกเถียงครั้งนี้จะเน้นเรื่องความปลอดภัยก็จริง แต่เวลาเปิดตัว API ใหม่ ตัวการออกแบบเองก็ควรเรียบร้อยด้วย

    • พูดให้แม่นยำ นี่คือ DOM API
      DOM API ให้ความรู้สึกมาตั้งแต่อดีตจนถึงทุกวันนี้ว่า “เหมือนคนที่ไม่เคยออกแบบ API มาก่อนเป็นคนสร้าง”
  • นักพัฒนายุค 90s:

    SQL("select * from user where name = " + name);
    

    นักพัฒนายุค 2020s:

    div.innerHTML = "Hello " + user.name;
    
    • นักพัฒนายุค 2030s:
      "Summarize this email: " + email.contents
      
      Prompt injection ก็เป็นแค่ปัญหาเดิมบนเทคโนโลยีใหม่เท่านั้น
      พวกเราไม่ได้เรียนรู้อะไรจากยุค 90s เลย