[x3d-public] script security

Andreas Plesch andreasplesch at gmail.com
Sun Oct 18 18:35:17 PDT 2020


For SFRotation, I did not get to the set trap yet. It was an insight
to find that it is best to create a new Proxy for the get trap from
inside the construct trap of the constructor Proxy. It gets very meta.

I could get X3DScripts in protos to start to work:

https://raw.githack.com/andreasplesch/x3dom/76dcda339bc0edbc8b990d76b52cc6bc029f3a8c/test/regression-suite/test/cases/x3dscript/MaterialModulator.html

Proper sequencing was actually not a problem but the initialize
function is now called every time an initial value for the Script node
fields is set (because this initial setting effectively sends set_
events for these fields to the Script). It is called when a Proto is
instanced or when the Script node is instanced and added to the scene,
so perhaps a little bit late. The initialize function cannot fire
events yet. The other issue was dealing with set_ and _changed
modifiers.

Proxies for output events in Scripts were difficult because one cannot
proxy literals like numbers or strings. So I reverted back to checking
for changes in field values, using now JSON.stringify since it works
on all value types. This works better but sometimes a script will want
to send an event even if the value did not change. I cannot really
think of a good solution. Maybe check x_ite how it sends an event for
an output field "out" if the script just sets it to a number: out = 5.
Not sure how it is possible to intercept that. Maybe using with() is
the only option because then the name can refer to a property of an
object.

-Andreas

On Sun, Oct 18, 2020 at 4:32 PM John Carlson <yottzumm at gmail.com> wrote:
>
>
> If the get proxy doesn’t work after the set proxy is defined, it may be worth defining a get proxy in the same Proxy object.
>
> This was a potential solution from my dreams.
>
> John
> On Sun, Oct 18, 2020 at 8:42 AM Andreas Plesch <andreasplesch at gmail.com> wrote:
>>
>> I added SFRotation as a Proxy to a Quaternion target to get the ScriptEvents example working:
>>
>> https://raw.githack.com/andreasplesch/x3dom/7cc55c8a98ffac62cc273d7b1fb0fa92ac7ebacd/test/regression-suite/test/cases/x3dscript/ScriptEvents.html
>>
>> It should be possible to add SFRotation to x3dom.fields in a separate PR independent of X3DScript progress.
>>
>> I think it should be possible to use Proxies for output fields of scripts. The targets would be the actual field objects of the script node, and there would be a set trap which invokes sending the event. Worth a try.
>>
>> Scripts in Prototype do not work yet. I think it is because the custom script node fields are not available yet when the protoinstance is constructed.
>>
>> -Andreas
>>
>> ---on the phone---
>>
>> On Sat, Oct 17, 2020, 1:25 PM Andreas Plesch <andreasplesch at gmail.com> wrote:
>>>
>>> I tried another simple x3d script, a simple bouncer, in x_ite:
>>>
>>> https://gist.githack.com/andreasplesch/8ded7b7ffb598a63c44318f5810b260d/raw/63c673c9bc177c9ad64a3e5a1ad9bd6f7180921a/safe.html
>>> https://gist.github.com/andreasplesch/8ded7b7ffb598a63c44318f5810b260d#file-bouncersafe-x3d
>>>
>>> It required adding initialization of given field values, as variables
>>> in the script. The script node has the fields, with their values, so I
>>> am now passing the script node itself to the function which evaluates
>>> the script. This way the node and its fields become available to the
>>> script. Here is the working example:
>>>
>>> https://raw.githack.com/andreasplesch/x3dom/695821820e34b8a6571b9fec722337735e632468/test/regression-suite/test/cases/x3dscript/Bouncer.html
>>>
>>> In dev tools you can drill down to see X3DScript.js, or look at my
>>> "fields" branch.
>>>
>>> It also turned out that watching for changes in output fields is not
>>> workable and somewhat wrong, so currently just all output fields fire
>>> events each time a script set function (an input event) is called.
>>> Perhaps it is necessary to use a Proxy, or setters which then can fire
>>> events.
>>>
>>> Generally, this would be my approach to scripts, their fields and
>>> routing events. Please feel free to take whatever you find useful.
>>> There would be lots to do, for example, creating a translation between
>>> official SAI functions and x3dom sai like functions. For example
>>> SFVec3f[0] is SFVec3f.x in x3dom. Browser.print is
>>> x3dom.debug.logWarning and so on. The translation could be included in
>>> each script. A more difficult part is to figure out how to deal with
>>> SFNode, MFNode fields.
>>>
>>> With regards to security, it may be worthwhile to just scan the script
>>> for "document" or "window" and refuse to evaluate. But of course this
>>> would not be a real solution. I think adding explicit opt in to allow
>>> execution of scripts somehow may be an option. Perhaps just by
>>> offering a separate version of x3dom, from a less well known location
>>> or even on request.
>>>
>>> Cheers, -Andreas
>>>
>>> On Sat, Oct 17, 2020 at 7:48 AM Andreas Plesch <andreasplesch at gmail.com> wrote:
>>> >
>>> > Hi John,
>>> >
>>> > since I had started to sketch some answers I went ahead and implemented a rough draft of a X3DScript node for x3dom.
>>> >
>>> > Here is the basic spec. example working with the node:
>>> >
>>> > https://raw.githack.com/andreasplesch/x3dom/4cf1ec31736109e67d7b44aa1afb8fc8133f8cb6/test/regression-suite/test/cases/x3dscript/TouchSensorIsOverEventECMAScript.html
>>> >
>>> > Here is the implementation:
>>> >
>>> > https://github.com/andreasplesch/x3dom/blob/fields/src/nodes/Scripting/X3DScript.js
>>> >
>>> > I am using "X3DScript" for now because it is less confusing. It should be possible to switch to Script type='app/x3dscript' at some point.
>>> >
>>> > It turns out that in html documents CDATA sections get converted into comments. This is great since it lets one use any character ( except for -->) in the script. So I am looking for converted comments under the script node for the script source.  I did not look into xhtml but xml should be easier.
>>> >
>>> > Since MDN also recommends Function over eval, I tried to go this way and could figure out an (unsafe) solution using wrappers to maintain the internal context of the script. I think the same approach may be possible for x_ite as well.
>>> >
>>> > I use the nice x_ite approach to get access to the functions in the script, by returning references to the functions.
>>> >
>>> > Unlike x_ite I am trying not to use with() since it is not recommended. Instead I add lots of helpers to the script source in a preamble, I think like you do. For output fields x_ite is also using with() and getters and setters. For now, I am trying to avoid with() and just compare output field values before and after a script set function gets called, from a route. If there is a change, an event is fired.
>>> >
>>> > There is no attempt to deal with XFNode field values. This will be tricky. I did not test anything other than the simple example but other simple examples may start to work as well, perhaps with some adjustments to how SAI is used. Gears will need SFRotation which may be easy to add to the preamble.
>>> >
>>> > Cheers, -Andreasq
>>> > ---on the phone---
>>> >
>>> >
>>> > On Thu, Oct 15, 2020 at 10:31 PM John Carlson <yottzumm at gmail.com> wrote:
>>> > >
>>> > >
>>> > >
>>> > > On Thu, Oct 15, 2020 at 9:25 PM John Carlson <yottzumm at gmail.com> wrote:
>>> > >>
>>> > >> What I am searching for is:
>>> > >>
>>> > >> 1. How to add Script related routes to X3DOM
>>> > >
>>> > >
>>> > > Once I set up Script and fields, this is done automatically with setupTree?
>>> > >
>>> > >>
>>> > >> 2. How to hook in Proto IS statements found in Scripts.
>>> > >
>>> > >
>>> > > Not sure how to do that yet.
>>> > >>
>>> > >> 3. How to modify any Script code to support parsing and the above.
>>> > >
>>> > >
>>> > > adding any functions, declaring variables, etc.
>>> > >>
>>> > >>
>>> > >> On Thu, Oct 15, 2020 at 9:15 PM John Carlson <yottzumm at gmail.com> wrote:
>>> > >>>
>>> > >>> Something like
>>> > >>>
>>> > >>> fromNode.setupRoute(fromField, toNode, toField);
>>> > >>>
>>> > >>> ? That's only for routes?  What about events?
>>> > >>>
>>> > >>> John
>>> > >>>
>>> > >>>
>>> > >>> On Thu, Oct 15, 2020 at 8:42 PM John Carlson <yottzumm at gmail.com> wrote:
>>> > >>>>
>>> > >>>>
>>> > >>>>>> Use the set_xfield functions on field_changed (xfield).
>>> > >>>>>
>>> > >>>>>
>>> > >>>>> Not implemented.  Is this new code?   Where would I put it under Scripting/?   Can you provide a short example?
>>> > >>>>>>
>>> > >>>>>>
>>> > >>>>>> Post messages for all _changed fields as given in the field def.
>>> > >>>>>> Somehow deal with SFNode fields.
>>> > >>>>>>
>>> > >>>>>>
>>> > >>>>
>>> > >>>> There is sample code under Script.js:
>>> > >>>> https://github.com/coderextreme/X3DJSONLD/blob/master/src/main/node/Script.js#L346
>>> > >>>>
>>> > >>>> Below:
>>> > >>>> ====================================================================
>>> > >>>>         doRoute(mypackage, fromNode, fromField, toNode, toField, log, set, changed, selector, url) {
>>> > >>>>                 var fromScript = mypackage.find(fromNode);
>>> > >>>>                 var toScript = mypackage.find(toNode);
>>> > >>>>                 // only add routes with scripts involved
>>> > >>>>                 if (typeof fromScript !== 'undefined' || typeof toScript !== 'undefined') {
>>> > >>>>                         var from =                       this.nodeUtil(selector)+fromNode+"','"+fromField+"')";
>>> > >>>>                         if (typeof fromScript !== 'undefined') {
>>> > >>>>                                 from = 'typeof '+this.useX3DJSON('Obj', selector, url, fromScript.name)+'.'+fromField+changed+' === "function" ? '+this.useX3DJSON('Obj', selector, url, fromScript.name) + '.'+fromField+changed+'() : '+this.useX3DJSON('Obj', selector, url, fromScript.name) + '.'+fromField;
>>> > >>>>                         }
>>> > >>>>                         var to =                        this.nodeUtil(selector)+toNode+"','"+toField+"',";
>>> > >>>>                         if (typeof toScript !== 'undefined') {
>>> > >>>>                                 to = this.useX3DJSON('Obj', selector, url, toScript.name) + '.'+set+toField+'(';
>>> > >>>>                         }
>>> > >>>>                         if (typeof fromScript !== 'undefined' && typeof toScript !== 'undefined') {
>>> > >>>>                                 log.log("               if ("+this.useX3DJSON('Obj', selector, url, toScript.name)+" && "+from+") {");
>>> > >>>>                         }
>>> > >>>>                         log.log("                       "+to+from+", __eventTime);");
>>> > >>>>                         if (typeof fromScript !== 'undefined' && typeof toScript !== 'undefined') {
>>> > >>>>                                 log.log("               }");
>>> > >>>>                         }
>>> > >>>>                 }
>>> > >>>>         }
>>> > >>>>
>>> > >>>>  ====================================================================
>>> > >>>>
>>> >
>>> >
>>>
>>>
>>> --
>>> Andreas Plesch
>>> Waltham, MA 02453



-- 
Andreas Plesch
Waltham, MA 02453



More information about the x3d-public mailing list