{"record":{"id":"64c0a5a371985038","repo":"siyuan-note/siyuan","slug":"globalthis-object-freeze-is-not-a-function","errorCode":null,"errorMessage":"globalThis.Object.freeze is not a function","messagePattern":"globalThis\\.Object\\.freeze is not a function","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/sandbox.go","lineNumber":132,"sourceCode":"\tlo.Must0(injectServer(p, rt, siyuan))\n\tlo.Must0(injectSecretsVars(p, rt, siyuan))\n\n\tlo.Must0(ObjectFreeze(rt, siyuan))\n\n\tlo.Must0(rt.GlobalObject().Set(\"siyuan\", siyuan))\n\treturn\n}\n\n// ObjectFreeze calls Object.freeze() on the given goja object.\nfunc ObjectFreeze(rt *goja.Runtime, obj *goja.Object) error {\n\tObject := rt.GlobalObject().Get(\"Object\").ToObject(rt)\n\tif Object == nil {\n\t\treturn fmt.Errorf(\"globalThis.Object is not an object\")\n\t}\n\n\tfreeze, ok := goja.AssertFunction(Object.Get(\"freeze\"))\n\tif !ok {\n\t\treturn fmt.Errorf(\"globalThis.Object.freeze is not a function\")\n\t}\n\n\t_, err := freeze(Object, obj)\n\treturn err\n}\n\n// ObjectSeal calls Object.seal() on the given goja object.\nfunc ObjectSeal(rt *goja.Runtime, obj *goja.Object) error {\n\tObject := rt.GlobalObject().Get(\"Object\").ToObject(rt)\n\tif Object == nil {\n\t\treturn fmt.Errorf(\"globalThis.Object is not an object\")\n\t}\n\n\tseal, ok := goja.AssertFunction(Object.Get(\"seal\"))\n\tif !ok {\n\t\treturn fmt.Errorf(\"globalThis.Object.seal is not a function\")\n\t}\n","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/sandbox.go#L114-L150","documentation":"ObjectFreeze resolves globalThis.Object and expects its \"freeze\" property to be a callable JS function. If Object exists but Object.freeze is not a function (e.g. it was overwritten with a non-function value), this error is thrown via goja.AssertFunction. It means the sandbox's Object built-in has been tampered with or stubbed incompletely.","triggerScenarios":"Calling ObjectFreeze on a runtime where globalThis.Object.freeze was reassigned to undefined, null, a plain value, or a non-callable proxy trap result — commonly after plugin code or a polyfill overwrote the built-in.","commonSituations":"A polyfill or shim that redefined Object without freeze; a security-hardened sandbox replacing freeze with a no-op plain function wrapper of wrong type; test code stubbing Object.freeze incorrectly before the runtime injected API objects.","solutions":["Restore or avoid overwriting globalThis.Object.freeze in runtime setup code","Order operations so API objects are frozen before any untrusted plugin code runs","If stubbing in tests, stub with a real function: globalThis.Object.freeze = (o) => o","Wrap ObjectFreeze and fall back to skipping the freeze when the built-in is unusable"],"exampleFix":"// before\n// test setup\nrt.RunString(\"Object.freeze = 1\")\nplugin.ObjectFreeze(rt, obj) // error: not a function\n// after\nrt.RunString(\"const __f = Object.freeze; Object.freeze = (o) => __f(o)\")","handlingStrategy":"type-guard","validationCode":"o := rt.GlobalObject().Get(\"Object\")\nif o != nil {\n    if _, ok := goja.AssertFunction(o.ToObject(rt).Get(\"freeze\")); !ok { /* skip or restore */ }\n}","typeGuard":"func canFreeze(rt *goja.Runtime) bool {\n    o := rt.GlobalObject().Get(\"Object\")\n    if o == nil { return false }\n    _, ok := goja.AssertFunction(o.ToObject(rt).Get(\"freeze\"))\n    return ok\n}","tryCatchPattern":"if err := plugin.ObjectFreeze(rt, obj); err != nil {\n    logging.LogWarningf(\"freeze skipped: %v\", err)\n}","preventionTips":["Do not overwrite Object.freeze with non-function values (including in tests/polyfills)","Freeze before untrusted code executes","Stub with real functions when mocking"],"tags":["goja","javascript","object-freeze","sandbox"],"backgroundTag":"type-mismatch","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}