In the https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage page, it tell us that:
The CacheStorage interface represents the storage for Cache objects. It provides a master directory of all the named caches that a ServiceWorker, other type of worker or window scope can access (you don't have to use it with service workers, even though that is the spec that defines it) and maintains a mapping of string names to corresponding Cache objects.
so, i want to know.Is it better to use cacheStorage in ServiceWorker than in Window scope? why?
As nobody answer that, i want to share what i think.
In my opinion, there are several advantages.
First of all, serviceWorker is handled by another thread, which make it more efficient.
The next one, serviceWorker can simply add to old website without changing code, while you have to rewrite the ajax code etc, when you plan to use it in window scope.
The last but not least, you can run this when your page has been shut down.For example, you can put sth into cache when you got the push.
However, it still make me confused. Why the browser allow the window scope to get the permission.Is it a convenient way for us to just write in the main thread? Or, that will bring us some security risk, because when our page has been xss, that hacker can get access to cache?
Why the browser allow the window scope to get the permission?
Service Workers do not have access to DOM elements.
So if I want to precache some urls that are found on the current page it is much easier to do from the window scope than from the service worker.
Related
I am working on a Java project. In it, we want to enable an end-user to define variables which are calculated based on a set of given variables of primitive types or strings. At some point, all given variables are set to specific values, and then the calculations should be carried out. All resulting calculated variables must then be sent to Java.
I am in the process of evaluating ways for the end-user to define his calculations. The (current) idea is to let him write JavaScript and let that code be interpreted/executed inside the Java program. I know of two ways for this to be done: Either use the javax.scripting API or GraalVM/Truffle. In both, we would do it like this:
The given variables are given into the script. In javax.scripting via ScriptEngine.put, in Graal/Truffle via Value.putMember.
The end-user can define variables in the global context (whose names must not collide with the ones coming from Java). How he sets their values is up to him - he can set them directly (to a constant, to one of the given variables, to the sum of some of them ...) or define objects and functions and set the values by calling those.
When the time comes where the given variables have a fixed value, the script is executed.
All variables that were defined in the global context by the script will be sent to Java. In javax.scripting via ScriptEngine.get, in Graal/Truffle via Value.getMember.
NOTE: We would not grant the script access to any Java classes or methods. In javax.scripting via check if the script contains the string Java.type (and disallow such a script), in Graal/Truffle via using the default Context (which has allowAllAccess=false).
The internet is full of hints and tips regarding JavaScript security issues and how to avoid them. On the one hand, I have the feeling that none of them apply here (explanation below). On the other hand, I don't know JavaScript well - I have never used it for anything else than pure, side-effect-free calculations.
So I am looking for some guidance here: What kind of security issues could be present in this scenario?
Why I cannot see any security issues in this scenario:
This is pure JavaScript. It does not even allow creating Blobs (which are part of WebAPI, not JavaScript) which could be used to e.g. create a file on disk. I understand that JavaScript does not contain any functionality to escape its sandbox (like file access, threads, streams...), it is merely able to manipulate the data that is given into its sandbox. See this part of https://262.ecma-international.org/11.0/#sec-overview:
ECMAScript is an object-oriented programming language for performing
computations and manipulating computational objects within a host
environment. ECMAScript as defined here is not intended to be
computationally self-sufficient; indeed, there are no provisions in
this specification for input of external data or output of computed
results. Instead, it is expected that the computational environment of
an ECMAScript program will provide not only the objects and other
facilities described in this specification but also certain
environment-specific objects, whose description and behaviour are
beyond the scope of this specification except to indicate that they
may provide certain properties that can be accessed and certain
functions that can be called from an ECMAScript program.
The sandbox in our scenario only gets some harmless toys (i.e. given variables of primitive types or strings) put into it, and after the child has played with them (the script has run), the resulting buildings (user-defined variables) are taken out of it to preserve them (used inside Java program).
(1) Code running in a virtual machine might be able to escape. Even for well known JS implementations such as V8 this commonly happens. By running untrusted code on your server, whenever such a vulnerability becomes known, you are vulnerable. You should definitely prepare for that, do a risk assessment, e.g. which other data is accessible on the (virtual) machine the engine runs on (other customers data?, secrets?), and additionally harden your infrastructure against that.
(2) Does it halt? What happens if a customer runs while(true); ? Does that crash your server? One can defend against that by killing the execution after a certain timeout (don't try to validate the code, this will never work reliably).
(3) Are the resources used limited (memory)? With a = ""; while(true) a += "memory"; one can easily allocate a lot of memory, with negative impact on other programs. One should make sure that also the memory usage is limited in such a way that the program is killed before resources are exhausted.
Just some thoughts. You're essentially asking if you can trust your sandbox/vitual machine, for that you should either assume that you're using a good one or the only way to be really sure is to read through all its source code yourself. If you choose a trusted and well known sandbox, I'd guess you can just trust it (javascript shouldn't be able to affect file system stuff outside of it).
On the other hand why aren't you just doing all this calculations client side and then sending the result to your backend, it seems like a lot of setup just to be able to run javascript server side. If the argument for this is "not cheating" or something similar, then you can't avoid that even if your code is sent to the server (you have no idea who's sending you that javascript). In my opinion doing this setup just to run it server side doesn't make sense, just run it client side.
If you do need to use it server side then you need to consider if your java is running with root permissions (in which case it will likely also invoke the sandbox with root permissions). On my setup my nodejs is executing under ~/home so even if a worst case happens and someone manages to delete everything the worst they can do is wipe out the home directory. If you're running javascript server side then I'd strongly suggest at the very least never do so under root. It shouldn't be able to do anything outside that sandbox but at least then even in the worst case it can't wipe out your server.
Something else I'd consider (since I have no idea what your sandbox allows or limits) is whether you can request and make API calls with javascript in that sandbox (or anything similar), because if it's running under root and allows that it would give someone root access to your infrastructure (your infrastructure thinking it's your server making requests when it's actually malicious JS code).
You could also make a mistake or start up your VM with an incorrect argument or missing config option and it suddenly allows a vulnerability without you being aware of it, so you'll have to make sure you're setting it up correctly.
Something else is that if you ever store that JS in some database, instead of just executing it, then you have to make sure that it's not made directly available to any other users without checking it otherwise you'd have XSS happening. For example you build an app for "coding tests" and store the result of their test in a database, then you want to show that result to a potential employer, if you just directly display that result to them you'll execute malicious code in their browser.
But I don't really see a reason why you should care about any of this, just run it client side.
A have a react application using a single page. I call index.html and use ajax(axio) and update the page. I do not use any routing.
I have some global variables and will use in the whole scope of the application. The variables are primitive type integer for example. Some of the variables may be updated during the app lifecycle and some remain constant. But I should be able to reach them from all react components/javascripts. They may contain business related constants or example decimal format mask, keeping them private in each component will not be useful.
There is no need/reason to store it on the disk (localStorage).
Question is: what is the best way (performance etc) storing the global variable foo in the app?
window.foo = 10 or
window.sessionStorage.foo = 10
AFAIK, window.foo is for a single page and sessionStorage allows using within multiple pages within the same origin. What is best in my case when I use a single page? Are there any other drawbacks of window.foo usage? Security is not important, the vales stored are not sensitive. Most critical is the performance.
You probably want to use context rather than either of those. From that documentation:
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.
Definitely don't use global variables. The global namespace is incredibly crowded, and adding to it is generally not best practice. If you did use a global for this, I'd recommend using just one, and having it refer to an object with properties for the various pieces of information you want to share. Note that they'll be window-specific.
One reason to possibly consider using sessionStorage (or perhaps periodically synchronizing your React context to it) is if you want changes in one window to be reflected in another window. Two windows/tabs from the same origin share the same sessionStorage and can get an event (storage) when the other one changes that storage. So if the global information were an app theme (say, light vs. dark), changing it in one tab could also affect the other tab if you respond to the storage event by updating your React context. Note that sessionStorage (and localStorage) only store strings, so the usual thing is to convert to JSON when storing (JSON.stringify) and from JSON when loading (JSON.parse).
say I have the javascript:
/*getAttribute is mootools method for retrieving a named attribute*/
var companyNumber = button.getAttribute('data-company-number');
var payPoint = button.getAttribute('data-pay-point');
window.location = '/Payslip/ListPayslips/?companyNumber=' + companyNumber + '&payPoint=' + payPoint
delete payPoint;//is this necessary?
delete companyNumber;//is this necessary?
Would the delete lines be necessary? And would they even get called?
No its not necessary, after the redirect all variables and instances will be deleted.
To answer the first question, yes. Everything is garbage on unload (unload fired on refresh, redirect or close).
To answer the second question, the deletes will not be hit after the redirect. The JS engine will stop there and fire unload etc.
As for the discussion around memory management and explicit variable deletion, here are some considerations:
Good memory management can become important when developing larger web apps that are left open in browser for long periods of time, especially when the target client browsers can be older or on slower machines or mobile devices.
In these cases, where you declare variables to hold temporary information, particularly large objects, you may choose to delete these to free them up for garbage collection. It is my opinion that you should avoid new declarations if they are not necessary and re-use objects where you can - but perhaps not at the expense of readability ;)
To add to 'Corey Ogburn's point, delete itself does not free memory, but disconnects a variable from it's value. It is this that frees the variable for garbage collection.
Yes, you lose all the variables if the redirect loads in the current frame/document. The best way to handle this is to create a couple of divs and any redirects need to be loaded in the other div. For instance, you could have a header and main div. Your JS can now reside in the page and any redirects should be loaded into the main div. That way you are preserving state.
An alternative is to use the HTML5 local/session storage.
EDIT:
Your second question which is at the bottom regarding delete. No, delete is not necessary. Others have responded with links and reasons why.
It seems there's no way to completely hide source/encrypt something to prevent users from inspecting the logic behind a script.
Aside from viewing the source, then, is it possible to manipulate every variables, objects while a script is running?
It seems it is possible to some degree: by using Chrome's developer tools or Firebug, you can easily edit variables or even invoke functions on the global scope.
Then what about variables, functions inside of an instantiated objects or self invoked anonymous functions? Here is an example:
var varInGlobal = 'On the global scope: easily editable';
function CustomConstructor()
{
this.exposedProperty = 'Once instantiated, can be easily manipulated too.';
this.func1 = function(){return func1InConstructor();}
var var1InConstructor = 'Can be retrived by invoking func1 from an instantiated object';
// Can it be assigned a new value after this is instantiated?
function func1InConstructor()
{
return var1InConstructor;
}
}
var customObject = new CustomConstructor();
After this is ran on a browser:
// CONSOLE WINDOW
varInGlobal = 'A piece of cake!';
customObject.exposedProperty = 'Has new value now!';
customObject.var1InConstructor; // undefined: the variable can't be access this way
customObject.func1(); // This is the correct way
At this stage, is it possible for a user to edit the variable "var1InConstructor" in customObject?
Here's another example:
There is a RPG game built on Javascript. The hero in the game has two stats: strength and agility. the character's final damage is calculated by combining these two stats. It is clear that players can find out this logic by inspecting the source.
Let's assume the entire script is self invoked and stats/calculate functions are inside of objects' constructors so they can't be reached by normally after instantiated. My question is, can the players edit the character's str and agi while the game is running(by using Firebug or whatever) so they can steamroll everything and ruin the game?
The variable var1InConstructor cannot be re-bound under normal ECMAScript rules as it is visible only within the lexical scope. However, as alex (and others) rightly say, the client should not be trusted.
Here are some ways the user can exploit the assumption that the variable is read-only:
Use a JavaScript debugger (e.g. FireBug) and re-assign the variable while stopped at a breakpoint within the applicable scope.
Copy and paste the original source code, but add a setter with access to the variable. The user could even copy the entire program invalidating almost every assumption about execution.
Modify or inject a value at a usage site: an exploitation might be possible without ever actually updating the original variable (e.g. player.power = function () { return "godlike" }).
In the end, with a client-side program, there is no way to absolutely prevent a user from cheating without a centralized authority (read: server) auditing every action - and even then it still might be possible to cheat by reading additional game state, such as enemy positions.
JavaScript, being easy to read, edit, and execute dynamically is even easier to hack/fiddle with than a compiled application. Obfuscation is possible but, if someone wants to cheat, they will.
I don't think this constitutes an answer, it could be seen as anecdotal, but it's a bit long for a comment.
Everything you do when it comes to the integrity of your coding on this issue has to revolve around needing to verify that the data hasn't changed outside of the logic of your game.
My experience with game development (via flash, primarily...but could be compared to javascript) is that you need to think about everything being a handshake where possible. When you are expecting data to come to the server from the client you want to make sure that you have some form of passage of communication that lessens the chance of someone simply sending false data. Store data on the server side as much as possible and use the client side code to call for it when it's needed, and refresh this data store often.
You'll find that HTML games tend to do a lot of abstraction of the logic to the server side, even for menial tasks. Attacking an enemy, picking up an item, these are calls to functions within server-side code, and is why the game animation could carry on in some of these games while the connection times out in the background, causing error messages to pop up and refresh the interface to the server's last known valid state.
Flash was easier in this regard as you didn't have any access to alter any data or corrupt it unless it left the flash environment
Yes, anything ran on the client should be untrusted if you're using the data from it to update a server side state.
As you suggested, you can't hide the logic/client-side code. You can make it "harder" for people to read the source by obfuscating it, but it's very trivial to undo.
Assuming you're making a game from your example, the first rule of networked games is "never trust the client". You need to either run all the game logic on a server, or you need to validate all the input on a server. Never update the game state based on input from a client without validating it first.
You can't hide any variable.
Also, if the user is so good in javascript, he can easily edit your script, without editing the variables value through the console.
JS code that is injected into an HTML using Ajax is pretty darn difficult to get your hands on, but it also has it's limitations. Most notably, you can't use JS includes in injected HTML . . . only inline JS.
I've been working with some of that recently actually and it's a real pain to debug. You can't see it, step into it, or add breakpoints to it in any way that I can figure out . . . in Firebug or Chrome's built-in tool.
But, as others have said . . . I still wouldn't consider it trusted.
I have an app with a top frame and two framesets inside this top frame. While navigating to other pages the top frame remains the same and only the framesets change. I use localStorage for storing some data (which is also stored on the server, but if it is on client we don’t make the round trip each time), this feature is not available on IE7 so we decided to try to simulate localStorage in IE7.
The idea was to store a variable localStorage on the top frame (only if localStorage was not available). Whenever localStorage was not available on the top frame we would then create a dummy localStorage object with _data,getItem(),setItem(),removeItem(). The life of this object would last as long as the life of the top frame, which would save us a lot of round trips to the server and therefore offer a great performance boost in IE7.
The problem that I’m having is that whenever I change the frame (not the top frame) and I get the localStorage from the top frame and try to get an item using the window.top.localStorage.getItem(‘…’); I get the error message can't execute code from a freed script.
Any ideas why I get this??
I would recommend you to take a look in jStorage which provide common interface for localStorage, or old globalStorage or userData behavior. Probably you can use jStorage directly (see here) and save your time writing the corresponding code or you can use the same idea for your own implementation. More information about old userData behavior you can find for example here.
Maybe I will be repeating what Brilliand already shared, but as I don't understand his answer entirely I will share some ideas/advice as well:
First of all make sure that all relevant frames are hosted on the same domain (including things like opening the top frameset on www.domain.com and having internal links without the "www.")
In case you need cross domain scripting check out the internet for some relevant tricks to achieve that (the theory).
It might be worth trying to wrap all access to the localStorage within a few functions in the top frame (I can think of a few reasons which could theoretically cause problems with direct access to objects in the top frame... although this should as far as I know work).
Try reinitialize all references to subframes, you might for example have forgotten adding a "var" in front of a window.frames reference and not reinitalizing it after navigation (it would explain the error message, although it seems quite an unlikely mistake).
It might be also worth making sure to not keep any references to top.localStorage itself inside any of the child frames (although, again, it shouldn't cause any problems).
You might want to consider using a cross platform localstorage wrapper. They tend to work with proprietary functions in IE allowing a localStorage like functionality in IE as well (1MB max, but that should be enough). An example of such a library is store.js
See What causes the error "Can't execute code from a freed script"
That error message occurs when code created by the child frame (which has since been closed) is accessed. This means, at least, that you can't keep JavaScript functions around after the window they came from was closed; I'm not certain that applies to data objects as well, but it might. If so, then simple storage of JavaScript objects in the top window won't work.
It should be possible to work around this problem by ensuring that you completely detach the data from the child window before storing it. This can be done by having the storage function (which must be created by the parent window alone) JSON encode that data, and store the encoded string. Retrieval would be less finicky, since the retrieved object doesn't need to be kept around longer than the child window that retrieved it.