PhantomJs automation requires unsafe-eval to work

2019-09-15 02:33发布

问题:

I'm using Selenium Java and PhantomJs to automate a GUI that is written in Scala and running on the Play framework. Recently, the PhantomJs driver fails to run. I've traced it down to the security headers.

In the application.conf, if I have the following: play.filters.headers.contentSecurityPolicy="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"

Then the PhantomJs test fails on interacting with any form elements (even something as simple as finding a textbox and using sendKeys() on it.

The failure is:

Sep 13, 2016 9:55:52 AM org.openqa.selenium.phantomjs.PhantomJSDriverService <init>
INFO: executable: /usr/local/bin/phantomjs
Sep 13, 2016 9:55:52 AM org.openqa.selenium.phantomjs.PhantomJSDriverService <init>
INFO: port: 24167
Sep 13, 2016 9:55:52 AM org.openqa.selenium.phantomjs.PhantomJSDriverService <init>
INFO: arguments: [--webdriver=24167, --webdriver-logfile=/Users/andrew.fong/Documents/projects/ca-issuance/phantomjsdriver.log]
Sep 13, 2016 9:55:52 AM org.openqa.selenium.phantomjs.PhantomJSDriverService <init>
INFO: environment: {}
[INFO  - 2016-09-13T16:55:52.823Z] GhostDriver - Main - running on port 24167
[INFO  - 2016-09-13T16:55:52.982Z] Session [ee517e30-79d2-11e6-8032-47d95fff4a3c] - page.settings - {"XSSAuditingEnabled":true,"javascriptCanCloseWindows":true,"javascriptCanOpenWindows":true,"javascriptEnabled":true,"loadImages":true,"localToRemoteUrlAccessEnabled":true,"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1","webSecurityEnabled":false}
[INFO  - 2016-09-13T16:55:52.983Z] Session [ee517e30-79d2-11e6-8032-47d95fff4a3c] - page.customHeaders:  - {}
[INFO  - 2016-09-13T16:55:52.983Z] Session [ee517e30-79d2-11e6-8032-47d95fff4a3c] - Session.negotiatedCapabilities - {"browserName":"phantomjs","version":"2.1.1","driverName":"ghostdriver","driverVersion":"1.2.0","platform":"mac-10.11 (El Capitan)-64bit","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"},"phantomjs.page.settings.XSSAuditingEnabled":true,"phantomjs.page.settings.javascriptEnabled":true,"phantomjs.page.settings.webSecurityEnabled":false,"phantomjs.page.settings.localToRemoteUrlAccessEnabled":true}
[INFO  - 2016-09-13T16:55:52.983Z] SessionManagerReqHand - _postNewSessionCommand - New Session Created: ee517e30-79d2-11e6-8032-47d95fff4a3c
[ERROR - 2016-09-13T16:55:53.337Z] 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
[INFO  - 2016-09-13T16:55:53.347Z] ShutdownReqHand - _handle - About to shutdown

Sep 13, 2016 9:55:53 AM org.openqa.selenium.phantomjs.PhantomJSDriverService <init>
INFO: executable: /usr/local/bin/phantomjs
Sep 13, 2016 9:55:53 AM org.openqa.selenium.phantomjs.PhantomJSDriverService <init>
INFO: port: 22298
Sep 13, 2016 9:55:53 AM org.openqa.selenium.phantomjs.PhantomJSDriverService <init>
INFO: arguments: [--webdriver=22298, --webdriver-logfile=/Users/andrew.fong/Documents/projects/ca-issuance/phantomjsdriver.log]
Sep 13, 2016 9:55:53 AM org.openqa.selenium.phantomjs.PhantomJSDriverService <init>
INFO: environment: {}

org.openqa.selenium.UnsupportedCommandException: TypeError - undefined is not a constructor (evaluating '_getTagName(currWindow).toLowerCase()')
Command duration or timeout: 6 milliseconds
Build info: version: '2.39.0', revision: '14fa800511cc5d66d426e08b0b2ab926c7ed7398', time: '2013-12-16 13:18:38'
System info: host: 'afong-03', ip: '10.41.232.69', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.11.6', java.version: '1.8.0_91'
Driver info: org.openqa.selenium.phantomjs.PhantomJSDriver
Capabilities [{applicationCacheEnabled=false, rotatable=false, handlesAlerts=false, databaseEnabled=false, version=2.1.1, platform=MAC, browserConnectionEnabled=false, proxy={proxyType=direct}, nativeEvents=true, phantomjs.page.settings.XSSAuditingEnabled=true, phantomjs.page.settings.javascriptEnabled=true, acceptSslCerts=false, driverVersion=1.2.0, phantomjs.page.settings.webSecurityEnabled=false, locationContextEnabled=false, webStorageEnabled=false, phantomjs.page.settings.localToRemoteUrlAccessEnabled=true, browserName=phantomjs, takesScreenshot=true, driverName=ghostdriver, javascriptEnabled=true, cssSelectorsEnabled=true}]
Session ID: ee517e30-79d2-11e6-8032-47d95fff4a3c

    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:193)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:554)
    at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:268)
    at org.openqa.selenium.remote.RemoteWebElement.sendKeys(RemoteWebElement.java:89)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:192)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at com.workday.platsec.selenium.element.Textbox.action(Textbox.groovy:20)
    at com.workday.platsec.selenium.element.ValueWebElementInterface$action.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at com.workday.security.ca.views.pageObjects.MgmtActors.fillTextbox(MgmtActors.groovy:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:151)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:102)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:56)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:194)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:214)
    at com.workday.security.ca.views.pageObjects.MgmtActors.fillScope(MgmtActors.groovy:55)
    at com.workday.security.ca.views.pageObjects.MgmtActors$fillScope$0.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at com.workday.security.ca.views.pageObjectsTest.MgmtActorsTest.canFillScope(MgmtActorsTest.groovy:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runners.Suite.runChild(Suite.java:127)
    at org.junit.runners.Suite.runChild(Suite.java:26)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

If in the application.conf, I have the following: play.filters.headers.contentSecurityPolicy="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" (notice the 'unsafe-eval')

Then PhantomJs works fine. Also of note is that if I use Selenium and the Chrome browser, it works without the need for the 'unsafe-eval'. Strangely enough looking into the javascript, I didn't see any evals so it's unclear to me why unsafe-eval is needed to run the PhantomJs browser for these tests.