ariya / phantomjs

Scriptable Headless Browser

Home Page:http://phantomjs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

'unsafe-eval' is not an allowed ... Security Policy directive: "script-src 'self'

jain0709 opened this issue · comments

trying to automate scenario for login https site getting following error :-

[DEBUG] WebPage - evaluateJavaScript result QVariant(QVariantMap, QMap(("status", QVariant(double, 13) ) ( "value" , QVariant(QVariantMap, QMap(("message", QVariant(QString, "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' ".
") ) ) ) ) ) )
2015-03-27T20:34:57 [DEBUG] HTTP Response - Status Code 500 Internal Server Error

same test is working fine when using chrome browser. Running phantom js as :-

phantomjs --ignore-ssl-errors=true --web-security=false --ssl-protocol=tlsv1 --local-to-remote-url-access=true --webdriver=4444 --debug=true

seems some kind of bug with phantomjs.

I'm having the same issue when trying to log in through IdentityServer3 with PhantomJS 2. Chrome and PhantomJS 1.9.8 work just fine.

Thanks for suggestion, It worked with PhantomJS 1.9.8

@jain0709 We don't want you to have to downgrade. If something worked in 1.9.x and doesn't in 2.0, that's something we should fix.

That said, we need quite a bit more information from you before we can do anything about this. Specifically, we need to know what website provoked this error, and how you were using PhantomJS to access it -- not just the command line invocation, but the script. If at all possible, construct a self-contained test script that we can run as

$ phantomjs issue13114.js

and see the same problem you are. It's OK if you need extra files or even a web server, just explain in enough detail that we can make it happen for ourselves.

Also, there's a decent chance this is a situation where the newer Webkit in 2.0 is refusing to do something insecure when the older one would let you get away with it. This is a guess, based on the text of the error message. I could be wrong.

Also also, you shouldn't ever need to use --ignore-ssl-errors=true or --web-security=false -- that suggests to me that you have major problems with the environment you're running PhantomJS in, and you may find that this problem vanishes if you sort those out first.

@zackw I'll see about creating a quick test case soon. The problem I was experiencing is that my app was doing a redirect (via JavaScript) to our authentication server, which was a different page, but on the same domain (virtual directories in IIS). I tried accessing the login page directly and it worked just fine.

@zackw Here's a commit with a test case that MIGHT be reproducing the issue. If not the right issue, it still is one I think! Vooban@a18eab4

Simply start a two web servers for the folder on port 8000 and 8001 and the output is something like :

success 8000
redirect caught
Operation canceled
http://localhost:8001/index2.html
failed http://localhost:8001/index2.html

@cdroulers That doesn't appear to have anything to do with Content-Security-Policy directives?

@zackw Nope. I caught this while trying to reproduce. I'm still unable to create a test case. The problem happens for me with a C# Selenium test case. Would it be okay to create a repro this way?

@cdroulers I think we can cope with that, if that's what you need to do to make it happen.

@zackw I've narrowed it down to a decent test case. If I try to render a page with a Content-Security-Policy in a phantomjs script, the page loads and renders in a screenshot fine. The JavaScript is not executed.

If I try to load that page with Selenium's RemoteWebDriver though, it fails with the error. I'm trying to create a very small and specific test case to reproduce it. Do you have a suggestion on how to write that test case with selenium in a language that would be easy to run for you? Ruby, Python, etc. I can figure out how to write it!

@cdroulers Anything you can possibly do to reproduce the issue without Selenium is worth doing, but beyond that, don't worry about languages; we're gonna have to rewrite it to fit it into our automated test suite anyway.

"The JavaScript is not executed", though, that might be enough of a clue right there. Which JavaScript exactly was that?

@zackw The JavaScript not being executed is inlined JavaScript, which the Content-Security-Policy header forbids. When I open the page in Chrome, nothing is executed and I get warnings in the developer console.

In Phantom, everything succeeds without warnings (that I can see!), the screenshot is taken properly. In the JavaScript, I try to write in the body, and the text does not appear in the body. So I think PhantomJS is handling everything just fine.

On the other hand, when I simply try to load the page in Selenium and then read the Url or Title of the IWebDriver, it fails with the error in the OP. I'm starting to think it's a problem with the Selenium Web Driver! Do you have any idea how it works for PhantomJS?

master...Vooban:master

Here's a diff of how I got a repro. The issue13114.js works fine (and doesn't execute the JS).

The Selenium test case crashes with the error from the OP. I'm not well versed with Selenium enough to know what exactly happens between the two when driver.Url is called.

this happen on https://github.com now(phantomjs-2.1.1-windows):

 1) Github test open URL Then  I expect that the url is "https://github.com/":
     Uncaught Error: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the
following Content Security Policy directive: "script-src assets-cdn.github.com".
 Uncaught Error: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the
following Content Security Policy directive: "script-src assets-cdn.github.com".

the phantomjs raise error:

[INFO  - 2016-02-24T13:47:49.812Z] GhostDriver - Main - running on port 4444
[INFO  - 2016-02-24T13:48:02.627Z] Session [3937fde0-dafd-11e5-ac6f-115b0bd0fe78] - page.settings - {"XSSAuditingEnabled":false,"javascriptCanCloseWindows":true,"javascriptCanOpenWindows":true,"javascriptEnabled":true,"loadImages":true,"localToRemoteUrlAccessEnabled":false,"userAgent":"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1","webSecurityEnabled":false}
[INFO  - 2016-02-24T13:48:02.627Z] Session [3937fde0-dafd-11e5-ac6f-115b0bd0fe78] - page.customHeaders:  - {}
[INFO  - 2016-02-24T13:48:02.627Z] Session [3937fde0-dafd-11e5-ac6f-115b0bd0fe78] - Session.negotiatedCapabilities - {"browserName":"phantomjs","version":"2.1.1","driverName":"ghostdriver","driverVersion":"1.2.0","platform":"windows-10-32bit","javascriptEnabled":true,"takesScreenshot":true,"handlesAlerts":false,"databaseEnabled":false,"locationContextEnabled":false,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"cssSelectorsEnabled":true,"webStorageEnabled":false,"rotatable":false,"acceptSslCerts":false,"nativeEvents":true,"proxy":{"proxyType":"direct"}}
[INFO  - 2016-02-24T13:48:02.627Z] SessionManagerReqHand - _postNewSessionCommand - New Session Created: 3937fde0-dafd-11e5-ac6f-115b0bd0fe78
[ERROR - 2016-02-24T13:48:31.217Z] RouterReqHand - _handle.error - {"line":264,"sourceURL":"phantomjs://code/webelement_request_handler.js","stack":"_postValueCommand@phantomjs://code/webelement_request_handler.js:264:52\n_handle@phantomjs://code/webelement_request_handler.js:72:30\n_reroute@phantomjs://code/request_handler.js:61:20\n_handle@phantomjs://code/session_request_handler.js:120:42\n_reroute@phantomjs://code/request_handler.js:61:20\n_handle@phantomjs://code/router_request_handler.js:78:46"}

  phantomjs://platform/console++.js:263 in error

Same happening to me when I call Driver.Url. It worked with version 1.9.8.

Running on Selenium, C#.

Same issue here: seems to do that whenever trying to load anything with HTTPS, really.

Same as what @snowyu reported.

I'm also seeing this issue as described by @snowyu. Running selenium, ruby.

I have also the issue running phantomjs 2.1.1 with :

  • behat v2.5.5
  • behat/mink v1.7.1
  • mink-selenium2-driver v1.3.1
  • on ubuntu 14.04

And it works with phantomjs 1.9.8

Here is a short example that reproduces the issue without Selenium and either with or without --web-security=false. The error occurs when loading github.com, but not with any other site (e.g yahoo.com).
`

var debug = require('debug')('myapp:example');    
// Load the page using Horseman/PhantomJS.

// This function is called inside the context of the loaded page.
function example() {
    return 'success';
}

// To debug, use "DEBUG=myapp:*,horseman npm start"
var Horseman = require('node-horseman');

module.exports = function (req, res) {
    var url = 'http://' + req.query.domain;
    var security = req.query.security;
    debug('Security: ' + security);
    var horseman = new Horseman({webSecurity:security});

    horseman
        // Open the page and extract the data.
        .open(url)
        .evaluate(example)
        .then(function(result){
            res.render('results', { result: result });
        })
        .catch(function (e) {
            debug('Caught error: ' + e.message);
            res.render('error', {message: e.message, error: e});
        })
};

`
If you call this with http://localhost:3000/example?domain=github.com&security=true you get:

horseman phantom version 2.1.1
myapp:example Caught error: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src assets-cdn.github.com".

I know what's wrong now. Github is sending a Content-Security-Policy directive that forbids inline scripts. page.evaluate injects code using inline scripts, so it doesn't work. It's effectively the same phenomenon as Content-Security-Policy breaking bookmarklets.

This looks like a 2.0 regression probably because 1.9.x didn't implement CSP.

We need to figure out a way to exempt page.evaluate from CSP restrictions. Unfortunately, this might involve adding new interfaces to Qt/Webkit. I can't promise you any kind of timeframe for a fix.

@mself I tagged this "need minimized test case" in spite of your nice tidy test case because we still need a self-contained test case -- one that doesn't have any dependency on github.com, which could change out from under us. If you have time to convert this test case into something that could be dropped into the existing automated test framework (this would involve getting rid of Horseman as well), that would be immensely helpful, but if you don't, we will get to it eventually.

Removing Horseman should be trivial since it looks like any attempt to use page.evaluate on github.com will trigger the issue (unless the issue is related to how Horseman auto-injects jQuery).

But I don't know enough about CSP to craft a sample page to load that would trigger the issue. And might the behavior be different for local files vs. localhost vs. a hosted page that uses SSL? That could make the test case harder to implement.

I'm afraid I don't know enough about CSP to answer most of those questions myself. That said, I think the only thing necessary is a page - contents don't matter - served with Content-Security-Policy: script-src 'none'. (I don't think there is any way to accomplish that from a local file, but localhost vs. external page shouldn't matter, and the test suite provides HTTP and HTTPS web servers on localhost.)

Github is currently using a more complicated CSP directive, but I think the bulk of it is irrelevant:

default-src 'none'; base-uri 'self'; connect-src 'self' uploads.github.com status.github.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com api.braintreegateway.com client-analytics.braintreegateway.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; frame-src render.githubusercontent.com; img-src 'self' data: assets-cdn.github.com identicons.github.com www.google-analytics.com collector.githubapp.com *.gravatar.com *.wp.com checkout.paypal.com *.githubusercontent.com; media-src 'none'; object-src assets-cdn.github.com; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com

Wondering if the JS can be executed from the chrome context (privileged)
rather than from the normal page context. Would that still be affected?
On Apr 27, 2016 18:42, "Zack Weinberg" notifications@github.com wrote:

I'm afraid I don't know enough about CSP to answer most of those questions
myself. That said, I think the only thing necessary is a page -
contents don't matter - served with Content-Security-Policy: script-src
'none'. (I don't think there is any way to accomplish that from a local
file, but localhost vs. external page shouldn't matter, and the test suite
provides HTTP and HTTPS web servers on localhost.)

Github is currently using a more complicated CSP directive:

default-src 'none'; base-uri 'self'; connect-src 'self' uploads.github.com status.github.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com api.braintreegateway.com client-analytics.braintreegateway.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; frame-src render.githubusercontent.com; img-src 'self' data: assets-cdn.github.com identicons.github.com www.google-analytics.com collector.githubapp.com *.gravatar.com *.wp.com checkout.paypal.com *.githubusercontent.com; media-src 'none'; object-src assets-cdn.github.com; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#13114 (comment)

@Ocramius It is unclear to me - as a developer! - whether (Qt/)Webkit even has that distinction, let alone whether its idea of that distinction lines up with what we would need in this context.

Any updates on this? We're also bumping into the issue with Identity Server 3.

+1
any workaround on how to use page.evaluate in this case?

We added 'unsafe-eval' to our CSP options for Identity Server in our CI environment in the interim.

@travisjweber any details on what/how you did it, and if it helped? That could be useful to know for all others involved in the thread.

Well for IdentityServer3 this did the trick (using ASP.NET Core, targeting .NET 4.6.2)

`var cspOptions = new CspOptions();

//override script source defaults for dev to allow phantom JS/Selenium to run
if (env.IsDevelopment() || env.IsLocalDevelopment())
{
cspOptions.ScriptSrc = "'self' 'unsafe-eval'";
}

var idsrvOptions = new IdentityServerOptions
{
Factory = //.... other unrelated details omitted here....
CspOptions = cspOptions
};

app.UseIdentityServer(idsrvOptions);`

@traviscooper thanks! Sorry, I misunderstood the solution then, that does indeed work if you have control over the server-side.

Oh yeah, most definitely need that control! Our same tests work with chrome's driver FYI, we were using that locally but it doesn't work with our builds so we [temporarily] relaxed the CSP so Phantom works until we can figure out something longer-term.

Going through the replies seem temporary fix is to downgrade PhantomJS or modify CSP option for Identity Server....
In our case here we have to use at least 2.1 due its support of SSL certificates, also no access to the Identity Server - what would be the solution in this case?
It is mentioned to remove horseman? If yes, how or what is another option?

Thank you.

Hi, I am using this dependency in my sbt build :
"com.github.detro.ghostdriver" % "phantomjsdriver" % "1.0.1"
and by default it is using this combination :
"browserName":"phantomjs","version":"2.1.1","driverName":"ghostdriver","driverVersion":"1.2.0"
How to use the 1.9.8 version ?.

Seeing the same thing trying to interact with stripe website while authorizing an API. Works fine with chrome just like others have said.

We wound up creating an http proxy to strip out the csp directive for running our tests with phantomjs.

We encountered the same problem while trying to implement a behat test for SOFORT payment integration. Any progress here?

commented

Any progress here?

it should work for every command but execute_script and execute_async_script in the next version of ghostdriver.

In meteor we used this:

if (process.env.NODE_ENV === 'development') {
    BrowserPolicy.content.allowEval(); // for PhantomJS end-to-end testing
}

Which is something like this in raw content-security-policy header:

script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost:3000 https://localhost:3000

Also experiencing this issue.

In Python's webdriver, even reading current_url (which calls execute("getCurrentUrl")['value']) raises a WebDriverException with the unsafe-eval complaint on affected sites. (Tested on PhantomJS 2.1.1.)

We've switched to using Selenium-Grid with Chrome and Internet Explorer, no more dealing with a headless browser just for our Selenium tests.

Any updates on this issue?

also hitting this issue now 2.5 years later :(

PhantomJS latest stable version 2.1.1 has a bug when it tries to get a webpage that has the following response header:
content-security-policy: default-src 'none'

The Fix:
Branch 2.1.1, File: \phantomjs\src\qt\qtwebkit\Source\WebCore\page\ContentSecurityPolicy.cpp, Change line 354:

, m_allowEval(false)

To:

, m_allowEval(true)

Then build.py -r ... Enjoy!

commented

Due to our very limited maintenance capacity (see #14541 for more details), we need to prioritize our development focus on other tasks. Therefore, this issue will be automatically closed. In the future, if we see the need to attend to this issue again, then it will be reopened. Thank you for your contribution!