Whilst using CSP for a slightly different purpose (sandboxing) I realized that a very simple auto clicked link seems to bypass even relatively strict CSP. What I am describing i
This is unlikely going to be a satisfying approach - and obviously it isn't based on CSP - but it might be your only option if you really have to prevent such attacks. Before using anything like this, make sure that there is really no way to disable inline scripts (which should cover most attacks). Moreover, you should send your feedback to the public-webappsec@w3.org mailing list with a [CSP2] subject.
Here my (incomplete) idea:
function guardMethods(clazz, methodNames, urlGetter, allowFilter, reportViolation) {
var prototype = clazz.prototype;
methodNames.forEach(function (methodName) {
var originalMethod = prototype[methodName];
if (originalMethod) {
Object.defineProperty(prototype, methodName, {
value: function () {
var url = urlGetter.apply(this, arguments) || '';
if (allowFilter(url)) {
return originalMethod.apply(this, arguments);
} else {
reportViolation(url);
}
}
});
}
})
}
function allowFilter(url) {
// todo: implement
}
function reportViolation(url) {
console.error('Redirection prevented:', url);
}
guardMethods(HTMLAnchorElement, ['click', 'dispatchEvent', 'fireEvent'], function () {return this.href}, allowFilter, reportViolation);
You would have to implement similar guards for location, location.href, window.open and other functions/properties/events which allow to redirect to other pages. If you miss just one, then you are still vulnerable. Forms, XHR and most other resources can be covered with CSP itself. As far as I know, the prototype hack does not work in some older browsers.
Once more, I do not recommend to use this. The chance that you make a mistake or that it does not work in some browsers or that a new API will be added which can be leveraged for redirects is just too high.