🐛 Fix plugin sandbox freezing CLJS Proxy constructor breaking Transit encoding

When the plugin sandbox calls harden() (SES lockdown) on any proxy object
returned from the penpot.* API, SES traverses the prototype chain up to
Proxy.prototype and freezes the CLJS Proxy constructor function. Transit's
typeTag helper later fails with "object is not extensible" when trying to
set its cache property on that frozen constructor.

Fix by deleting the constructor data property from Proxy.prototype so that
harden never traverses to the CLJS Proxy constructor function.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
Andrey Antukh
2026-03-10 11:20:45 +00:00
committed by Alonso Torres
parent acc383ba31
commit 27a934dcfd

View File

@@ -466,10 +466,17 @@
#?(:cljs
(def Proxy
(app.util.object/class
:name "Proxy"
:extends js/Object
:constructor (constantly nil))))
(let [ctor (app.util.object/class
:name "Proxy"
:extends js/Object
:constructor (constantly nil))]
;; Remove the `constructor` data property from the prototype so that
;; SES `harden` (used by the plugin sandbox) does not traverse from a
;; proxy instance back to this constructor function and freeze it.
;; If the constructor is frozen before Transit's `typeTag` helper sets
;; its cache property, Transit throws "object is not extensible".
(js-delete (.-prototype ctor) "constructor")
ctor)))
(defmacro reify
"A domain specific variation of reify that creates anonymous objects