Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Webプラットフォームで議論されているセキュリティ課題 / Security issues b...

Webプラットフォームで議論されているセキュリティ課題 / Security issues being discussed on Web Platforms

Frontend Conference Fukuoka 2026
https://frontend-conf.fukuoka.jp/2026/

Avatar for petamoriken / 森建

petamoriken / 森建

September 12, 2026

More Decks by petamoriken / 森建

Other Decks in Programming

Transcript

  1. Can you find the issue? (CVE-2024-45389) // Get the <script>

    element for this file (classic script) const script = document.currentScript; // Get the src of <script> and retrieve the JS base path const baseUrl = new URL(script.src).pathname; // Load and execute the related JS file import(`${baseUrl}related.js`) .then((moduleNS) => {/* */}); 2
  2. Can you find the issue? (CVE-2024-45389) // Get the <script>

    element for this file (classic script) const script = document.currentScript; // Check if script is actually a <script> element if (script.tagName.toUpperCase() !== "SCRIPT") { throw new Error("DOM clobbering!"); } // Get the src of <script> and retrieve the JS base path const baseUrl = new URL(script.src).pathname; // Load and execute the related JS file import(`${baseUrl}related.js`) 3 .then((moduleNS) => {/* */});
  3. DOM Clobbering <!DOCTYPE html> <html> <head> <title>FEC Fukuoka 2026</title> </head>

    <body> <script> console.log(document.title); // "FEC Fukuoka 2026" </script> </body> 5 </html>
  4. DOM Clobbering <!DOCTYPE html> <html> <head> <title>FEC Fukuoka 2026</title> </head>

    <body> <img name="title"> <script> console.log(document.title); // HTMLImageElement </script> </body> 6 </html>
  5. To Resolve CVE-2024-45389 // Get the <script> element for this

    file (classic script) const script = document.currentScript; // Check if script is actually a <script> element if (script.tagName.toUpperCase() !== "SCRIPT") { throw new Error("DOM clobbering!"); } // Get the src of <script> and retrieve the JS base path const baseUrl = new URL(script.src).pathname; // Load and execute the related JS file import(`${baseUrl}related.js`) 8 .then((moduleNS) => {/* */});
  6. Table of Contents • DOM Clobbering • (Self-Introduction) • Prototype

    Pollution • Thenable (Promises/A+) • TC39 Task Group 3: Security 11
  7. Self-Introduction petamoriken pixiv WebDev engineer in Fukuoka 12 • A

    Deno contributor • An advocate for ES2025 Float16Array • I like to keep up with Web Standard
  8. Normative: Don't call well-known Symbol methods for RegExp on primitive

    values "a b c".split(" "); // ["a", "b", "c"] String.prototype[Symbol.split] = () => "hi!"; "a b c".split(" "); // "hi!" 13
  9. What is the Prototype Chain? All objects have a [[Prototype]]

    internal slot, which is traversed when accessing properties [1, 2, 3].includes(2); [1, 2, 3] Array.prototype “includes” method 16 Object.prototype null
  10. Prototype Pollution Convenient for polyfills, but allows arbitrary properties... const

    obj = { foo: 1 }; Object.prototype.bar = 2; console.log(obj.foo); // 1 console.log(obj.bar); // 2 17
  11. Prototype Pollution Attack 💥 e.g. Overwriting Object.prototype via {}.constructor.prototype const

    payload = { constructor: { prototype: { isAdmin: true, }, }, }; unsafeMerge(obj, payload); 19 Object.prototype.isAdmin; // true
  12. Prototype Pollution Attack 💥 CVE assigned due to the unsafe

    merge code 20 • CVE-2019-10744 • CVE-2024-57077 • CVE-2020-28282 • CVE-2025-57353 • CVE-2022-25904 • CVE-2026-29063 • CVE-2023-26136 etc.
  13. Just an idea: Freeze prototypes right after the polyfill if

    (Array.prototype.uniqueBy === undefined) { Object.defineProperty(Array.prototype, "uniqueBy", { value: function uniqueBy() {/* */}, writable: false, enumerable: false, configurable: true, }); } // Freeze prototypes Object.freeze(Object.prototype); Object.freeze(Array.prototype); 21 // ...
  14. Spec bug: (Assignment) Override Mistake • Assigning a value with

    the same name as a writable: false property in the prototype chain throws a TypeError ※ Object.freeze makes all properties writable: false 22
  15. Spec bug: (Assignment) Override Mistake const proto = Object.create(Object.prototype, {

    "foo": { value: 1, writable: false, }, }); const obj = Object.create(proto); obj.foo = 2; // Throws TypeError: Cannot assign to read only property obj 23 proto Object.prototype “foo” (writable: false) null
  16. Spec bug: (Assignment) Override Mistake Object.freeze(Object.prototype); const obj = {};

    obj.toString = () => {}; // Throws TypeError obj Object.prototype “toString” (writable: false) 24 null
  17. Spec bug: (Assignment) Override Mistake • Fixing this spec bug

    is a breaking change and cannot be resolved ◦ Actually breaks lodash 25
  18. The Iterator.prototype.constructor Issue // Freeze %IteratorPrototype% (Iterator.prototype) const ArrayIteratorPrototype =

    Object.getPrototypeOf([].values()); const IteratorPrototype = Object.getPrototypeOf(ArrayIteratorPrototype); Object.freeze(IteratorPrototype); // make "constructor" writable: false // Use old regenerator-runtime (babel-polyfill) const RegeneratorFunctionPrototype = Object.create(IteratorPrototype); RegeneratorFunctionPrototype.constructor = RegeneratorFunction; // TypeError RegeneratorFunction Prototype 27 Iterator.prototype Object.prototype “constructor” (writable: false) null
  19. Summary So Far: Prototype Pollution • All objects have a

    [[Prototype]] internal slot • Object.freeze for prototype pollution fixes is risky due to Assignment Override Mistake ◦ Fixing the Assignment Override Mistake itself is a breaking change and cannot be resolved 29
  20. Stage 1 Stabilize, and other integrity traits • Problem with

    Object.freeze (writable: false) • New overridable trait ◦ Prevents Assignment Override Mistake • frozen + apply integrity traits = stabilize ◦ (Other traits exist but are omitted here) 30
  21. Stage 1 Stabilize, and other integrity traits • fixed trait

    ◦ Prevents Return Override Mistake • non-trapping trait ◦ Prevents Proxy trapping 32
  22. Stabilize prototypes right after the polyfill (solved?) if (Array.prototype.uniqueBy ===

    undefined) { Object.defineProperty(Array.prototype, "uniqueBy", { value: function uniqueBy() {/* */}, writable: false, enumerable: false, configurable: true, }); } // Stabilize prototypes Object.stabilize(Object.prototype); Object.stabilize(Array.prototype); 33 // ...
  23. 😓 // Stabilize prototypes Object.stabilize(Object.prototype); Object.stabilize(Array.prototype); Object.stabilize(Function.prototype); Object.stabilize(Date.prototype); Object.stabilize(RegExp.prototype); Object.stabilize(Error.prototype);

    Object.stabilize(String.prototype); Object.stabilize(Number.prototype); Object.stabilize(Promise.prototype); Object.stabilize(Map.prototype); Object.stabilize(Set.prototype); 34 // ...
  24. Stage 1 Secure ECMAScript if (Array.prototype.uniqueBy === undefined) { Object.defineProperty(Array.prototype,

    "uniqueBy", { value: function uniqueBy() {/* */}, writable: false, enumerable: false, configurable: true, }); } // Stabilize prototypes lockdown(); 35
  25. npm:ses import "npm:ses"; if (Array.prototype.uniqueBy === undefined) { Object.defineProperty(Array.prototype, "uniqueBy",

    { value: function uniqueBy() {/* */}, writable: false, enumerable: false, configurable: true, }); } // Stabilize prototypes 36 lockdown();
  26. Summary: Prototype Pollution • Prototype pollution is being exploited in

    attacks • Workaround strategies for the Assignment Override Mistake spec bug are required before resolving this in the spec 38
  27. Thenable (Promises/A+) • In the ES5.1 era, libraries defined their

    own asynchronous interfaces • To resolve inconsistencies, the community created a spec treating the "then" method specially • https://promisesaplus.com/ 40
  28. Thenable (Promises/A+) • For interoperability, ECMAScript also gives special treatment

    to the "then" method const thenable = { then(resolve, reject) { resolve(42); }, }; await thenable; // 42 42
  29. Thenable (Promises/A+) Thenable Can Break Dynamic Imports 😢 export function

    then(resolve, reject) { resolve(42); } // Unable to access... export function foo() {} 43
  30. Thenable (Promises/A+) • Modern JS engines use JIT compilers for

    optimization • Handling side effects when accessing the "then" property adds complexity, which could lead to memory layout bugs and vulnerabilities ◦ CVE-2024-43357 44
  31. Side effects when accessing the “then” const thenable = {

    get then() { // Do something bad that corrupts the memory layout return (resolve, reject) => {/* */}; } }; 45
  32. Stage 2 Curtailing the power of "Thenables" • CVE-2024-43357 was

    a vulnerability occurring at the boundary between DOM and JS • Likely suppress getters or Proxy-based thenables, specifically for WebIDL • Keep Promise.resolve/await unchanged for compatibility (expose as Promise.safeResolve?) 47
  33. Summary: Thenable (Promises/A+) • ECMAScript also supports community-driven specs regarding

    the "then" method • Rejecting thenables that could cause side effects using getters or Proxies, limited to WebIDL, will mitigate vulnerabilities 49
  34. Key Industries in TC39 52 • Browser Vendors (Google, Apple,

    Microsoft, Mozilla) • Cloud & Edge Runtimes / WinterTC (Node.js, Deno, Cloudflare, Amazon) • IoT & Embedded Systems / TC53 (Moddable) • Big Tech & Social Platforms (Meta, ByteDance) • Enterprise & FinTech Platform (Salesforce, Bloomberg, IBM) • E-Commerce & Digital Commerce (Shopify, Alibaba, PayPal) • Gaming & Entertainment (Sony SIE) • CPU & Hardware Vendors (Intel, ARM, Qualcomm, Huawei) • Web Ecosystem Security (Socket, F5 Networks) • Web3 & Crypto (Agoric, Consensys / MetaMask) etc...
  35. TC39 Task Group 3: Security • Specialized task group for

    Security & Privacy • Evaluating security for new proposals and managing vulnerability disclosures 53
  36. TC39 Task Group 3: Security “To ensure the ECMAScript security

    model is effective for the constantly evolving threat landscape of today and tomorrow.” 54
  37. TC39 Task Group 3: Security • Integrity and Tamperproofing ◦

    Stage 1 Stabilize, and other integrity traits ◦ Stage 1 Secure ECMAScript ◦ Stage 2 Curtailing the power of "Thenables" • Sandboxing ◦ Stage 1 Realm Globals ◦ Stage 1 Compartments ◦ Stage 2.7 ShadowRealms 55
  38. TG3 Hot Topic: EU Cyber Resilience Act • Covers software

    linked to networks and sold commercially in the EU ◦ Might also include PWA / Native Web Apps • Major incidents must be reported to ENISA SRP starting yesterday (2026/9/11) 56
  39. Summary • Addressing security issues on the Web Platform without

    causing breaking changes • ECMA TG3: Security works to protect security and privacy in JavaScript 58
  40. Do you have any questions? • DOM Clobbering • (Self-Introduction)

    • Prototype Pollution • Thenable (Promises/A+) • TC39 Task Group 3: Security 59