"SCRIPT5: Access is denied" error when accessing web sites using LocalStorage - javascript

One of our client is getting ""SCRIPT5: Access is denied" error when accessing web sites on Windows 8.1/IE11. Only one client is having this issue not all.
when we looked at the error message it turns ut it failed when tried to access
_global.localStorage
Client said its working fine if they add our site in "Trusted Site".
the problem we having is that none of our dev/test environments has this issue.we are running same version of OS and IE as client. so we are having bit difficulty trying to reproduce this issue.
sa mentioned here
Access Denied for localstorage in IE10
i have tried turn on/off DOMStorage/Enhance Protection Mode/Protection Mode but still no luck.
our best guess so far is there must be some setting/group policy which applied by Client's IT dept which causes this issue rather code issue as it works for all other clients.
so my question here is
which setting/group policy/domain setting i can check so that i can reproduce this error.
How can i fix the issue w/o making any code change as client has more than 1000 users so only changing the policy by IT dept is the only option here rather asking every user to add to "Trusted Site"
is there anything that i missed to check.
any help would be awesome.

I had the same issue and solved it in the next way:
let storage;
try {
storage = localStorage; // throws error if not supported by browser
} catch(e) { // caching this error and assigning fallback
let innerStorage = {};
storage = {
getItem: function(e) {
return innerStorage[e]
},
setItem: function(e, i) {
return innerStorage[e] = i
},
removeItem: function(e) {
delete innerStorage[e]
}
}
Best regards,
Aleh

Related

How to detect if page doesn't allow to run external script via Content Security Policy? [duplicate]

I noticed that GitHub and Facebook are both implementing this policy now, which restricts third party scripts from being run within their experience/site.
Is there a way to detect whether a document is running against CSP using JavaScript?
I'm writing a bookmarklet, and want to give the user a message if they're on a site that doesn't support embedding a script tag.
You can try to catch a CSP violation error using an event "securitypolicyviolation"
From: https://developer.mozilla.org/en-US/docs/Web/API/SecurityPolicyViolationEvent
example:
document.addEventListener("securitypolicyviolation", (e) => {
console.log(e.blockedURI);
console.log(e.violatedDirective);
console.log(e.originalPolicy);
});
What about this. For slow connections, the timeout should probably be raised. Onload is what I used to detect it and it seems to work. If it loads then CSP obviously isn't enabled or it is configured improperly.
var CSP = 0;
frame = document.createElement('script');
frame.setAttribute('id', 'theiframe');
frame.setAttribute('src', location.protocol+'//example.com/');
frame.setAttribute('onload', 'CSP=1;');
document.body.appendChild(frame);
setTimeout(function(){if (0 == CSP){alert("CSP IS ENABLED");}}, 250);
From https://github.com/angular/angular.js/blob/cf16b241e1c61c22a820ed8211bc2332ede88e62/src/Angular.js#L1150-L1158, function noUnsafeEval
function noUnsafeEval() {
try {
/* jshint -W031, -W054 */
new Function('');
/* jshint +W031, +W054 */
return false;
} catch (e) {
return true;
}
}
Currently, there is no way to do so in shipping browsers.
However, something such as the following should work, per spec, and does in Chrome with experimental web platform features enabled in chrome://flags/:
function detectCSPInUse() {
return "securityPolicy" in document ? document.securityPolicy.isActive : false;
}
The SecurityPolicy interface (what you get from document.securityPolicy if it is implemented) has a few attributes that give more detail as to what is currently allowed.
An easy way to detect support for CSP is just by checking if JavaScript's eval()-method can be run without throwing an error, like so:
try {
eval("return false;");
} catch (e) {
return true;
}
However, this only works if CSP is actually turned on (obviously), with Content-Security-Policy being set in the response headers the page loaded with, and without 'unsafe-eval' in script-src.
I came here looking for a way to detect CSP support in browsers without CSP actually being turned on. It would seem this is not possible though.
On a side note, IE does not support CSP, only the sandbox directive in IE 10+, which, by looking at the CSP standard, does not make it a conformant web browser.
From https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5:
fetch(document.location.href)
.then(resp => {
const csp = resp.headers.get('Content-Security-Policy');
// does this exist? Is is any good?
});
This will fail however with connect-src='none' and be reported.
I am checking onError event in my bookmarklet code and prompt a user to install my extension if script is not loaded.
javascript:(function(){
var s=document.createElement('script');
s.setAttribute('type','text/javascript');
s.setAttribute('src','https://example.ru/bookmarklet?hostname=%27+encodeURIComponent(location.hostname));
s.setAttribute('onerror', 'if(confirm(`Downloading from the site is possible only through the "MyExtensionName" extension. Install extension?`)){window.open("https://chrome.google.com/webstore/detail/myextensionlink");}');
document.body.appendChild(s);})();

Import client certificate in IE with javascript

I trying to import/install a client certificate into IE but I'm getting following error in my js code.
function ImportClientCertificate()
{
try {
var objCertEnrollClassFactory = document.getElementById("objCertEnrollClassFactory");
var objEnroll = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509Enrollment");
var sPKCS7 = "-----BEGIN CERTIFICATE-----" +
"MIIDADCCAmkCCQ..." +
"-----END CERTIFICATE-----"
objEnroll.Initialize(1);
//->this line causes the exception
objEnroll.InstallResponse(3, sPKCS7, 1, "correctpassword");
}
catch (ex) {
alert(ex.description);
/*Exception being thrown: CertEnroll::CX509Enrollment::InstallResponse: Access is denied. 0x80070005 (WIN32: 5 ERROR_ACCESS_DENIED)*/
}
}
What could be the reason for this exception? I already tried to set the security level in IE to low but it doesn't helped. Manual installation of the cert into the users private cert store works fine.
Any help is highly appreciated.
I'm surprised this worked for you!
I found that I had to change the restrictions parameter (3 in your example) to be either 0 or 4. This is based on the MSDN documentation at https://msdn.microsoft.com/en-us/library/windows/desktop/aa378051(v=vs.85).aspx:
E_ACCESSDENIED
This method was called from the web and either AllowNoOutstandingRequest or AllowUntrustedCertificate was specified in the Restrictions parameter.
After two days of research on the net, I finally find out how to get this script working. The only solution I found for IE 11, is to enable following option in the IE settings box.

Modifying the Referer request header through a Google Chrome extension

I've got the following code which attempts to ensure that a Referer header is set when issuing requests:
chrome.webRequest.onBeforeSendHeaders.addListener(function (info) {
var refererRequestHeader = _.find(info.requestHeaders, function (requestHeader) {
return requestHeader.name === 'Referer';
});
var refererUrl = info.url.substring(0, info.url.indexOf('/embed/'));
if (_.isUndefined(refererRequestHeader)) {
info.requestHeaders.push({
name: 'Referer',
value: refererUrl
});
} else {
refererRequestHeader.value = refererUrl;
}
return { requestHeaders: info.requestHeaders };
}, {
// Match on my specific iframe or else else this logic can leak into outside webpages and corrupt other YouTube embeds.
urls: ['*://*.youtube.com/embed/?enablejsapi=1&origin=chrome-extension:\\\\jbnkffmindojffecdhbbmekbmkkfpmjd']
},
['blocking', 'requestHeaders']
);
This code works great 99% of the time. However, on some PCs, it fails. I am attempting to investigate why this is happening, but I don't have very many leads to go on.
My questions are:
Does this code look appropriate for what it is attempting to achieve? I attempt to find an existing Referer requestHeader. If found, I set the header's value to the given URL. If the header is not found, I push it.
I've done some reading on the "handlerBehaviorChanged" method exposed through chrome.webRequest.handlerBehaviorChanged, but I'm still unsure if this is something which could resolve my issue. I found this post: How to clean chrome in-memory cache? which hints at intermittent errors with chrome.webRequest... however, I didn't see anything conclusive. Would it be prudent to call handleBehaviorChanged after setting my listener?
What other options might I have for debugging this issue? Has anyone experienced intermittent failures in related scenarios?

How to detect Content Security Policy (CSP)

I noticed that GitHub and Facebook are both implementing this policy now, which restricts third party scripts from being run within their experience/site.
Is there a way to detect whether a document is running against CSP using JavaScript?
I'm writing a bookmarklet, and want to give the user a message if they're on a site that doesn't support embedding a script tag.
You can try to catch a CSP violation error using an event "securitypolicyviolation"
From: https://developer.mozilla.org/en-US/docs/Web/API/SecurityPolicyViolationEvent
example:
document.addEventListener("securitypolicyviolation", (e) => {
console.log(e.blockedURI);
console.log(e.violatedDirective);
console.log(e.originalPolicy);
});
From https://github.com/angular/angular.js/blob/cf16b241e1c61c22a820ed8211bc2332ede88e62/src/Angular.js#L1150-L1158, function noUnsafeEval
function noUnsafeEval() {
try {
/* jshint -W031, -W054 */
new Function('');
/* jshint +W031, +W054 */
return false;
} catch (e) {
return true;
}
}
What about this. For slow connections, the timeout should probably be raised. Onload is what I used to detect it and it seems to work. If it loads then CSP obviously isn't enabled or it is configured improperly.
var CSP = 0;
frame = document.createElement('script');
frame.setAttribute('id', 'theiframe');
frame.setAttribute('src', location.protocol+'//example.com/');
frame.setAttribute('onload', 'CSP=1;');
document.body.appendChild(frame);
setTimeout(function(){if (0 == CSP){alert("CSP IS ENABLED");}}, 250);
Currently, there is no way to do so in shipping browsers.
However, something such as the following should work, per spec, and does in Chrome with experimental web platform features enabled in chrome://flags/:
function detectCSPInUse() {
return "securityPolicy" in document ? document.securityPolicy.isActive : false;
}
The SecurityPolicy interface (what you get from document.securityPolicy if it is implemented) has a few attributes that give more detail as to what is currently allowed.
An easy way to detect support for CSP is just by checking if JavaScript's eval()-method can be run without throwing an error, like so:
try {
eval("return false;");
} catch (e) {
return true;
}
However, this only works if CSP is actually turned on (obviously), with Content-Security-Policy being set in the response headers the page loaded with, and without 'unsafe-eval' in script-src.
I came here looking for a way to detect CSP support in browsers without CSP actually being turned on. It would seem this is not possible though.
On a side note, IE does not support CSP, only the sandbox directive in IE 10+, which, by looking at the CSP standard, does not make it a conformant web browser.
From https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5:
fetch(document.location.href)
.then(resp => {
const csp = resp.headers.get('Content-Security-Policy');
// does this exist? Is is any good?
});
This will fail however with connect-src='none' and be reported.
I am checking onError event in my bookmarklet code and prompt a user to install my extension if script is not loaded.
javascript:(function(){
var s=document.createElement('script');
s.setAttribute('type','text/javascript');
s.setAttribute('src','https://example.ru/bookmarklet?hostname=%27+encodeURIComponent(location.hostname));
s.setAttribute('onerror', 'if(confirm(`Downloading from the site is possible only through the "MyExtensionName" extension. Install extension?`)){window.open("https://chrome.google.com/webstore/detail/myextensionlink");}');
document.body.appendChild(s);})();

How to detect browser's protocol handlers?

I have created a custom URL protocol handler.
http://
mailto://
custom://
I have registered a WinForms application to respond accordingly. This all works great.
But I would like to be able to gracefully handle the case where the user doesn't have the custom URL protocol handler installed, yet.
In order to be able to do this I need to be able to detect the browser's registered protocol handlers, I would assume from JavaScript. But I have been unable to find a way to poll for the information. I am hoping to find a solution to this problem.
Thanks for any ideas you might be able to share.
This would be a very, very hacky way to do this... but would this work?
Put the link in as normal...
But attach an onclick handler to it, that sets a timer and adds an onblur handler for the window
(in theory) if the browser handles the link (application X) will load stealing the focus from the window...
If the onblur event fires, clear the timer...
Otherwise in 3-5seconds let your timeout fire... and notify the user "Hmm, looks like you don't have the Mega Uber Cool Application installed... would you like to install it now? (Ok) (Cancel)"
Far from bulletproof... but it might help?
There's no great cross-browser way to do this. In IE10+ on Win8+, a new msLaunchUri api enables you to launch a protocol, like so:
navigator.msLaunchUri('skype:123456',
function()
{
alert('success');
},
function()
{
alert('failed');
}
);
If the protocol is not installed, the failure callback will fire. Otherwise, the protocol will launch and the success callback will fire.
I discuss this topic a bit further here:
https://web.archive.org/web/20180308105244/https://blogs.msdn.microsoft.com/ieinternals/2011/07/13/understanding-protocols/
This topic is of recent (2021) interest; see https://github.com/fingerprintjs/external-protocol-flooding for discussion.
HTML5 defines Custom scheme and content handlers (to my knowledge Firefox is the only implementor so far), but unfortunately there is currently no way to check if a handler already exists—it has been proposed, but there was no follow-up. This seems like a critical feature to use custom handlers effectively and we as developers should bring attention to this issue in order to get it implemented.
There seems to be no straightforward way via javascript to detect the presence of an installed app that has registered a protocol handler.
In the iTunes model, Apple provides urls to their servers, which then provide pages that run some javascript:
http://ax.itunes.apple.com/detection/itmsCheck.js
So the iTunes installer apparently deploys plugins for the major browsers, whose presence can then be detected.
If your plugin is installed, then you can be reasonably sure that redirecting to your app-specific url will succeed.
What seams the most easy solution is to ask the user the first time.
Using a Javascript confirm dialog per example:
You need this software to be able to read this link. Did you install it ?
if yes: create a cookie to not ask next time; return false and the link applies
if false: window.location.href = '/downloadpage/'
If you have control of the program you're trying to run (the code), one way to see if the user was successful in running the application would be to:
Before trying to open the custom protocol, make an AJAX request to a server script that saves the user's intent in a database (for example, save the userid and what he wanted to do).
Try to open the program, and pass on the intent data.
Have the program make a request to the server to remove the database entry (using the intent data to find the correct row).
Make the javascript poll the server for a while to see if the database entry is gone. If the entry is gone, you'll know the user was successful in opening the application, otherwise the entry will remain (you can remove it later with cronjob).
I have not tried this method, just thought it.
I was able to finally get a cross-browser (Chrome 32, Firefox 27, IE 11, Safari 6) solution working with a combination of this and a super-simple Safari extension. Much of this solution has been mentioned in one way or another in this and this other question.
Here's the script:
function launchCustomProtocol(elem, url, callback) {
var iframe, myWindow, success = false;
if (Browser.name === "Internet Explorer") {
myWindow = window.open('', '', 'width=0,height=0');
myWindow.document.write("<iframe src='" + url + "'></iframe>");
setTimeout(function () {
try {
myWindow.location.href;
success = true;
} catch (ex) {
console.log(ex);
}
if (success) {
myWindow.setTimeout('window.close()', 100);
} else {
myWindow.close();
}
callback(success);
}, 100);
} else if (Browser.name === "Firefox") {
try {
iframe = $("<iframe />");
iframe.css({"display": "none"});
iframe.appendTo("body");
iframe[0].contentWindow.location.href = url;
success = true;
} catch (ex) {
success = false;
}
iframe.remove();
callback(success);
} else if (Browser.name === "Chrome") {
elem.css({"outline": 0});
elem.attr("tabindex", "1");
elem.focus();
elem.blur(function () {
success = true;
callback(true); // true
});
location.href = url;
setTimeout(function () {
elem.off('blur');
elem.removeAttr("tabindex");
if (!success) {
callback(false); // false
}
}, 1000);
} else if (Browser.name === "Safari") {
if (myappinstalledflag) {
location.href = url;
success = true;
} else {
success = false;
}
callback(success);
}
}
The Safari extension was easy to implement. It consisted of a single line of injection script:
myinject.js:
window.postMessage("myappinstalled", window.location.origin);
Then in the web page JavaScript, you need to first register the message event and set a flag if the message is received:
window.addEventListener('message', function (msg) {
if (msg.data === "myappinstalled") {
myappinstalledflag = true;
}
}, false);
This assumes the application which is associated with the custom protocol will manage the installation of the Safari extension.
In all cases, if the callback returns false, you know to inform the user that the application (i.e., it's custom protocol) is not installed.
You say you need to detect the browser's protocol handlers - do you really?
What if you did something like what happens when you download a file from sourceforge? Let's say you want to open myapp://something. Instead of simply creating a link to it, create a link to another HTML page accessed via HTTP. Then, on that page, say that you're attempting to open the application for them. If it doesn't work, they need to install your application, which they can do by clicking on the link you'll provide. If it does work, then you're all set.
This was a recommended approach for IE by Microsoft support
http://msdn.microsoft.com/en-us/library/ms537503%28VS.85%29.aspx#related_topics
"If you have some control over the binaries being installed on a user’s machine, checking the UA in script seems like a relevant approach:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent\Post Platform
" -- By M$ support
Every web page has access to the userAgent string and if you drop a custom post platform value, detecting this in javascript using navigator.userAgent is quite simple.
Fortunately, other major browsers like Firefox and Chrome (barring Safari :( ), do not throw "page not found" errors when a link with a custom protocol is clicked and the protocol is not installed on the users machine. IE is very unforgiving here, any trick to click in a invisible frame or trap javascript errors does not work and ends up with ugly "webpage cannot be displayed" error. The trick we use in our case is to inform users with browser specific images that clicking on the custom protocol link will open an application. And if they do not find the app opening up, they can click on an "install" page. In terms of XD this wprks way better than the ActiveX approach for IE.
For FF and Chrome, just go ahead and launch the custom protocol without any detection. Let the user tell you what he sees.
For Safari, :( no answers yet
I'm trying to do something similar and I just discovered a trick that works with Firefox. If you combine it with the trick for IE you can have one that works on both main browsers (I'm not sure if it works in Safari and I know it doesn't work in Chrome)
if (navigator.appName=="Microsoft Internet Explorer" && document.getElementById("testprotocollink").protocolLong=="Unknown Protocol") {
alert("No handler registered");
} else {
try {
window.location = "custom://stuff";
} catch(err) {
if (err.toString().search("NS_ERROR_UNKNOWN_PROTOCOL") != -1) {
alert("No handler registered");
}
}
}
In order for this to work you also need to have a hidden link somewhere on the page, like this:
<a id="testprotocollink" href="custom://testprotocol" style="display: none;">testprotocollink</a>
It's a bit hacky but it works. The Firefox version unfortunately still pops up the default alert that comes up when you try to visit a link with an unknown protocol, but it will run your code after the alert is dismissed.
You can try something like this:
function OpenCustomLink(link) {
var w = window.open(link, 'xyz', 'status=0,toolbar=0,menubar=0,height=0,width=0,top=-10,left=-10');
if(w == null) {
//Work Fine
}
else {
w.close();
if (confirm('You Need a Custom Program. Do you want to install?')) {
window.location = 'SetupCustomProtocol.exe'; //URL for installer
}
}
}
This is not a trivial task; one option might be to use signed code, which you could leverage to access the registry and/or filesystem (please note that this is a very expensive option). There is also no unified API or specification for code signing, so you would be required to generate specific code for each target browser. A support nightmare.
Also, I know that Steam, the gaming content delivery system, doesn't seem to have this problem solved either.
Here's another hacky answer that would require (hopefully light) modification to your application to 'phone home' on launch.
User clicks link, which attempts to launch the application. A unique
identifier is put in the link, so that it's passed to the
application when it launches. Web app shows a spinner or something of that nature.
Web page then starts checking for a
'application phone home' event from an app with this same unique ID.
When launched, your application does an HTTP post to your web app
with the unique identifier, to indicate presence.
Either the web page sees that the application launched, eventually, or moves on with a 'please download' page.

Categories