module pattern provides no privacy in Firefox

P

Peter Michaux

The module pattern has been discussed many times and has shown how
ECMAScript has the ability to encapsulate data as "private" variables
by using closures.

Today, in a comment on my blog, a reader, haysmark, points out that
Mozilla's JavaScript(TM), the implementation in Firefox, has a second
argument extension to eval that allows external code to spy on
otherwise private variables.

http://peter.michaux.ca/article/4947#comment-8061

Try the examples below in Firefox.

// Getting "private" variables
var obj = (function() {
var a = 21;
return {
// public function must reference 'a'
fn: function() {a;}
};
})();

var foo;
eval('foo=a', obj.fn);
console.log(foo); // 21


// Setting "private" variables
var obj = (function() {
var a = 21;
return {
getA: function(){return a;},
alertA: function(){alert(a);}
};
})();

console.log(obj.getA()); //21
eval('a=3', obj.getA);
console.log(obj.getA()); // 3
obj.alertA(); // 3

I don't think about the second argument to eval very frequently and
have never used it. This "hack" was a surprise to me and is a pretty
neat trick.

(I posted a slightly longer version of this message to my blog
http://peter.michaux.ca/article/8069 to try to see what others who
don't read this group think.)

Peter
 
R

Richard Cornford

The module pattern has been discussed many times and has shown how
ECMAScript has the ability to encapsulate data as "private"
variables by using closures.

Not the module pattern. Encapsulation using closures in javascript
pre-dates the module pattern so the ability had already been shown.
Today, in a comment on my blog, a reader, haysmark, points out that
Mozilla's JavaScript(TM), the implementation in Firefox, has a
second argument extension to eval that allows external code to spy
on otherwise private variables.

http://peter.michaux.ca/article/4947#comment-8061

Try the examples below in Firefox.

// Getting "private" variables
var obj = (function() {
var a = 21;
return {
// public function must reference 'a'
fn: function() {a;}
};

})();

var foo;
eval('foo=a', obj.fn);
console.log(foo); // 21

// Setting "private" variables
var obj = (function() {
var a = 21;
return {
getA: function(){return a;},
alertA: function(){alert(a);}
};

})();

console.log(obj.getA()); //21
eval('a=3', obj.getA);
console.log(obj.getA()); // 3
obj.alertA(); // 3

I don't think about the second argument to eval very frequently
and have never used it.

Speaking of "the second argument" suggests that such an argument would
be common and consistent. We are talking about a non-standard extension,
and so not something that can be expected to be in the environment of
cross-browser code except by coincidence.
This "hack" was a surprise to me and is a pretty
neat trick.
<snip>

It is not really a change in the situation. Because client-side code
is transmitted to the client as source code and interpreted/compiled
on the client from the source code it receives, there never was any
guarantee that anything could be placed out of reach by a javascript
programmer.

Consider content inserting/re-writing proxies for a start. As the
source code passes through such a proxy it can add a privileged
getter and setter for every 'private' variable in the system and
there is nothing the author of the original code could do to
prevent that. (Even ES4, with its formal notions of encapsulation
and 'private' is going to be vulnerable to content inserting
proxies (say swapping all occurrences of a 'private' keyword into
something more permissive)).

Once in the DOM there are many browser which will expose the
source code to javascript, so (other) javascript can manipulate the
strings of source code and then re-compile them back to produce
an environment that precisely as open as wanted.

So it is within the user's power to take total control over the
javascript code that executes in their browser regardless of
where it originates. And there is nothing that the code's
programmer can do to prevent that (or even to find out if/when
the code executed is not the code that was broadcast). That
situation is just the consequence of sending the source code
rather than a pre-complied executable.

An - eval - argument that re-establishes a scope from a previous
execution context doesn't make client-side javascript any less
of a bad place to holding important secretes or any less
something that should be trusted to be doing (or not doing)
any particular thing. It is just one more tool in a world where
the people who want such tools already have a collection including
everything they need.

While the module pattern may have originated from ideas about
having 'private' members of various sorts I don't think that
was ever the primary reason for using it. More the ability
of the module pattern to group related code into discrete
units and keep the internal details of those units out of the
global scope. So while the earliest examples may have internal
variables and functions which are not exposed (and so might
be regarded as private) they are not exposed not because
there is an overwhelming reason for not exposing them but
rather because there is no reason to expose them.

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top