Scriptactulous + AIR + eval = Adobe AIR runtime security violation for JavaScript code in the application security sandbox (eval)
Reported by King Maxemilian | June 9th, 2008 @ 03:08 PM
AIR does not authorize the eval function for security reason (code injection)
I noticed a problem on effect library class "Effect.Base" where there is an eval
performed (visibly, only for lazy code reason) as a result that the library does not
work in an AIR application. I rewrite the code and it's working fine now in the AIR app.
/*
eval('this.render = function(pos){ '+
'if (this.state=="idle"){this.state="running";'+
codeForEvent(this.options,'beforeSetup')+
(this.setup ? 'this.setup();':'')+
codeForEvent(this.options,'afterSetup')+
'};if (this.state=="running"){'+
'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
'this.position=pos;'+
codeForEvent(this.options,'beforeUpdate')+
(this.update ? 'this.update(pos);':'')+
codeForEvent(this.options,'afterUpdate')+
'}}');*/
this.render = function(pos){
if (this.state=="idle"){
this.state="running";
if(this.options["beforeSetupInternal"]) {
this.options.beforeSetupInternal(this);
}
if(this.options["beforeSetup"]) {
this.options.beforeSetup(this);
}
if(this.setup) {
this.setup();
}
if(this.options["afterSetupInternal"]) {
this.options.afterSetupInternal(this);
}
if(this.options["afterSetup"]) {
this.options.afterSetup(this);
}
}
if (this.state=="running"){
pos=this.options.transition(pos)*this.fromToDelta+this.options.from;
this.position=pos;
if(this.options["beforeUpdateInternal"]) {
this.options.beforeUpdateInternal(this);
}
if(this.options["beforeUpdate"]) {
this.options.beforeUpdate(this);
}
if(this.update) {
this.update(pos);
}
if(this.options["afterUpdateInternal"]) {
this.options.beforeUpdateInternal(this);
}
if(this.options["afterUpdate"]) {
this.options.beforeUpdate(this);
}
}
}
I notice as well an eval of JS in controls.js, but I can't find no solution except find
another way to execute the js (btw - this could be a security issue performing js of an httprequest response)
Comments and changes to this ticket
-
John-David Dalton July 24th, 2008 @ 11:50 PM
- → Tag changed from to air eval
I see a couple of errors in your rewrite of this:
if(this.options["afterUpdateInternal"]) { this.options.beforeUpdateInternal(this); } if(this.options["afterUpdate"]) { this.options.beforeUpdate(this); }should be:
if(this.options["afterUpdateInternal"]) { this.options.afterUpdateInternal(this); } if(this.options["afterUpdate"]) { this.options.afterUpdate(this); } -
John-David Dalton July 25th, 2008 @ 12:11 AM
An alternative to the code above is:
this.render = (function() { function dispatch(effect, eventName) { if (effect.options[eventName + 'Internal']) effect.options[eventName + 'Internal'](effect); if (effect.options[eventName]) effect.options[eventName](effect); } return function(pos) { if (this.state === "idle") { this.state = "running"; dispatch(this, 'beforeSetup'); if (this.setup) this.setup(); dispatch(this, 'afterSetup'); } if (this.state === "running") { pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from; this.position = pos; dispatch(this, 'beforeUpdate'); if (this.update) this.update(pos); dispatch(this, 'afterUpdate'); } } })();or
this.render = (function() { function dispatch(effect, eventName) { if (effect.options[eventName + 'Internal']) effect.options[eventName + 'Internal'](effect); if (effect.options[eventName]) effect.options[eventName](effect); } function run(effect, method) { var args = $A(arguments).slice(2), n = method.capitalize(); dispatch(effect, 'before' + n); if (effect[method]) effect[method].apply(effect, args); dispatch(effect, 'after' + n); } return function(pos) { if (this.state === "idle") { this.state = "running"; run(this, 'setup'); } if (this.state === "running") { pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from; run(this, 'update', this.position = pos); } } })();I am avoiding "bind" (but it could be used here)
-
Thomas Fuchs July 24th, 2008 @ 11:57 PM
i'll add this to the next bugfix version.
I can't really understand WHY Adobe broke JavaScript in the first place (they even asked before they released AIR, and we told them they shouldn't mess with the language). Oh my.
Note that Prototype also has eval() calls in some places.
-
John-David Dalton July 25th, 2008 @ 12:22 AM
Correct about the usage in Prototype. But Prototype will work if you avoid the obvious methods: String#evalScripts String#evalJSON Ajax#Request (avoid JavaScript/JSON in the responseText, or use options evalJS:false, evalJSON:false) The eval used in Selector.compileMatcher() is never called because the internal engine in AIR is WebKit which calls Selector.compileXPathMatcher() instead. So it lucks out and is compatible.Interestingly though AIR does allow:
function exec(code){ new Function('', code)(); } //usage exec('alert("Hello World")'); //alerts "Hello World" -
Thomas Fuchs July 25th, 2008 @ 12:17 AM
- → State changed from new to resolved
(from [efb38b665f9e5c48a5179f249f926e96c18ddee7]) Change Effect.Base#render not to use eval(), so certain JavaScript runtime environments (like Adobe AIR) that do not support eval() work. [King Maxemilian, John-David Dalton] [#20 state:resolved]
-
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
script.aculo.us is an open-source JavaScript framework for visual effects and interface behaviours.
Source available from github
The Git repository resides at:
http://github.com/madrobby/scriptaculous
Check out the current development trunk with:
git clone git://github.com/madrobby/scriptaculous.git
As script.aculo.us 1.xx is feature-frozen, this development trunk is for bugfixes only.
New development should happen only for
script.aculo.us 2.
Creating a bug report
When creating a bug report, be sure to include as much relevant information as possible. Post a an example that shows off the problem. Preferably, alter the unit tests and show through either changed or added tests how the expected behavior is not occuring.
