Home > Mobile >  Safe way of implementing single iframe for html files with script src=data:
Safe way of implementing single iframe for html files with script src=data:

Time:02-28

I have an webapp in Angular and on that website there is an iframe that is used to display some reports. Some of those reports are in HTML and have scripts in them in data:

<script src="data:application/javascript;base64,KGZ1bmN0a...Ck7Cgo="></script>

And I need to make them work. But for this to work I would have to change CSP to to allow script-src data: and this is not a very smart move. I was hopping to solve that by separating that iframe as much as possible from webapp so I was trying to use iframe in sandbox mode, yet it will still don't work without script-src data: due to having null origin.

Is there a way of setting some other origin for iframe or injecting custom CSP into it?

Is there is some other way of running data: scripts in iframe in at least semi secure way ?

CodePudding user response:

After some experimentation wit my coworker we cooked up solution that seems to work. Maybe it will help someone in some way. Also maybe someone have something to point out about it.

        const token = TokenService.getToken();
        var headers = [['Content-Security-Policy', 'script-src data:']];
        if (token) {
            headers.concat(['Authorization', token]);
        }
        const xhr = new XMLHttpRequest();
        xhr.open('GET', this.fileUrl.toString().replace('./', document.baseURI))
        xhr.responseType = 'document';
        xhr.onreadystatechange = ev => {
            if (xhr.readyState === xhr.DONE) {
                if (xhr.status === 200) {
                    var content = this.frameEl.nativeElement.contentWindow ||
                        this.frameEl.nativeElement.contentDocument.document ||
                        this.frameEl.nativeElement.contentDocument;
                    content.document.open();
                    content.document.write(xhr.response.documentElement.innerHTML);
                    content.document.close();
                } else {
                    this.frameEl.nativeElement.attr('srcdoc', '<html><head></head><body>Error loading data.</body></html>');
                }
            }
        }
        headers.forEach(function (header) {
            xhr.setRequestHeader(header[0], header[1]);
        });
        xhr.send();
  • Related