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

ユーザーが作成したコードをブラウザ上で安全に実行できる Plugin システムへのアプローチ

Avatar for Saji Saji
January 08, 2026
34

ユーザーが作成したコードをブラウザ上で安全に実行できる Plugin システムへのアプローチ

Avatar for Saji

Saji

January 08, 2026
Tweet

Transcript

  1. ͜ͷτʔΫͰͷʮ1MVHJOγεςϜʯ ༷ʑͳʮ1MVHJOγεςϜʯ͕ଘࡏ͢Δ͕ɺ͜ͷτʔΫͰ͸ҎԼΛର৅ͱ͢Δ w ϒϥ΢β্Ͱಈ͘΋ͷ 㱠αʔόʔαΠυ  w ඞવతʹ΄΅+4Ͱॻ͔ΕΔ 8BTNͳΒʁΈ͍ͨͳ࿩͸ޙड़ 

    w SE1BSUZ Ϣʔβʔɾύʔτφʔاۀ༷ ʹΑΔ΋ͷ͕΄ͱΜͲ w ۀ຿ɾχʔζʹ߹Θ֦ͤͨுɾޮ཰Խखஈͱͯ͠ར༻͞ΕΔ ͳͷͰ͜ͷൃදͷλΠτϧ͸ʮϢʔβʔ͕࡞੒ͨ͠ίʔυΛϒϥ΢β্Ͱ҆શ ʹ࣮ߦͰ͖Δ1MVHJOγεςϜ΁ͷΞϓϩʔνʯ
  2. +4&OHJOFPO8BTNͰִ཭͢Δ ϝϦοτ👍 w ϝϞϦϨϕϧͰִ཭͞Εͨ+4ͷ࣮ߦ؀ڥ͕ಘΒΕΔ 8BTNͷڧΈ  w ͏·͘ڮ౉͠Λ͢Ε͹ಉظతͳ"1*Λ࡞Δ͜ͱ΋Մೳ σϝϦοτ👎 w

    ΞϓϦέʔγϣϯຊମͱͷڮ౉͠Λࣗ෼ͨͪͰ࣮૷͢Δඞཁ͕͋Δ w ར༻Ͱ͖Δ+4ͷػೳ͸+4&OHJOF࣍ୈ+4ͷݴޠػೳ͔͠࢖͑ͳ͍ w 6*͸ͳ͍ͷͰ%0.͸ૢ࡞Ͱ͖ͳ͍ॳظϩʔυͷ໘Ͱෆར
  3. 3FBMNT4IJNͰִ཭͢Δલఏ ͦ΋ͦ΋3FBMNT &$."4DSJQU3FBMNT ͱ͸ w &$."4DSJQU +4ͷ࢓༷ Ͱఆٛ͞Ε͍ͯΔ֓೦ͷͭ w +4͕ධՁ͞ΕΔάϩʔόϧม਺΍ϏϧυΠϯΫϥεɺ࣮ߦ͞ΕΔίʔυ΍ঢ়

    ଶɾϦιʔεͳͲΛ͢΂ͯ·ͱΊ΋ͷ w ΑΓৄ͘͠͸.%/ͷʮ+BWB4DSJQUFYFDVUJPONPEFMʯͱ͍͏هࣄ͕ྑ͍ 3FBMN4IJNT3FBMNTͱݺ͹ΕΔ࢓૊Έ ֓೦ Λ࣮ݱ͢ΔTIJN w 㲈Ծ૝తʹ3FBMNΛ৽͘͠࡞ΕͯΔΑ͏ʹ͢Δٕज़
  4. બ͹Εͨͷ͸ʮJGSBNFʯͰͨ͠ େ͖͔ͬͨϝϦοτ w 6*Λ͍࣋ͬͯͯ%0.ૢ࡞ΛؚΊͨ΄΅׬ᘳͳ+4࣮ߦ؀ڥͰ͋Δ͜ͱ w ͪΌΜͱઃఆ ޙड़ ͢Ε͹࣮ߦΛ҆શʹִ཭͢Δ͜ͱ͕Մೳ w 8FCͷඪ४ػೳʹ৐ΕΔͷͰϓϥάΠϯػߏ͕ෳࡶԽ͠ʹ͍͘

    ͋Δఔ౓ڐ༰Ͱ͖Δͱ൑அͨ͠σϝϦοτ w ύϑΥʔϚϯεˠ4&0΍ϢʔβମݧΛؾʹ͢Δ΋ͷΑΓ͸एׯ༏ઌ౓͕௿͍ w "1*͕ඇಉظͳΔˠࠓޙ௥Ճ͍ͯ͘͠"1*Ͱॱ࣍ඇಉظͷ΋ͷ͚ͩʹ
  5. JGSBNF ↔︎ ΞϓϦέʔγϣϯຊମͷ௨৴ ΞϓϦέʔγϣϯຊମͱͷ௨৴͸$IBOOFM.FTTBHJOH"1*Λར༻͢Δ $IBOOFM.FTTBHJOH"1*ͱ͸ w ҟͳΔίϯςΩετؒͰ௨৴Λߦ͏ͨΊͷඪ४ػೳ w *GSBNF ↔︎

    ຒΊࠐΈݩϖʔδͭͷJ'SBNFಉ࢜จॻͱ4IBSFE8PSLFS ΞϓϦέʔγϣϯຊମͱ$PSTT0SJHJOJGSBNFͱͰ௨৴͢Δ།Ұͷํ๏ w ٯʹݴ͑͹$IBOOFM.FTTBHJOH"1*ʹݶఆͰ͖Δ
  6. $IBOOFM.FTTBHJOH"1*Ͱͷૄ௨ ຊମˠQMVHJOJGSBNFʹ66*%Λૹ৴͢Δ const uuid = generateUUID(); const channel = new

    MessageChannel(); function onLoad() { // send UUID iframe.contentWindow.postMessage(uuid, "*", [channel.port2]); }
  7. $IBOOFM.FTTBHJOH"1*Ͱͷૄ௨ JGSBNF͸ड͚औͬͨΒૹΓओͷPSJHJOΛνΣοΫͦ͠ͷ··ฦ৴ const handler = (e) => { if (!checkMessageOrigin(e.origin))

    { reject(new Error("Invalid origin")); } messagePort.postMessage(e.data); window.removeEventListener("message", handler); // ... }; window.addEventListener("message", handler);
  8. $IBOOFM.FTTBHJOH"1*Ͱͷૄ௨ ຊମ͸1MVHJOJGSBNF͔Βͷฦ৴Λ֬ೝ 66*%͕ಉ͡PSJHJO͕ਖ਼͍͔͠ const handler = (e) => { if

    (e.data === uuid && checkMessageOrigin(e.origin)) { resolve(channel.port1); } else { reject(new Error("Invalid message origin or uuid")); } channel.port1.removeEventListener("message", handler); }; channel.port1.addEventListener("message", handler);
  9. 4IBEPX3FBMNT1SPQPTBM 3FBMNTΛ໌ࣔతʹ࡞੒Ͱ͖Δ4IBEPX3FBMNΫϥεΛ௥Ճ͢Δ w ࡞੒͞Εͨ3FBMN಺Ͱ͸+BWB4DSJQUΛධՁͰ͖Δ const realm = new ShadowRealm(); const

    result = realm.evaluate(` function add(s1, s2) {return s1 + s2;} add("Hello, ", "world!"); `); console.log(result); // Hello, World!