diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a6db3fd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM art-hq.intranet.qualys.com:5006/secure/distroless/debian12/zing/java-nonroot:24.08.300.0-2-jre17.0.13.0.101 + +USER root + +WORKDIR /home/app +ADD --chown=app:app ./target/github-was-action.jar /home/app/GitHubActionsQWas-0.0.1-SNAPSHOT.jar +ADD --chown=app:app ./run_service.sh /home/app/run_service.sh + +RUN /busybox/mkdir -p /home/app/outputs + +VOLUME /home/app/outputs + +RUN ["/busybox/chmod", "775", "/home/app/run_service.sh"] + +RUN ["/busybox/chmod", "-R", "777", "/home/app/outputs"] + +RUN chmod ugo+rwx $JAVA_HOME/lib/security/cacerts + +#HEALTHCHECK CMD curl --fail localhost:8081/actuator/health || exit 1 +USER app +ENTRYPOINT ["/busybox/sh", "/home/app/run_service.sh"] diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..a733630 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,18 @@ +@Library("jenkins-libraries-v2@master") +import com.qualys.pipeline.* + +def templateName = "generic-docker-template" +def branch = "master" +def nodeLabel = "slave" + +pipeline = loadPipelineTemplate(templateName, branch, nodeLabel) + +def customPreHookStep = {sh "sed -i 's/RELEASE<\\/release.number>/${BUILD_ID}<\\/release.number>/g' ${WORKSPACE}/pom.xml"} + +HooksHelper hook = new HooksHelper() +hook.addPreHook(StageName.BUILD, customPreHookStep) + +// use when hook is enabled +pipeline.runPipeline("properties.yaml", nodeLabel, hook) + +//pipeline.runPipeline("properties.yaml", nodeLabel) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..80a5728 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Swapnil Ramesh Adhav + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index f6c1c55..9ab984c 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,12 @@ jobs: uses: Qualys/github-action-qwas@main id: was with: - API_SERVER: ${{ vars.API_SERVER }} + PLATFORM: ${{ vars.PLATFORM }} + AUTH_TYPE: ${{ vars.AUTH_TYPE }} QUALYS_USERNAME: ${{ vars.QUALYS_USERNAME }} QUALYS_PASSWORD: ${{ secrets.QUALYS_PASSWORD }} + CLIENT_ID: ${{ vars.CLIENT_ID }} + CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }} WEBAPP_ID: ${{ vars.WEBAPP_ID }} SCAN_NAME: ${{ vars.SCAN_NAME }} SCAN_TYPE: ${{ vars.SCAN_TYPE }} @@ -111,9 +114,12 @@ jobs: uses: Qualys/github-action-qwas@main id: was with: - API_SERVER: ${{ vars.API_SERVER }} + PLATFORM: ${{ vars.PLATFORM }} + AUTH_TYPE: ${{ vars.AUTH_TYPE }} QUALYS_USERNAME: ${{ vars.QUALYS_USERNAME }} QUALYS_PASSWORD: ${{ secrets.QUALYS_PASSWORD }} + CLIENT_ID: ${{ vars.CLIENT_ID }} + CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }} WEBAPP_ID: ${{ vars.WEBAPP_ID }} SCAN_NAME: ${{ vars.SCAN_NAME }} SCAN_TYPE: ${{ vars.SCAN_TYPE }} @@ -169,9 +175,12 @@ jobs: uses: Qualys/github-action-qwas@main id: was with: - API_SERVER: ${{ vars.API_SERVER }} + PLATFORM: ${{ vars.PLATFORM }} + AUTH_TYPE: ${{ vars.AUTH_TYPE }} QUALYS_USERNAME: ${{ vars.QUALYS_USERNAME }} QUALYS_PASSWORD: ${{ secrets.QUALYS_PASSWORD }} + CLIENT_ID: ${{ vars.CLIENT_ID }} + CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }} WEBAPP_ID: ${{ vars.WEBAPP_ID }} SCAN_NAME: ${{ vars.SCAN_NAME }} SCAN_TYPE: ${{ vars.SCAN_TYPE }} @@ -229,9 +238,12 @@ jobs: uses: Qualys/github-action-qwas@main id: was with: - API_SERVER: ${{ vars.API_SERVER }} + PLATFORM: ${{ vars.PLATFORM }} + AUTH_TYPE: ${{ vars.AUTH_TYPE }} QUALYS_USERNAME: ${{ vars.QUALYS_USERNAME }} QUALYS_PASSWORD: ${{ secrets.QUALYS_PASSWORD }} + CLIENT_ID: ${{ vars.CLIENT_ID }} + CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }} WEBAPP_ID: ${{ vars.WEBAPP_ID }} SCAN_NAME: ${{ vars.SCAN_NAME }} SCAN_TYPE: ${{ vars.SCAN_TYPE }} @@ -278,9 +290,12 @@ If repository is private, then add PAT (personal access token) token in the chec | Parameter | Description | Mandatory/ Optional | Default Value | Parameter Type | |--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------|---------------|----------------| -| QUALYS_PASSWORD | Use the Qualys Password | Mandatory | "" | Secret | -| QUALYS_USERNAME | Use the Qualys Username | Mandatory | "" | Variable | -| API_SERVER | Use the API URL. [Click here](https://www.qualys.com/platform-identification/) to get your API URL. (Make sure that you provide API server URL only. Platform URL or API Gateway URL is not valid) | Mandatory | "" | Variable | +| PLATFORM | This parameter specifies the qualys platform. | Mandatory | "" | Variable | +| AUTH_TYPE | This parameter specifies the authentication type. BASIC and OAUTH are supported | Mandatory | "" | Variable | +| QUALYS_PASSWORD | Use the Qualys Password will be used in BASIC authentication. | Mandatory for BASIC | "" | Secret | +| QUALYS_USERNAME | Use the Qualys Username will be used in BASIC authentication. | Mandatory for BASIC | "" | Variable | +| CLIENT_ID | This parameter specifies the client id will be used in OAUTH authentication. | Mandatory for OAUTH | "" | Variable | +| CLIENT_SECRET | This parameter specifies the client secret will be used in OAUTH authentication. | Mandatory for OAUTH | "" | Secret | | WEBAPP_ID | Use the Web App ID that you want to scan. | Mandatory | "" | Variable | | SCAN_NAME | Use any name for the scan. The timestamp gets appended automatically. | Mandatory | "" | Variable | | SCAN_TYPE | This parameter specifies the scan type. Use VULNERABILITY or DISCOVERY as a parameter value. | Mandatory | "" | Variable | diff --git a/Test Results - java_in_GitHubActionsQWas.html b/Test Results - java_in_GitHubActionsQWas.html new file mode 100644 index 0000000..08068f8 --- /dev/null +++ b/Test Results - java_in_GitHubActionsQWas.html @@ -0,0 +1,1020 @@ + + + + + Test Results — java in GitHubActionsQWas + + + + + + + + + +
+ +
+
    + "C:\Program Files\Eclipse Adoptium\jdk-17.0.8.101-hotspot\bin\java.exe" -ea -javaagent:C:\Users\sadhav\AppData\Local\JetBrains\IdeaIC2023.3\testAgent\intellij-coverage-agent-1.0.738.jar=C:\Users\sadhav\AppData\Local\Temp\coverage1286args -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\lib\idea_rt.jar=62994:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Users\sadhav\.m2\repository\org\junit\platform\junit-platform-launcher\1.9.3\junit-platform-launcher-1.9.3.jar;C:\Users\sadhav\.m2\repository\org\junit\vintage\junit-vintage-engine\5.9.3\junit-vintage-engine-5.9.3.jar;C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\plugins\junit\lib\junit5-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\plugins\junit\lib\junit-rt.jar;C:\Users\sadhav\OneDrive - Qualys, Inc\Desktop\Projects\github-action-qwas\target\test-classes;C:\Users\sadhav\OneDrive - Qualys, Inc\Desktop\Projects\github-action-qwas\target\classes;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-starter-web\3.1.6\spring-boot-starter-web-3.1.6.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-starter\3.1.6\spring-boot-starter-3.1.6.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot\3.1.6\spring-boot-3.1.6.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\3.1.6\spring-boot-autoconfigure-3.1.6.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-starter-logging\3.1.6\spring-boot-starter-logging-3.1.6.jar;C:\Users\sadhav\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.20.0\log4j-to-slf4j-2.20.0.jar;C:\Users\sadhav\.m2\repository\org\apache\logging\log4j\log4j-api\2.20.0\log4j-api-2.20.0.jar;C:\Users\sadhav\.m2\repository\org\slf4j\jul-to-slf4j\2.0.9\jul-to-slf4j-2.0.9.jar;C:\Users\sadhav\.m2\repository\jakarta\annotation\jakarta.annotation-api\2.1.1\jakarta.annotation-api-2.1.1.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-starter-json\3.1.6\spring-boot-starter-json-3.1.6.jar;C:\Users\sadhav\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.15.3\jackson-databind-2.15.3.jar;C:\Users\sadhav\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.15.3\jackson-annotations-2.15.3.jar;C:\Users\sadhav\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.15.3\jackson-core-2.15.3.jar;C:\Users\sadhav\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.15.3\jackson-datatype-jdk8-2.15.3.jar;C:\Users\sadhav\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.15.3\jackson-datatype-jsr310-2.15.3.jar;C:\Users\sadhav\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.15.3\jackson-module-parameter-names-2.15.3.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\3.1.6\spring-boot-starter-tomcat-3.1.6.jar;C:\Users\sadhav\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\10.1.16\tomcat-embed-core-10.1.16.jar;C:\Users\sadhav\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\10.1.16\tomcat-embed-el-10.1.16.jar;C:\Users\sadhav\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\10.1.16\tomcat-embed-websocket-10.1.16.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-web\6.0.14\spring-web-6.0.14.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-beans\6.0.14\spring-beans-6.0.14.jar;C:\Users\sadhav\.m2\repository\io\micrometer\micrometer-observation\1.11.6\micrometer-observation-1.11.6.jar;C:\Users\sadhav\.m2\repository\io\micrometer\micrometer-commons\1.11.6\micrometer-commons-1.11.6.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-webmvc\6.0.14\spring-webmvc-6.0.14.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-aop\6.0.14\spring-aop-6.0.14.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-context\6.0.14\spring-context-6.0.14.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-expression\6.0.14\spring-expression-6.0.14.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-starter-test\3.1.6\spring-boot-starter-test-3.1.6.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-test\3.1.6\spring-boot-test-3.1.6.jar;C:\Users\sadhav\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\3.1.6\spring-boot-test-autoconfigure-3.1.6.jar;C:\Users\sadhav\.m2\repository\com\jayway\jsonpath\json-path\2.8.0\json-path-2.8.0.jar;C:\Users\sadhav\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\4.0.1\jakarta.xml.bind-api-4.0.1.jar;C:\Users\sadhav\.m2\repository\jakarta\activation\jakarta.activation-api\2.1.2\jakarta.activation-api-2.1.2.jar;C:\Users\sadhav\.m2\repository\net\minidev\json-smart\2.4.11\json-smart-2.4.11.jar;C:\Users\sadhav\.m2\repository\net\minidev\accessors-smart\2.4.11\accessors-smart-2.4.11.jar;C:\Users\sadhav\.m2\repository\org\assertj\assertj-core\3.24.2\assertj-core-3.24.2.jar;C:\Users\sadhav\.m2\repository\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;C:\Users\sadhav\.m2\repository\org\junit\jupiter\junit-jupiter\5.9.3\junit-jupiter-5.9.3.jar;C:\Users\sadhav\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.9.3\junit-jupiter-api-5.9.3.jar;C:\Users\sadhav\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;C:\Users\sadhav\.m2\repository\org\junit\platform\junit-platform-commons\1.9.3\junit-platform-commons-1.9.3.jar;C:\Users\sadhav\.m2\repository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;C:\Users\sadhav\.m2\repository\org\junit\jupiter\junit-jupiter-params\5.9.3\junit-jupiter-params-5.9.3.jar;C:\Users\sadhav\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.9.3\junit-jupiter-engine-5.9.3.jar;C:\Users\sadhav\.m2\repository\org\junit\platform\junit-platform-engine\1.9.3\junit-platform-engine-1.9.3.jar;C:\Users\sadhav\.m2\repository\org\mockito\mockito-core\5.3.1\mockito-core-5.3.1.jar;C:\Users\sadhav\.m2\repository\org\objenesis\objenesis\3.3\objenesis-3.3.jar;C:\Users\sadhav\.m2\repository\org\mockito\mockito-junit-jupiter\5.3.1\mockito-junit-jupiter-5.3.1.jar;C:\Users\sadhav\.m2\repository\org\skyscreamer\jsonassert\1.5.1\jsonassert-1.5.1.jar;C:\Users\sadhav\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-core\6.0.14\spring-core-6.0.14.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-jcl\6.0.14\spring-jcl-6.0.14.jar;C:\Users\sadhav\.m2\repository\org\springframework\spring-test\6.0.14\spring-test-6.0.14.jar;C:\Users\sadhav\.m2\repository\org\xmlunit\xmlunit-core\2.9.1\xmlunit-core-2.9.1.jar;C:\Users\sadhav\.m2\repository\org\apache\httpcomponents\httpclient\4.5.13\httpclient-4.5.13.jar;C:\Users\sadhav\.m2\repository\org\apache\httpcomponents\httpcore\4.4.16\httpcore-4.4.16.jar;C:\Users\sadhav\.m2\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;C:\Users\sadhav\.m2\repository\commons-codec\commons-codec\1.15\commons-codec-1.15.jar;C:\Users\sadhav\.m2\repository\com\google\code\gson\gson\2.8.9\gson-2.8.9.jar;C:\Users\sadhav\.m2\repository\org\projectlombok\lombok\1.18.30\lombok-1.18.30.jar;C:\Users\sadhav\.m2\repository\junit\junit\4.13.2\junit-4.13.2.jar;C:\Users\sadhav\.m2\repository\org\hamcrest\hamcrest-core\2.2\hamcrest-core-2.2.jar;C:\Users\sadhav\.m2\repository\org\yaml\snakeyaml\2.2\snakeyaml-2.2.jar;C:\Users\sadhav\.m2\repository\ch\qos\logback\logback-classic\1.4.14\logback-classic-1.4.14.jar;C:\Users\sadhav\.m2\repository\org\slf4j\slf4j-api\2.0.9\slf4j-api-2.0.9.jar;C:\Users\sadhav\.m2\repository\ch\qos\logback\logback-core\1.4.14\logback-core-1.4.14.jar;C:\Users\sadhav\.m2\repository\org\slf4j\slf4j-simple\2.0.9\slf4j-simple-2.0.9.jar;C:\Users\sadhav\.m2\repository\com\github\stefanbirkner\system-lambda\1.2.1\system-lambda-1.2.1.jar;C:\Users\sadhav\.m2\repository\org\powermock\powermock-module-junit4\2.0.9\powermock-module-junit4-2.0.9.jar;C:\Users\sadhav\.m2\repository\org\powermock\powermock-module-junit4-common\2.0.9\powermock-module-junit4-common-2.0.9.jar;C:\Users\sadhav\.m2\repository\org\powermock\powermock-api-mockito2\2.0.9\powermock-api-mockito2-2.0.9.jar;C:\Users\sadhav\.m2\repository\org\powermock\powermock-api-support\2.0.9\powermock-api-support-2.0.9.jar;C:\Users\sadhav\.m2\repository\org\powermock\powermock-core\2.0.9\powermock-core-2.0.9.jar;C:\Users\sadhav\.m2\repository\org\powermock\powermock-reflect\2.0.9\powermock-reflect-2.0.9.jar;C:\Users\sadhav\.m2\repository\org\javassist\javassist\3.27.0-GA\javassist-3.27.0-GA.jar;C:\Users\sadhav\.m2\repository\net\bytebuddy\byte-buddy\1.14.10\byte-buddy-1.14.10.jar;C:\Users\sadhav\.m2\repository\net\bytebuddy\byte-buddy-agent\1.14.10\byte-buddy-agent-1.14.10.jar;C:\Users\sadhav\.m2\repository\org\jacoco\jacoco-maven-plugin\0.8.11\jacoco-maven-plugin-0.8.11.jar;C:\Users\sadhav\.m2\repository\org\codehaus\plexus\plexus-utils\3.0.24\plexus-utils-3.0.24.jar;C:\Users\sadhav\.m2\repository\org\apache\maven\shared\file-management\3.1.0\file-management-3.1.0.jar;C:\Users\sadhav\.m2\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0.jar;C:\Users\sadhav\.m2\repository\org\apache\maven\reporting\maven-reporting-api\3.0\maven-reporting-api-3.0.jar;C:\Users\sadhav\.m2\repository\org\apache\maven\doxia\doxia-sink-api\1.0\doxia-sink-api-1.0.jar;C:\Users\sadhav\.m2\repository\org\jacoco\org.jacoco.agent\0.8.11\org.jacoco.agent-0.8.11-runtime.jar;C:\Users\sadhav\.m2\repository\org\jacoco\org.jacoco.core\0.8.11\org.jacoco.core-0.8.11.jar;C:\Users\sadhav\.m2\repository\org\ow2\asm\asm\9.6\asm-9.6.jar;C:\Users\sadhav\.m2\repository\org\ow2\asm\asm-commons\9.6\asm-commons-9.6.jar;C:\Users\sadhav\.m2\repository\org\ow2\asm\asm-tree\9.6\asm-tree-9.6.jar;C:\Users\sadhav\.m2\repository\org\jacoco\org.jacoco.report\0.8.11\org.jacoco.report-0.8.11.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 @w@C:\Users\sadhav\AppData\Local\Temp\idea_working_dirs_junit.tmp @C:\Users\sadhav\AppData\Local\Temp\idea_junit.tmp -socket62993 +Process finished with exit code 0 + +
  • + +
    3.87 s
    +
    QualysWASScanBuilderTest
    +
      +
    • + +
      2.03 s
      +
      passedtest_all_mandatory_parameters_set
      +
        +
      • + OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
        SLF4J: Class path contains multiple SLF4J providers.
        SLF4J: Found provider [ch.qos.logback.classic.spi.LogbackServiceProvider@6ad11a56]
        SLF4J: Found provider [org.slf4j.simple.SimpleServiceProvider@522b2631]
        SLF4J: See https://www.slf4j.org/codes.html#multiple_bindings for an explanation.
        SLF4J: Actual provider is of type [ch.qos.logback.classic.spi.LogbackServiceProvider@6ad11a56]
        +
      • +
      +
    • +
    • + +
      39 ms
      +
      passedtest_getScanFinishedStatus
      +
    • +
    • + +
      1.49 s
      +
      passedtest_testConnection_with_invalid_credentials
      +
        +
      • + WARNING: A terminally deprecated method in java.lang.System has been called
        WARNING: System::setSecurityManager has been called by com.github.stefanbirkner.systemlambda.SystemLambda (file:/C:/Users/sadhav/.m2/repository/com/github/stefanbirkner/system-lambda/1.2.1/system-lambda-1.2.1.jar)
        WARNING: Please consider reporting this to the maintainers of com.github.stefanbirkner.systemlambda.SystemLambda
        WARNING: System::setSecurityManager will be removed in a future release
        +
      • +
      • + 17:25:03.577 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Testing connection with Qualys API Server...
        17:25:03.590 [main] INFO com.example.GitHubActionsQWas.WASClient.WASClient -- Making Request: https://example.com/qps/rest/3.0/count/was/webapp
        +
      • +
      • + java.lang.Exception: Please provide valid API and/or Proxy details. Server returned with Response code: 404
        at com.example.GitHubActionsQWas.WASClient.WASClient.testConnection(WASClient.java:66)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilder.testConnection(QualysWASScanBuilder.java:408)
        at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$yHmWyJug.invokeWithArguments(Unknown Source)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
        at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
        at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
        at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
        at org.mockito.Answers.answer(Answers.java:90)
        at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
        at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
        at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
        at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilder.testConnection(QualysWASScanBuilder.java:407)
        at com.github.stefanbirkner.systemlambda.SystemLambda.withSecurityManager(SystemLambda.java:794)
        at com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit(SystemLambda.java:404)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilderTest.test_testConnection_with_invalid_credentials(QualysWASScanBuilderTest.java:194)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
        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.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
        at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:42)
        at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
        at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:72)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
        at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
        at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
        at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
        at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
        at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
        +
      • +
      • + 17:25:05.000 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Test connection failed. Reason: Please provide valid API and/or Proxy details. Server returned with Response code: 404
        17:25:05.004 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/Qualys_Wasscan_1069358967.txt
        +
      • +
      +
    • +
    • + +
      98 ms
      +
      passedtest_launch_scan_successfully_fail_condition_configured_and_build_failed
      +
        +
      • + 17:25:05.038 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Using Qualys API Server: https://example.com
        17:25:05.097 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Qualys task - Started Launching web app scanning with WAS
        17:25:05.102 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Launching scan with 'WAIT_FOR_RESULT: true', 'POLLING_INTERVAL: 5 mins', 'TIMEOUT: 350 mins', 'CANCEL_OPTION:true', 'CANCEL_HOURS:12 hrs'
        17:25:05.102 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Scan successfully launched with scan id: 12345678 and scan name: New WAS Vulnerability Scan launched from API
        17:25:05.102 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Qualys task - Fetching scan finished status
        17:25:05.102 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Scan finished status fetched successfully
        17:25:05.103 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Qualys task - Fetching scan result
        17:25:05.104 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Please switch to WAS Classic UI and Check for report...
        17:25:05.104 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- To check scan result, please follow the url: https://example.com/portal-front/module/was/#forward=/module/was/&scan-report=12345678
        17:25:05.104 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- The vulnerabilities count by severity exceeded one of the configured threshold value :
        Configured :
        Severity 1: true
        Severity 2: true
        Severity 3: true
        Severity 4: true
        Severity 5: true
        Found :
        Severity 1; Count: 0
        Severity 2; Count: 1
        Severity 3; Count: 1
        Severity 4; Count: 0
        Severity 5; Count: 0
        17:25:05.106 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/Qualys_Wasscan_12345678.json
        17:25:05.110 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Something went wrong. Reason: null
        com.github.stefanbirkner.systemlambda.SystemLambda$CheckExitCalled: null
        at com.github.stefanbirkner.systemlambda.SystemLambda$NoExitSecurityManager.checkExit(SystemLambda.java:1419)
        at java.base/java.lang.Runtime.exit(Runtime.java:113)
        at java.base/java.lang.System.exit(System.java:1860)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilder.launchWebApplicationScan(QualysWASScanBuilder.java:285)
        at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$yHmWyJug.invokeWithArguments(Unknown Source)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
        at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
        at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
        at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
        at org.mockito.Answers.answer(Answers.java:90)
        at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
        at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
        at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
        at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilder.launchWebApplicationScan(QualysWASScanBuilder.java:221)
        at com.github.stefanbirkner.systemlambda.SystemLambda.withSecurityManager(SystemLambda.java:794)
        at com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit(SystemLambda.java:404)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilderTest.test_launch_scan_successfully_fail_condition_configured_and_build_failed(QualysWASScanBuilderTest.java:221)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
        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.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
        at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:42)
        at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
        at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:72)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
        at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
        at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
        at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
        at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
        at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
        +
      • +
      +
    • +
    • + +
      15 ms
      +
      passedtest_adds_exclude_qids_field_when_exclude_is_not_null_or_empty
      +
    • +
    • + +
      91 ms
      +
      passedtest_launch_scan_successfully_fetch_result_failure
      +
        +
      • + 17:25:05.217 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Using Qualys API Server: https://example.com
        17:25:05.217 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Qualys task - Started Launching web app scanning with WAS
        17:25:05.218 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Launching scan with 'WAIT_FOR_RESULT: true', 'POLLING_INTERVAL: 5 mins', 'TIMEOUT: 350 mins', 'CANCEL_OPTION:true', 'CANCEL_HOURS:12 hrs'
        17:25:05.218 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Scan successfully launched with scan id: 12345678 and scan name: New WAS Vulnerability Scan launched from API
        17:25:05.218 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Qualys task - Fetching scan finished status
        17:25:05.218 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Scan finished status fetched successfully
        17:25:05.218 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Qualys task - Fetching scan result
        17:25:05.218 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- API Error - Could not fetch scan result for scan id: 12345678
        17:25:05.219 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/Qualys_Wasscan_12345678.txt
        17:25:05.222 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Something went wrong. Reason: null
        com.github.stefanbirkner.systemlambda.SystemLambda$CheckExitCalled: null
        at com.github.stefanbirkner.systemlambda.SystemLambda$NoExitSecurityManager.checkExit(SystemLambda.java:1419)
        at java.base/java.lang.Runtime.exit(Runtime.java:113)
        at java.base/java.lang.System.exit(System.java:1860)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilder.launchWebApplicationScan(QualysWASScanBuilder.java:296)
        at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$yHmWyJug.invokeWithArguments(Unknown Source)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
        at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
        at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
        at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
        at org.mockito.Answers.answer(Answers.java:90)
        at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
        at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
        at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
        at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilder.launchWebApplicationScan(QualysWASScanBuilder.java:221)
        at com.github.stefanbirkner.systemlambda.SystemLambda.withSecurityManager(SystemLambda.java:794)
        at com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit(SystemLambda.java:404)
        at com.example.GitHubActionsQWas.service.QualysWASScanBuilderTest.test_launch_scan_successfully_fetch_result_failure(QualysWASScanBuilderTest.java:242)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
        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.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
        at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:42)
        at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
        at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:72)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
        at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
        at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
        at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
        at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
        at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
        +
      • +
      +
    • +
    • + +
      8 ms
      +
      passedtest_isMandatoryParametersSet
      +
    • +
    • + +
      18 ms
      +
      passedtest_assignSeverities
      +
        +
      • + 17:25:05.246 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Invalid value: 6 for SEVERITY_LEVEL. Valid values are 1 to 5
        17:25:05.248 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/Qualys_Wasscan_1069358967.txt
        +
      • +
      +
    • +
    • + +
      7 ms
      +
      passedtest_adds_fail_on_scan_error_field_when_is_fail_on_scan_error_is_true
      +
    • +
    • + +
      35 ms
      +
      passedtest_returns_json_object_with_valid_scan_id
      +
    • +
    • + +
      17 ms
      +
      passedtest_evaluateFailurePolicy
      +
    • +
    • + +
      14 ms
      +
      passedtest_validateParameters
      +
        +
      • + 17:25:05.318 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Invalid value for AUTH_RECORD. Valid values are none, useDefault, other
        17:25:05.319 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/Qualys_Wasscan_1069358967.txt
        17:25:05.324 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Invalid value for OPTION_PROFILE. Valid values are useDefault, other
        17:25:05.326 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/Qualys_Wasscan_1069358967.txt
        +
      • +
      +
    • +
    • + +
      6 ms
      +
      passedtest_adds_severities_field_when_is_fail_on_severe_vulns_is_true
      +
    • +
    • + +
      5 ms
      +
      passedtest_returns_non_null_json_object_with_fail_conditions_field
      +
    • +
    • + +
      9 ms
      +
      passedtest_constructor_assigns_values
      +
    • +
    +
  • +
  • + +
    9.13 s
    +
    QualysWASScanStatusServiceTest
    +
      +
    • + +
      1.05 s
      +
      passedtest_fetchScanStatus_waitsForInterval
      +
        +
      • + 17:25:05.386 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Waiting for 0 minute(s) before making next attempt for scanResult of scanId:12345...
        +
      • +
      +
    • +
    • + +
      2.01 s
      +
      passedtest_fetchScanStatus_timeout
      +
        +
      • + 17:25:06.406 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Waiting for 0 minute(s) before making next attempt for scanResult of scanId:12345...
        17:25:08.409 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Failed to get scan result; timeout of 0 minutes reached.
        17:25:08.409 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Please switch to WAS Classic UI and Check for report...
        17:25:08.409 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- To check scan result, please follow the url: https://example.com/portal-front/module/was/#forward=/module/was/&scan-report=12345
        17:25:08.412 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/Qualys_Wasscan_12345.txt
        17:25:08.414 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Exception: null
        +
      • +
      +
    • +
    • + passedtest_fetchScanStatus_returnsScanStatusWhenScanIsFinished +
    • +
    • + +
      1.01 s
      +
      passedtest_fetchScanStatus_waitsForScanToFinishBeforeReturningStatus
      +
        +
      • + 17:25:08.419 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Waiting for 0 minute(s) before making next attempt for scanResult of scanId:123...
        +
      • +
      +
    • +
    • + +
      1.01 s
      +
      passedtest_fetchScanStatus_returnsScanStatusWithinTimeoutPeriod
      +
        +
      • + 17:25:09.434 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Waiting for 0 minute(s) before making next attempt for scanResult of scanId:123...
        +
      • +
      +
    • +
    • + +
      1.01 s
      +
      passedtest_fetchScanStatus_waitInterval
      +
        +
      • + 17:25:10.447 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Waiting for 0 minute(s) before making next attempt for scanResult of scanId:12345...
        +
      • +
      +
    • +
    • + +
      1.01 s
      +
      passedtest_fetchScanStatus_waitsForIntervalBeforeNextAttempt
      +
        +
      • + 17:25:11.460 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Waiting for 0 minute(s) before making next attempt for scanResult of scanId:123...
        +
      • +
      +
    • +
    • + +
      1 ms
      +
      passedtest_fetchScanStatus_logsErrorMessageWhenScanResultIsNotJSONObject
      +
    • +
    • + +
      2.02 s
      +
      passedtest_fetchScanStatus_logsErrorMessageWhenScanStatusNotAvailableWithinTimeoutPeriod
      +
        +
      • + 17:25:12.479 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Waiting for 0 minute(s) before making next attempt for scanResult of scanId:12345...
        17:25:14.484 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Failed to get scan result; timeout of 0 minutes reached.
        17:25:14.485 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Please switch to WAS Classic UI and Check for report...
        17:25:14.485 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- To check scan result, please follow the url: https://example.com/portal-front/module/was/#forward=/module/was/&scan-report=12345
        17:25:14.487 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/Qualys_Wasscan_12345.txt
        17:25:14.491 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanStatusService -- Exception: null
        +
      • +
      +
    • +
    +
  • +
  • + +
    3 ms
    +
    HelperTest
    +
      +
    • + passedtest_setTimeoutInMinutes_default_timeout_when_timeout_is_null_or_empty +
    • +
    • + +
      3 ms
      +
      passedtest_dumpDataIntoFile_creates_directory_and_writes_data_to_file_successfully
      +
        +
      • + 17:25:14.495 [main] INFO com.example.GitHubActionsQWas.util.Helper -- Result artifact uploaded at location: outputs/test.txt
        +
      • +
      +
    • +
    • + passedtest_calculate_timeout_in_minutes_when_timeout_is_in_regex_form +
    • +
    • + passedtest_setTimeoutInMinutes_invalid_timeout_1 +
        +
      • + 17:25:14.498 [main] ERROR com.example.GitHubActionsQWas.util.Helper -- Invalid timeout time value. Cannot parse -For input string: "invalid"
        17:25:14.498 [main] ERROR com.example.GitHubActionsQWas.util.Helper -- Using default period of 60 minutes for timeout.
        +
      • +
      +
    • +
    • + passedtest_setTimeoutInMinutes_invalid_timeout_2 +
        +
      • + 17:25:14.498 [main] ERROR com.example.GitHubActionsQWas.util.Helper -- Invalid vulnsTimeout time value. Cannot parse -For input string: "invalid_timeout"
        17:25:14.498 [main] ERROR com.example.GitHubActionsQWas.util.Helper -- Using default period of 60*24 minutes for vulnsTimeout.
        +
      • +
      +
    • +
    +
  • +
  • + +
    34 ms
    +
    QualysWASScanServiceTest
    +
      +
    • + +
      31 ms
      +
      passedtest_launch_scan_with_valid_parameters_returns_scan_id()
      +
        +
      • + 17:25:14.623 [main] INFO com.example.GitHubActionsQWas.service.QualysWASScanBuilder -- Calling Launch Scan API with Payload: {"ServiceRequest":{"data":{"WasScan":{"type":"scanType","name":"scanName_2024-02-02-17-25","target":{"webApp":{"id":"webAppId"},"webAppAuthRecord":{"isDefault":true}}}}}}
        +
      • +
      +
    • +
    • + +
      3 ms
      +
      passedtest_instantiation_with_valid_parameters()
      +
    • +
    +
  • +
  • + +
    2 ms
    +
    TestModel
    +
      +
    • + +
      2 ms
      +
      passedprojectSetUp()
      +
    • +
    +
  • +
  • + +
    1.13 s
    +
    WASClientTest
    +
      +
    • + +
      4 ms
      +
      passedtest_response_code_zero()
      +
        +
      • + java.lang.NullPointerException: Cannot invoke "com.google.gson.JsonObject.has(String)" because "responseObject" is null
        at com.example.GitHubActionsQWas.WASClient.WASClient.testConnection(WASClient.java:73)
        at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$yHmWyJug.invokeWithArguments(Unknown Source)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
        at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
        at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
        at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
        at org.mockito.Answers.answer(Answers.java:90)
        at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
        at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
        at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
        at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
        at com.example.GitHubActionsQWas.WASClient.WASClient.testConnection(WASClient.java:63)
        at com.example.GitHubActionsQWas.WASClient.WASClientTest.test_response_code_zero(WASClientTest.java:105)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
        at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
        at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
        at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
        at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
        at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
        at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
        at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
        +
      • +
      +
    • +
    • + +
      1.08 s
      +
      passedtest_returns_qualyswasresponse_object()
      +
        +
      • + 17:25:14.657 [main] INFO com.example.GitHubActionsQWas.WASClient.WASClient -- Making Request: https://example.com/qps/rest/3.0/launch/was/wasscan
        17:25:15.739 [main] INFO com.example.GitHubActionsQWas.WASClient.WASClient -- Server returned with ResponseCode: 404
        +
      • +
      +
    • +
    • + +
      22 ms
      +
      passedtest_returns_error_if_scan_status_finished_and_results_status_not_finished()
      +
        +
      • + 17:25:15.763 [main] INFO com.example.GitHubActionsQWas.WASClient.WASClient -- Scan Status: finished. Reason: failed
        +
      • +
      +
    • +
    • + +
      2 ms
      +
      passedtest_returns_null_if_scan_status_finished_and_results_status_finished()
      +
        +
      • + 17:25:15.766 [main] INFO com.example.GitHubActionsQWas.WASClient.WASClient -- Scan Status: finished
        +
      • +
      +
    • +
    • + +
      1 ms
      +
      passedtest_returns_scan_status_if_scan_status_error_or_canceled()
      +
        +
      • + 17:25:15.769 [main] INFO com.example.GitHubActionsQWas.WASClient.WASClient -- Scan Status: error. Reason: Error.
        +
      • +
      +
    • +
    • + +
      4 ms
      +
      passedtest_responseCode_not_success()
      +
        +
      • + java.lang.Exception: [error] Error message, Error resolution
        at com.example.GitHubActionsQWas.WASClient.WASClient.testConnection(WASClient.java:82)
        at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$yHmWyJug.invokeWithArguments(Unknown Source)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
        at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
        at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
        at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
        at org.mockito.Answers.answer(Answers.java:90)
        at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
        at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
        at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
        at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
        at com.example.GitHubActionsQWas.WASClient.WASClient.testConnection(WASClient.java:63)
        at com.example.GitHubActionsQWas.WASClient.WASClientTest.lambda$test_responseCode_not_success$0(WASClientTest.java:133)
        at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:53)
        at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:35)
        at org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3083)
        at com.example.GitHubActionsQWas.WASClient.WASClientTest.test_responseCode_not_success(WASClientTest.java:132)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
        at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
        at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
        at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
        at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
        at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
        at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
        at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
        +
      • +
      +
    • +
    • + +
      1 ms
      +
      passedtest_valid_api_and_proxy_details()
      +
    • +
    • + +
      6 ms
      +
      passedtest_response_code_not_between_200_and_299_with_success_response_code()
      +
        +
      • + java.lang.Exception: HTTP Response code from server: 400.
        at com.example.GitHubActionsQWas.WASClient.WASClient.testConnection(WASClient.java:74)
        at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$yHmWyJug.invokeWithArguments(Unknown Source)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
        at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
        at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
        at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
        at org.mockito.Answers.answer(Answers.java:90)
        at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
        at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
        at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
        at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
        at com.example.GitHubActionsQWas.WASClient.WASClient.testConnection(WASClient.java:63)
        at com.example.GitHubActionsQWas.WASClient.WASClientTest.test_response_code_not_between_200_and_299_with_success_response_code(WASClientTest.java:87)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
        at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
        at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
        at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
        at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
        at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
        at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
        at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
        +
      • +
      +
    • +
    • + +
      2 ms
      +
      passedtest_response_code_between_200_and_299()
      +
    • +
    • + +
      4 ms
      +
      passedtest_returns_null_if_scan_status_not_error_canceled_or_finished()
      +
        +
      • + 17:25:15.790 [main] ERROR com.example.GitHubActionsQWas.WASClient.WASClient -- Error getting scan status: Cannot invoke "com.google.gson.JsonArray.get(int)" because "dataArr" is null
        java.lang.NullPointerException: Cannot invoke "com.google.gson.JsonArray.get(int)" because "dataArr" is null
        at com.example.GitHubActionsQWas.WASClient.WASClient.getScanFinishedStatus(WASClient.java:110)
        at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$yHmWyJug.invokeWithArguments(Unknown Source)
        at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
        at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
        at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
        at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
        at org.mockito.Answers.answer(Answers.java:90)
        at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
        at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
        at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
        at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
        at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
        at com.example.GitHubActionsQWas.WASClient.WASClient.getScanFinishedStatus(WASClient.java:96)
        at com.example.GitHubActionsQWas.WASClient.WASClientTest.test_returns_null_if_scan_status_not_error_canceled_or_finished(WASClientTest.java:150)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
        at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
        at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
        at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
        at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
        at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
        at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
        at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
        at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
        +
      • +
      +
    • +
    +
  • +
  • + +
    57 ms
    +
    QualysWASScanResultParserTest
    +
      +
    • + +
      1 ms
      +
      passedtest_correctly_evaluates_severity()
      +
    • +
    • + +
      17 ms
      +
      passedtest_success_with_vulnerabilities()
      +
        +
      • + 17:25:15.813 [main] ERROR com.example.GitHubActionsQWas.service.QualysWASScanResultParser -- something went wrong - Reason: Cannot invoke "com.google.gson.JsonElement.getAsInt()" because the return value of "com.google.gson.JsonObject.get(String)" is null
        +
      • +
      +
    • +
    • + +
      3 ms
      +
      passedtest_instantiation_with_json_criteria_and_wasclient_object()
      +
    • +
    • + +
      33 ms
      +
      passedtest_returns_json_object_with_valid_scan_id()
      +
    • +
    • + passedtest_returns_json_object() +
    • +
    • + +
      3 ms
      +
      passedtest_instantiation_with_empty_json_criteria_and_wasclient_object()
      +
    • +
    +
  • +
+
+
+ + + diff --git a/properties.yaml b/properties.yaml new file mode 100644 index 0000000..344e3df --- /dev/null +++ b/properties.yaml @@ -0,0 +1,27 @@ +### Tools ##### +maven: apache-maven-3.9.4 +jdk: JDK_17 + +### Source code properties ### +#signtools-checkout: true + +#### Project properties ### +project-name: github-was-action +image-path: qualys/qint/github-was-action +artifacts-to-archive: target/github-was-action*.jar +is-instrumentation-enabled: false + +#build-additional-args: -Drelease.number="${BUILD_ID}" +build-additional-args: -DskipTests=true + +# BlackDuck properties +is-blackduck-enabled: true +blackduck-project-name: apiintegration_github-was-action +blackduck-artifacts-to-scan: / + +## Notification Properties ## +email-notifications: +teams-webhook-url: https://qualys.webhook.office.com/webhookb2/fb013c9c-125f-4fed-940f-0403fcaceb2e@81a9ef9a-9a98-4b00-886a-895a603bc029/IncomingWebhook/1d8267aff251406ba66d2f0b8cd9cc86/8769138b-5890-4644-ab24-5826018693e4 + +is-coverity-enabled : true +cov-project-name: QINT diff --git a/run_service.sh b/run_service.sh new file mode 100644 index 0000000..432db74 --- /dev/null +++ b/run_service.sh @@ -0,0 +1,26 @@ +#!/busybox/sh + +HOME="/home/app" + +: ${SERVICE_NAME:="github-was-action"} +: ${SPRING_ACTIVE_PROFILE:="override"} +: ${LOGS_DIR:="/var/log/app/"} + +JAVAOPTS="-server \ + -Dlogs-dir=$LOGS_DIR \ + + -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE \ + + -Dspring.application.name=$SERVICE_NAME \ + + -XX:+UseG1GC \ + -XX:MaxGCPauseMillis=200 \ + -XX:+ScavengeBeforeFullGC \ + -Dio.netty.leakDetectionLevel=simple \ + -XX:+DisableExplicitGC \ + -XX:+AlwaysPreTouch \ + -Xss1m" + +echo $JAVAOPTS + +exec java $JAVAOPTS -jar $HOME/github-was-action.jar \ No newline at end of file diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..54a95c5 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,42 @@ +# must be unique in a given SonarQube instance +sonar.projectKey=com.qualys.qint:github-was-action + +# --- optional properties --- + +# defaults to project key +sonar.projectName=github-was-action +# defaults to 'not provided' +#sonar.projectVersion=1.0 + +# Path is relative to the sonar-project.properties file. Defaults to . +#sonar.sources=. + +#sonar.exclusions=/src/**/* +# Encoding of the source code. Default is default system encoding +#sonar.sourceEncoding=UTF-8 + +#sonar.projectBaseDir= + +#sonar.working.directory= + +# sonar.java.source= + +# sonar.java.target= + +# sonar.tests= + +# sonar.java.binaries= + +# sonar.java.libraries= + +# sonar.java.test.binaries= + +# sonar.java.test.libraries= + +# sonar.junit.reportPaths= + +# sonar.groovy.binaries= + +# sonar.jacoco.reportPaths= + +# sonar.groovy.jacoco.reportPath= \ No newline at end of file diff --git a/src/main/java/com/example/GitHubActionsQWas/WASAuth/WASAuth.java b/src/main/java/com/example/GitHubActionsQWas/WASAuth/WASAuth.java index 7582a8a..31eced1 100644 --- a/src/main/java/com/example/GitHubActionsQWas/WASAuth/WASAuth.java +++ b/src/main/java/com/example/GitHubActionsQWas/WASAuth/WASAuth.java @@ -1,57 +1,76 @@ package com.example.GitHubActionsQWas.WASAuth; +import ch.qos.logback.core.util.StringUtil; +import com.example.GitHubActionsQWas.WASClient.QualysWASResponse; +import com.example.GitHubActionsQWas.WASClient.WASBaseClient; +import com.example.GitHubActionsQWas.WASClient.WASClient; +import com.example.GitHubActionsQWas.util.ApiServerUrl; +import lombok.Getter; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +@Getter public class WASAuth { private String server; private String username; private String password; + private String clientId; + private String clientSecret; private String authKey; + private String authType; + private String platform; private String proxyServer; private String proxyUsername; private String proxyPassword; private int proxyPort; + private final Logger logger = LoggerFactory.getLogger(WASClient.class); - public WASAuth() { - } - - public WASAuth(String oauthKey) { - this.authKey = oauthKey; - } - - public String getServer() { - return server; - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; + public WASAuth(String platform) { + this.platform = platform; } - public String getAuthKey() { - return authKey; + public void setWasCredentials(String server, String username, String password, String authType) { + this.server = server; + this.username = username; + this.password = password; + this.authType = authType; } - public String getProxyServer() { - return proxyServer; + public void setWasOAuthCredentials(String server, String clientId, String clientSecret, String authType) { + this.server = server; + this.clientId = clientId; + this.clientSecret = clientSecret; + this.authType = authType; } - public String getProxyUsername() { - return proxyUsername; - } + public void setOAuthKey() throws Exception { + WASClient client = new WASClient(this); + CloseableHttpClient httpClient = client.getCloseableHttpClient(); - public String getProxyPassword() { - return proxyPassword; - } + URL url = new URL(server + "/auth/oidc"); + logger.info("Making Request: " + url); - public int getProxyPort() { - return proxyPort; - } + HttpPost postRequest = new HttpPost(url.toString()); + postRequest.addHeader("Content-Type", "application/x-www-form-urlencoded"); + postRequest.addHeader("clientId", this.clientId); + postRequest.addHeader("clientSecret", this.clientSecret); - public void setWasCredentials(String server, String username, String password) { - this.server = server; - this.username = username; - this.password = password; + CloseableHttpResponse httpResponse = httpClient.execute(postRequest); + logger.info("Server returned with ResponseCode: " + httpResponse.getStatusLine().getStatusCode()); + this.authKey = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); + logger.warn("OAUTH Key is generated successfully..."); + if (StringUtil.notNullNorEmpty(this.platform)) { + this.server = ApiServerUrl.getByKey(platform).getUrl(); + } } } diff --git a/src/main/java/com/example/GitHubActionsQWas/WASClient/WASClient.java b/src/main/java/com/example/GitHubActionsQWas/WASClient/WASClient.java index b4e78c7..b4f35ee 100644 --- a/src/main/java/com/example/GitHubActionsQWas/WASClient/WASClient.java +++ b/src/main/java/com/example/GitHubActionsQWas/WASClient/WASClient.java @@ -1,6 +1,7 @@ package com.example.GitHubActionsQWas.WASClient; import com.example.GitHubActionsQWas.WASAuth.WASAuth; +import com.example.GitHubActionsQWas.constants.Constants; import com.example.GitHubActionsQWas.util.Helper; import com.google.gson.*; import org.apache.http.HttpEntity; @@ -21,6 +22,8 @@ import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; import java.util.Base64; import java.util.HashMap; @@ -77,6 +80,10 @@ public QualysWASResponse getReportStatus(String reportId) { return this.get(this.apiMap.get("getReportStatus") + reportId); } + public CloseableHttpClient getCloseableHttpClient() throws NoSuchAlgorithmException, KeyManagementException { + return this.getHttpClient(); + } + private void download(String apiPath) { CloseableHttpClient httpClient = null; @@ -86,7 +93,12 @@ private void download(String apiPath) { httpClient = this.getHttpClient(); HttpGet getRequest = new HttpGet(url.toString()); - getRequest.addHeader("Authorization", "Basic " + this.getBasicAuthHeader()); + if (Constants.BASIC.equals(auth.getAuthType())) { + getRequest.addHeader("Authorization", "Basic " + this.getBasicAuthHeader()); + } else if (Constants.OAUTH.equals(auth.getAuthType())) { + getRequest.addHeader("Authorization", "Bearer " + auth.getAuthKey()); + getRequest.addHeader("request-source", "gateway"); + } CloseableHttpResponse response = httpClient.execute(getRequest); logger.debug("Server returned with ResponseCode: {}", response.getStatusLine().getStatusCode()); @@ -201,7 +213,12 @@ private QualysWASResponse get(String apiPath) { HttpGet getRequest = new HttpGet(url.toString()); getRequest.addHeader("accept", "application/json"); - getRequest.addHeader("Authorization", "Basic " + this.getBasicAuthHeader()); + if (Constants.BASIC.equals(auth.getAuthType())) { + getRequest.addHeader("Authorization", "Basic " + this.getBasicAuthHeader()); + } else if (Constants.OAUTH.equals(auth.getAuthType())) { + getRequest.addHeader("Authorization", "Bearer " + auth.getAuthKey()); + getRequest.addHeader("request-source", "gateway"); + } CloseableHttpResponse response = httpClient.execute(getRequest); apiResponse.responseCode = response.getStatusLine().getStatusCode(); logger.debug("Server returned with ResponseCode: " + apiResponse.responseCode); @@ -245,7 +262,12 @@ private QualysWASResponse post(String apiPath, JsonObject requestData) { HttpPost postRequest = new HttpPost(url.toString()); postRequest.addHeader("accept", "application/json"); - postRequest.addHeader("Authorization", "Basic " + this.getBasicAuthHeader()); + if (Constants.BASIC.equals(auth.getAuthType())) { + postRequest.addHeader("Authorization", "Basic " + this.getBasicAuthHeader()); + } else if (Constants.OAUTH.equals(auth.getAuthType())) { + postRequest.addHeader("Authorization", "Bearer " + auth.getAuthKey()); + postRequest.addHeader("request-source", "gateway"); + } Gson gson = new Gson(); if (requestData != null) { postRequest.addHeader("Content-Type", "application/json"); diff --git a/src/main/java/com/example/GitHubActionsQWas/constants/Constants.java b/src/main/java/com/example/GitHubActionsQWas/constants/Constants.java index c5f78c9..4eafb7e 100644 --- a/src/main/java/com/example/GitHubActionsQWas/constants/Constants.java +++ b/src/main/java/com/example/GitHubActionsQWas/constants/Constants.java @@ -18,5 +18,6 @@ public class Constants { public static final String COMPLETE = "COMPLETE"; public static final String UNKNOWN = "UNKNOWN"; public static final String PDF_FORMAT = "PDF"; - + public static final String BASIC = "BASIC"; + public static final String OAUTH = "OAUTH"; } diff --git a/src/main/java/com/example/GitHubActionsQWas/service/QualysWASScanBuilder.java b/src/main/java/com/example/GitHubActionsQWas/service/QualysWASScanBuilder.java index 3257c73..cc19929 100644 --- a/src/main/java/com/example/GitHubActionsQWas/service/QualysWASScanBuilder.java +++ b/src/main/java/com/example/GitHubActionsQWas/service/QualysWASScanBuilder.java @@ -1,10 +1,14 @@ package com.example.GitHubActionsQWas.service; +import ch.qos.logback.core.util.StringUtil; import com.example.GitHubActionsQWas.WASAuth.WASAuth; import com.example.GitHubActionsQWas.WASClient.QualysWASResponse; import com.example.GitHubActionsQWas.WASClient.WASClient; import com.example.GitHubActionsQWas.constants.Constants; +import com.example.GitHubActionsQWas.util.ApiGatewayUrl; +import com.example.GitHubActionsQWas.util.ApiServerUrl; import com.example.GitHubActionsQWas.util.Helper; +import com.example.GitHubActionsQWas.util.PortalUrl; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -21,6 +25,10 @@ import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -36,6 +44,8 @@ public class QualysWASScanBuilder { private Environment environment; private String apiServer; private String portalServer; + private String gatewayServer; + private String platform; private String qualysUsername; private String qualysPasssword; private boolean useProxy = false; @@ -76,11 +86,14 @@ public class QualysWASScanBuilder { private boolean waitForResult; private WASClient client; private String fileType; + private String authType; + private String clientId; + private String clientSecret; + private String qualysIdentificationUrl; public QualysWASScanBuilder(Environment environment) { try { this.environment = environment; - this.apiServer = environment.getProperty("API_SERVER", ""); this.qualysUsername = environment.getProperty("QUALYS_USERNAME", ""); this.qualysPasssword = environment.getProperty("QUALYS_PASSWORD", ""); this.useProxy = environment.getProperty("USE_PROXY", Boolean.class, false); @@ -107,6 +120,21 @@ public QualysWASScanBuilder(Environment environment) { this.interval = environment.getProperty("INTERVAL", Integer.class, 1); this.timeout = environment.getProperty("TIMEOUT", Integer.class, (60 * 5) + 50); this.fileType = environment.getProperty("FILE_TYPE", "PDF"); + this.authType = environment.getProperty("AUTH_TYPE", ""); + this.clientId = environment.getProperty("CLIENT_ID", ""); + this.clientSecret = environment.getProperty("CLIENT_SECRET", ""); + this.platform = environment.getProperty("PLATFORM", ""); + this.qualysIdentificationUrl = "https://www.qualys.com/platform-identification"; + + if (StringUtil.notNullNorEmpty(platform)) { + this.apiServer = ApiServerUrl.getByKey(platform).getUrl(); + this.portalServer = PortalUrl.getByKey(platform).getUrl(); + this.gatewayServer = ApiGatewayUrl.getByKey(platform).getUrl(); + } else { + throw new Exception("PLATFORM not specified, Please configure it and try again. Please visit following url to identify correct platform: " + + qualysIdentificationUrl); + } + this.severity1Limit = 0; this.severity2Limit = 0; this.severity3Limit = 0; @@ -120,7 +148,7 @@ public QualysWASScanBuilder(Environment environment) { assignSeverities(); } } catch (Exception ex) { - logger.error("Something went wrong. Reason: " + ex.getCause()); + logger.error("Something went wrong. Reason: " + ex.getMessage()); System.exit(1); } } @@ -173,10 +201,14 @@ protected void assignSeverities() { } } - protected void initWASClient() { - WASAuth auth = new WASAuth(); - auth.setWasCredentials(apiServer, qualysUsername, qualysPasssword); - + protected void initWASClient() throws Exception { + WASAuth auth = new WASAuth(this.platform); + if (authType.equals(Constants.BASIC)) { + auth.setWasCredentials(apiServer, qualysUsername, qualysPasssword, Constants.BASIC); + } else { + auth.setWasOAuthCredentials(gatewayServer, clientId, clientSecret, Constants.OAUTH); + auth.setOAuthKey(); + } // if (useProxy) { // auth.setProxyCredentials(proxyServer, proxyPort, proxyUsername, proxyPassword); // } @@ -226,8 +258,6 @@ protected JsonObject getCriteriaAsJsonObject() { * */ public void launchWebApplicationScan() { - portalServer = apiServer.replace("api", "guard"); - logger.info("Using Qualys API Server: " + apiServer); try { @@ -410,7 +440,26 @@ private JsonElement getEvaluationResult(JsonObject result) { } public boolean isMandatoryParametersSet() { - return !(this.apiServer == null || this.apiServer.isEmpty() || this.qualysUsername == null || this.qualysUsername.isEmpty() || this.qualysPasssword == null || this.qualysPasssword.isEmpty() || webAppId == null || webAppId.isEmpty() || scanName == null || scanName.isEmpty() || scanType == null || scanType.isEmpty()); + boolean isMandatoryParametersSet = !(this.apiServer == null || this.apiServer.isEmpty() || + this.webAppId == null || this.webAppId.isEmpty() || + this.scanName == null || this.scanName.isEmpty() || + this.scanType == null || this.scanType.isEmpty() || + this.platform == null || this.platform.isEmpty() || + this.authType == null || this.authType.isEmpty()); + + if (authType != null && !authType.isEmpty()) { + if (authType.equals(Constants.OAUTH) && isMandatoryParametersSet) { + isMandatoryParametersSet = !(clientId == null || clientId.isEmpty() || + clientSecret == null || clientSecret.isEmpty()); + if (!isMandatoryParametersSet) logger.error("Client ID or Client Secret is not set for Auth-Type: {}", authType); + } else if (authType.equals(Constants.BASIC) && isMandatoryParametersSet) { + isMandatoryParametersSet = !(qualysUsername == null || qualysUsername.isEmpty() || + qualysPasssword == null || qualysPasssword.isEmpty()); + if (!isMandatoryParametersSet) logger.error("Username or Password is not set for Auth-Type: {}", authType); + } + } + + return isMandatoryParametersSet; } protected boolean testConnection() { diff --git a/src/main/java/com/example/GitHubActionsQWas/util/ApiGatewayUrl.java b/src/main/java/com/example/GitHubActionsQWas/util/ApiGatewayUrl.java new file mode 100644 index 0000000..5a7ade3 --- /dev/null +++ b/src/main/java/com/example/GitHubActionsQWas/util/ApiGatewayUrl.java @@ -0,0 +1,38 @@ +package com.example.GitHubActionsQWas.util; + +import lombok.Getter; + +@Getter +public enum ApiGatewayUrl { + US1 ("https://gateway.qualys.com"), + US2 ("https://gateway.qg2.apps.qualys.com"), + US3 ("https://gateway.qg3.apps.qualys.com"), + US4 ("https://gateway.qg4.apps.qualys.com"), + EU1 ("https://gateway.qualys.eu"), + EU2 ("https://gateway.qg2.apps.qualys.eu"), + EU3 ("https://gateway.qg3.apps.qualys.eu"), + IN1 ("https://gateway.qg1.apps.qualys.in"), + CA1 ("https://gateway.qg1.apps.qualys.ca"), + AE1 ("https://gateway.qg1.apps.qualys.ae"), + UK1 ("https://gateway.qg1.apps.qualys.co.uk"), + AU1 ("https://gateway.qg1.apps.qualys.com.au"), + KSA1 ("https://gateway.qg1.apps.qualysksa.com") + ; + + private final String url; + + ApiGatewayUrl(String url) { + this.url = url; + } + + public static ApiGatewayUrl getByKey(String key) throws Exception { + try { + return valueOf(key.toUpperCase()); + } catch (Exception e) { + String exception = String.format("Exception: You have entered invalid platform {%s}, Please visit following url to identify correct platform - %s", + key.toUpperCase(), + "https://www.qualys.com/platform-identification "); + throw new Exception(exception); + } + } +} diff --git a/src/main/java/com/example/GitHubActionsQWas/util/ApiServerUrl.java b/src/main/java/com/example/GitHubActionsQWas/util/ApiServerUrl.java new file mode 100644 index 0000000..8634a5a --- /dev/null +++ b/src/main/java/com/example/GitHubActionsQWas/util/ApiServerUrl.java @@ -0,0 +1,38 @@ +package com.example.GitHubActionsQWas.util; + +import lombok.Getter; + +@Getter +public enum ApiServerUrl { + US1 ("https://qualysapi.qualys.com"), + US2 ("https://qualysapi.qg2.apps.qualys.com"), + US3 ("https://qualysapi.qg3.apps.qualys.com"), + US4 ("https://qualysapi.qg4.apps.qualys.com"), + EU1 ("https://qualysapi.qualys.eu"), + EU2 ("https://qualysapi.qg2.apps.qualys.eu"), + EU3 ("https://qualysapi.qg3.apps.qualys.eu"), + IN1 ("https://qualysapi.qg1.apps.qualys.in"), + CA1 ("https://qualysapi.qg1.apps.qualys.ca"), + AE1 ("https://qualysapi.qg1.apps.qualys.ae"), + UK1 ("https://qualysapi.qg1.apps.qualys.co.uk"), + AU1 ("https://qualysapi.qg1.apps.qualys.com.au"), + KSA1 ("https://qualysapi.qg1.apps.qualysksa.com") + ; + + private final String url; + + ApiServerUrl(String url) { + this.url = url; + } + + public static ApiServerUrl getByKey(String key) throws Exception { + try { + return valueOf(key.toUpperCase()); + } catch (IllegalArgumentException e) { + String exception = String.format("Exception: You have entered invalid platform {%s}, Please visit following url to identify correct platform - %s", + key.toUpperCase(), + "https://www.qualys.com/platform-identification "); + throw new Exception(exception); + } + } +} diff --git a/src/main/java/com/example/GitHubActionsQWas/util/PortalUrl.java b/src/main/java/com/example/GitHubActionsQWas/util/PortalUrl.java new file mode 100644 index 0000000..e3fe66e --- /dev/null +++ b/src/main/java/com/example/GitHubActionsQWas/util/PortalUrl.java @@ -0,0 +1,38 @@ +package com.example.GitHubActionsQWas.util; + +import lombok.Getter; + +@Getter +public enum PortalUrl { + US1 ("https://qualysguard.qualys.com"), + US2 ("https://qualysguard.qg2.apps.qualys.com"), + US3 ("https://qualysguard.qg3.apps.qualys.com"), + US4 ("https://qualysguard.qg4.apps.qualys.com"), + EU1 ("https://qualysguard.qualys.eu"), + EU2 ("https://qualysguard.qg2.apps.qualys.eu"), + EU3 ("https://qualysguard.qg3.apps.qualys.eu"), + IN1 ("https://qualysguard.qg1.apps.qualys.in"), + CA1 ("https://qualysguard.qg1.apps.qualys.ca"), + AE1 ("https://qualysguard.qg1.apps.qualys.ae"), + UK1 ("https://qualysguard.qg1.apps.qualys.co.uk"), + AU1 ("https://qualysguard.qg1.apps.qualys.com.au"), + KSA1 ("https://qualysguard.qg1.apps.qualysksa.com") + ; + + private final String url; + + PortalUrl(String url) { + this.url = url; + } + + public static PortalUrl getByKey(String key) throws Exception { + try { + return valueOf(key.toUpperCase()); + } catch (Exception e) { + String exception = String.format("Exception: You have entered invalid platform {%s}, Please visit following url to identify correct platform - %s", + key.toUpperCase(), + "https://www.qualys.com/platform-identification "); + throw new Exception(exception); + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index af8677e..4a4feb6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1 @@ -logging.level.com.example.GitHubActionsQWas=info \ No newline at end of file +logging.level.com.example.GitHubActionsQWas=info diff --git a/src/test/java/com/example/GitHubActionsQWas/WASClient/WASClientTest.java b/src/test/java/com/example/GitHubActionsQWas/WASClient/WASClientTest.java new file mode 100644 index 0000000..3038fd0 --- /dev/null +++ b/src/test/java/com/example/GitHubActionsQWas/WASClient/WASClientTest.java @@ -0,0 +1,252 @@ +package com.example.GitHubActionsQWas.WASClient; + +import com.example.GitHubActionsQWas.WASAuth.WASAuth; +import com.example.GitHubActionsQWas.constants.Constants; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class WASClientTest { + + @Test + public void test_valid_api_and_proxy_details() { + WASAuth auth = mock(WASAuth.class); + WASClient wasClient = mock(WASClient.class); + when(auth.getServer()).thenReturn("server"); + when(auth.getUsername()).thenReturn("username"); + when(auth.getPassword()).thenReturn("password"); + when(auth.getProxyServer()).thenReturn("proxyServer"); + when(auth.getProxyPort()).thenReturn(8080); + when(auth.getProxyUsername()).thenReturn("proxyUsername"); + when(auth.getProxyPassword()).thenReturn("proxyPassword"); + + QualysWASResponse response = new QualysWASResponse(); + response.errored = false; + + when(wasClient.getWebAppCount()).thenReturn(response); + + try { + wasClient.testConnection(); + } catch (Exception e) { + fail("Exception thrown: " + e.getMessage()); + } + } + + @Test + public void test_response_code_between_200_and_299() { + WASAuth auth = mock(WASAuth.class); + WASClient wasClient = mock(WASClient.class); + when(auth.getServer()).thenReturn("server"); + when(auth.getUsername()).thenReturn("username"); + when(auth.getPassword()).thenReturn("password"); + when(auth.getProxyServer()).thenReturn("proxyServer"); + when(auth.getProxyPort()).thenReturn(8080); + when(auth.getProxyUsername()).thenReturn("proxyUsername"); + when(auth.getProxyPassword()).thenReturn("proxyPassword"); + + QualysWASResponse response = new QualysWASResponse(); + response.errored = false; + response.responseCode = 200; + + when(wasClient.getWebAppCount()).thenReturn(response); + + try { + wasClient.testConnection(); + } catch (Exception e) { + fail("Exception thrown: " + e.getMessage()); + } + } + + @Test + public void test_response_code_not_between_200_and_299_with_success_response_code() { + WASAuth auth = mock(WASAuth.class); + WASClient wasClient = spy(new WASClient(auth)); + when(auth.getServer()).thenReturn("server"); + when(auth.getUsername()).thenReturn("username"); + when(auth.getPassword()).thenReturn("password"); + when(auth.getProxyServer()).thenReturn("proxyServer"); + when(auth.getProxyPort()).thenReturn(8080); + when(auth.getProxyUsername()).thenReturn("proxyUsername"); + when(auth.getProxyPassword()).thenReturn("proxyPassword"); + + QualysWASResponse response = new QualysWASResponse(); + response.errored = false; + response.responseCode = 400; + + JsonObject responseObject = new JsonObject(); + responseObject.addProperty("responseCode", "success"); + + response.response = responseObject; + + when(wasClient.getWebAppCount()).thenReturn(response); + + try { + wasClient.testConnection(); + } catch (Exception e) { + assertEquals("HTTP Response code from server: 400. ", e.getMessage()); + } + } + + @Test + public void test_response_code_zero() { + WASClient client = spy(new WASClient(new WASAuth(""))); + when(client.getWebAppCount()).thenReturn(null); + QualysWASResponse response = new QualysWASResponse(); + response.responseCode = -1; + response.errored = false; + response.errorMessage = ""; + + Mockito.when(client.getWebAppCount()).thenReturn(response); + + try { + client.testConnection(); + fail("Expected Exception to be thrown"); + } catch (Exception e) { + assertEquals("Please provide valid API and/or Proxy details.", e.getMessage()); + } + } + + @Test + public void test_responseCode_not_success() { + // Mock QualysWASResponse with responseCode not equal to success + QualysWASResponse mockResponse = new QualysWASResponse(); + mockResponse.responseCode = 200; + JsonObject responseObject = new JsonObject(); + JsonObject serviceResponseObject = new JsonObject(); + serviceResponseObject.addProperty("responseCode", "error"); + JsonObject detailsObject = new JsonObject(); + detailsObject.addProperty("errorMessage", "Error message"); + detailsObject.addProperty("errorResolution", "Error resolution"); + serviceResponseObject.add("responseErrorDetails", detailsObject); + responseObject.add("ServiceResponse", serviceResponseObject); + mockResponse.response = responseObject; + + // Mock getWebAppCount() to return the mock response + WASClient wasClient = spy(new WASClient(new WASAuth(""))); + Mockito.when(wasClient.getWebAppCount()).thenReturn(mockResponse); + + // Test the behavior + assertThrows(Exception.class, () -> { + wasClient.testConnection(); + }); + } + + @Test + public void test_returns_null_if_scan_status_not_error_canceled_or_finished() { + WASClient wasClient = spy(new WASClient(mock(WASAuth.class))); + QualysWASResponse statusResponse = new QualysWASResponse(); + JsonObject result = new JsonObject(); + JsonObject responseObject = new JsonObject(); + responseObject.addProperty("responseCode", "SUCCESS"); + result.add("ServiceResponse", responseObject); + statusResponse.response = result; + + when(wasClient.getScanStatus(anyString())).thenReturn(statusResponse); + + String scanId = "12345"; + String scanResult = wasClient.getScanFinishedStatus(scanId); + + assertNull(scanResult); + } + + @Test + public void test_returns_scan_status_if_scan_status_error_or_canceled() { + WASClient wasClient = spy(new WASClient(mock(WASAuth.class))); + QualysWASResponse statusResponse = new QualysWASResponse(); + JsonObject result = new JsonObject(); + JsonObject responseObject = new JsonObject(); + responseObject.addProperty("responseCode", "SUCCESS"); + JsonArray dataArr = new JsonArray(); + JsonObject obj = new JsonObject(); + JsonObject scanObj = new JsonObject(); + scanObj.addProperty("status", "error"); + obj.add("WasScan", scanObj); + dataArr.add(obj); + responseObject.add("data", dataArr); + result.add("ServiceResponse", responseObject); + statusResponse.response = result; + + when(wasClient.getScanStatus(anyString())).thenReturn(statusResponse); + + String scanId = "12345"; + String scanResult = wasClient.getScanFinishedStatus(scanId); + + assertEquals("Error.", scanResult); + } + + @Test + public void test_returns_error_if_scan_status_finished_and_results_status_not_finished() { + WASClient wasClient = spy(new WASClient(mock(WASAuth.class))); + QualysWASResponse statusResponse = new QualysWASResponse(); + JsonObject result = new JsonObject(); + JsonObject responseObject = new JsonObject(); + responseObject.addProperty("responseCode", "SUCCESS"); + JsonArray dataArr = new JsonArray(); + JsonObject obj = new JsonObject(); + JsonObject scanObj = new JsonObject(); + scanObj.addProperty("status", "finished"); + JsonObject summaryObj = new JsonObject(); + summaryObj.addProperty("resultsStatus", "failed"); + scanObj.add("summary", summaryObj); + obj.add("WasScan", scanObj); + dataArr.add(obj); + responseObject.add("data", dataArr); + result.add("ServiceResponse", responseObject); + statusResponse.response = result; + + when(wasClient.getScanStatus(anyString())).thenReturn(statusResponse); + + String scanId = "12345"; + String scanResult = wasClient.getScanFinishedStatus(scanId); + + assertEquals("failed", scanResult); + } + + @Test + public void test_returns_null_if_scan_status_finished_and_results_status_finished() { + WASClient wasClient = spy(new WASClient(mock(WASAuth.class))); + QualysWASResponse statusResponse = new QualysWASResponse(); + JsonObject result = new JsonObject(); + JsonObject responseObject = new JsonObject(); + responseObject.addProperty("responseCode", "SUCCESS"); + JsonArray dataArr = new JsonArray(); + JsonObject obj = new JsonObject(); + JsonObject scanObj = new JsonObject(); + scanObj.addProperty("status", "finished"); + JsonObject summaryObj = new JsonObject(); + summaryObj.addProperty("resultsStatus", "finished"); + scanObj.add("summary", summaryObj); + obj.add("WasScan", scanObj); + dataArr.add(obj); + responseObject.add("data", dataArr); + result.add("ServiceResponse", responseObject); + statusResponse.response = result; + + when(wasClient.getScanStatus(anyString())).thenReturn(statusResponse); + + String scanId = "12345"; + String scanResult = wasClient.getScanFinishedStatus(scanId); + + assertEquals("finished", scanResult); + } + + @Test + public void test_returns_qualyswasresponse_object() { + // Arrange + WASAuth auth = new WASAuth(""); + auth.setWasCredentials("https://example.com", "username", "password", Constants.BASIC); + WASClient wasClient = new WASClient(auth); + JsonObject requestData = new JsonObject(); + + // Act + QualysWASResponse response = wasClient.launchWASScan(requestData); + + // Assert + assertNotNull(response); + assertTrue(response instanceof QualysWASResponse); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/GitHubActionsQWas/model/TestModel.java b/src/test/java/com/example/GitHubActionsQWas/model/TestModel.java new file mode 100644 index 0000000..a696c24 --- /dev/null +++ b/src/test/java/com/example/GitHubActionsQWas/model/TestModel.java @@ -0,0 +1,30 @@ +package com.example.GitHubActionsQWas.model; + +import com.example.GitHubActionsQWas.WASClient.QualysAPIResponse; +import com.example.GitHubActionsQWas.WASClient.QualysWASResponse; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Method; + +public class TestModel { + + @Test + public void projectSetUp() + throws ClassNotFoundException, InstantiationException, IllegalAccessException { + invokeMethods(QualysAPIResponse.class); + invokeMethods(QualysWASResponse.class); + } + private void invokeMethods(Class tClass) + throws ClassNotFoundException, IllegalAccessException, InstantiationException { + Class c = Class.forName(tClass.getName()); + Object t = c.newInstance(); + + Method[] allMethods = c.getDeclaredMethods(); + for (Method m : allMethods) { + try { + m.invoke(t, null); + } catch (Exception e) {// + } + } + } +} diff --git a/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanBuilderTest.java b/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanBuilderTest.java new file mode 100644 index 0000000..70ab439 --- /dev/null +++ b/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanBuilderTest.java @@ -0,0 +1,288 @@ +package com.example.GitHubActionsQWas.service; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.Before; +import org.junit.Test; +import org.springframework.core.env.Environment; + +import java.io.FileReader; + +import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class QualysWASScanBuilderTest { + private QualysWASScanBuilder builder; + private Environment environment = mock(Environment.class); + + @Before + public void setup() { + when(environment.getProperty("API_SERVER", "")).thenReturn("https://example.com"); + when(environment.getProperty("QUALYS_USERNAME", "")).thenReturn("qualusUsername"); + when(environment.getProperty("QUALYS_PASSWORD", "")).thenReturn("qualysPassword"); + when(environment.getProperty("USE_PROXY", Boolean.class, false)).thenReturn(false); + when(environment.getProperty("PROXY_SERVER", "")).thenReturn("proxyServer"); + when(environment.getProperty("PROXY_PORT", Integer.class, 0)).thenReturn(8080); + when(environment.getProperty("PROXY_USERNAME", "")).thenReturn("proxyUsername"); + when(environment.getProperty("PROXY_PASSWORD", "")).thenReturn("proxyPassword"); + when(environment.getProperty("WEBAPP_ID", "")).thenReturn("1069358967"); + when(environment.getProperty("SCAN_NAME", "")).thenReturn("New WAS Vulnerability Scan launched from API"); + when(environment.getProperty("SCAN_TYPE", "")).thenReturn("VULNERABILITY"); + when(environment.getProperty("AUTH_RECORD", "none")).thenReturn("none"); + when(environment.getProperty("AUTH_RECORD_ID", "")).thenReturn("authRecordId"); + when(environment.getProperty("OPTION_PROFILE", "useDefault")).thenReturn("useDefault"); + when(environment.getProperty("OPTION_PROFILE_ID", "")).thenReturn("optionProfileId"); + when(environment.getProperty("CANCEL_OPTION", Boolean.class, false)).thenReturn(true); + when(environment.getProperty("CANCEL_HOURS", "")).thenReturn("12"); + when(environment.getProperty("SEVERITY_CHECK", Boolean.class, false)).thenReturn(true); + when(environment.getProperty("SEVERITY_LEVEL", Integer.class, 0)).thenReturn(4); + when(environment.getProperty("IS_FAIL_ON_QID_FOUND", Boolean.class, false)).thenReturn(false); + when(environment.getProperty("QID_LIST", "")).thenReturn("qidList"); + when(environment.getProperty("EXCLUDE", "")).thenReturn(""); + when(environment.getProperty("FAIL_ON_SCAN_ERROR", Boolean.class, false)).thenReturn(false); + when(environment.getProperty("WAIT_FOR_RESULT", Boolean.class, true)).thenReturn(true); + when(environment.getProperty("INTERVAL", Integer.class, 5)).thenReturn(5); + when(environment.getProperty("TIMEOUT", Integer.class, (60 * 5) + 50)).thenReturn(350); + + builder = spy(new QualysWASScanBuilder(environment)); + } + + // Constructor assigns values to all parameters based on environment properties + @Test + public void test_constructor_assigns_values() throws Exception { + assertEquals("https://example.com", builder.getApiServer()); + assertEquals("qualusUsername", builder.getQualysUsername()); + assertEquals("qualysPassword", builder.getQualysPasssword()); + assertFalse(builder.isUseProxy()); + assertEquals("proxyServer", builder.getProxyServer()); + assertEquals(8080, builder.getProxyPort()); + assertEquals("proxyUsername", builder.getProxyUsername()); + assertEquals("proxyPassword", builder.getProxyPassword()); + assertEquals("1069358967", builder.getWebAppId()); + assertEquals("New WAS Vulnerability Scan launched from API", builder.getScanName()); + assertEquals("VULNERABILITY", builder.getScanType()); + assertEquals("none", builder.getAuthRecord()); + assertEquals("authRecordId", builder.getAuthRecordId()); + assertEquals("useDefault", builder.getOptionProfile()); + assertEquals("optionProfileId", builder.getOptionProfileId()); + assertTrue(builder.isCancelOptions()); + assertEquals("12", builder.getCancelHours()); + assertTrue(builder.isFailOnSevereVulns()); + assertTrue(builder.isSeverityCheck()); + assertEquals(4, builder.getSeverityLevel()); + assertEquals(5, builder.getInterval()); + assertEquals(350, builder.getTimeout()); + assertFalse(builder.isSev1Vulns()); + assertFalse(builder.isSev2Vulns()); + assertFalse(builder.isSev3Vulns()); + assertTrue(builder.isSev4Vulns()); + assertTrue(builder.isSev5Vulns()); + assertEquals("", builder.getExclude()); + assertFalse(builder.isFailOnScanError()); + assertNull("", builder.getPollingInterval()); + assertNull("", builder.getVulnsTimeout()); + assertTrue(builder.isWaitForResult()); + assertNotNull(builder.getClient()); + assertEquals(0, builder.getSeverity1Limit()); + assertEquals(0, builder.getSeverity2Limit()); + assertEquals(0, builder.getSeverity3Limit()); + assertEquals(1, builder.getSeverity4Limit()); + assertEquals(1, builder.getSeverity5Limit()); + assertNotNull(builder.getEnvironment()); + } + + @Test + public void test_validateParameters() throws Exception { + builder.validateParameters(); + + builder.setAuthRecord("authRecord"); + int statusCode = catchSystemExit(builder::validateParameters); + assertEquals(1, statusCode); + + builder.setAuthRecord("none"); + builder.setOptionProfile("optionProfile"); + statusCode = catchSystemExit(builder::validateParameters); + assertEquals(1, statusCode); + } + + @Test + public void test_assignSeverities() throws Exception { + builder.setSeverityLevel(1); + builder.assignSeverities(); + + assertTrue(builder.isSev1Vulns()); + assertTrue(builder.isSev2Vulns()); + assertTrue(builder.isSev3Vulns()); + assertTrue(builder.isSev4Vulns()); + assertTrue(builder.isSev5Vulns()); + + builder.setSeverityLevel(6); + int statusCode = catchSystemExit(builder::assignSeverities); + assertEquals(1, statusCode); + } + + @Test + public void test_returns_non_null_json_object_with_fail_conditions_field() { + JsonObject criteria = builder.getCriteriaAsJsonObject(); + assertNotNull(criteria); + assertTrue(criteria.has("failConditions")); + } + + @Test + public void test_adds_severities_field_when_is_fail_on_severe_vulns_is_true() { + QualysWASScanBuilder builder = new QualysWASScanBuilder(environment); + builder.setFailOnSevereVulns(true); + builder.setSev1Vulns(true); + builder.setSeverity1Limit(10); + builder.setSev2Vulns(true); + builder.setSeverity2Limit(20); + JsonObject criteria = builder.getCriteriaAsJsonObject(); + assertTrue(criteria.has("failConditions")); + JsonObject failConditions = criteria.getAsJsonObject("failConditions"); + assertTrue(failConditions.has("severities")); + JsonObject severities = failConditions.getAsJsonObject("severities"); + assertTrue(severities.has("1")); + assertEquals(10, severities.get("1").getAsInt()); + assertTrue(severities.has("2")); + assertEquals(20, severities.get("2").getAsInt()); + } + + @Test + public void test_adds_exclude_qids_field_when_exclude_is_not_null_or_empty() { + builder.setExclude("4,5,6"); + JsonObject criteria = builder.getCriteriaAsJsonObject(); + assertTrue(criteria.has("failConditions")); + JsonObject failConditions = criteria.getAsJsonObject("failConditions"); + assertTrue(failConditions.has("excludeQids")); + JsonArray excludeQids = failConditions.getAsJsonArray("excludeQids"); + assertEquals(3, excludeQids.size()); + } + + @Test + public void test_adds_fail_on_scan_error_field_when_is_fail_on_scan_error_is_true() { + builder.setFailOnScanError(true); + JsonObject criteria = builder.getCriteriaAsJsonObject(); + assertTrue(criteria.has("failConditions")); + JsonObject failConditions = criteria.getAsJsonObject("failConditions"); + assertTrue(failConditions.has("failOnScanError")); + assertTrue(failConditions.get("failOnScanError").getAsBoolean()); + } + + @Test + public void test_all_mandatory_parameters_set() { + QualysWASScanBuilder builder = new QualysWASScanBuilder(environment); + builder.setApiServer("apiServer"); + builder.setQualysUsername("qualysUsername"); + builder.setQualysPasssword("qualysPassword"); + builder.setWebAppId("webAppId"); + builder.setScanName("scanName"); + builder.setScanType("scanType"); + + boolean result = builder.isMandatoryParametersSet(); + + assertTrue(result); + } + + @Test + public void test_testConnection_with_invalid_credentials() throws Exception { + builder.setQualysUsername("invalidUsername"); + builder.setQualysPasssword("invalidPassword"); + builder.initWASClient(); + + int statusCode = catchSystemExit(builder::testConnection); + + assertEquals(1, statusCode); + } + + @Test + public void test_launch_scan_successfully_fail_condition_configured_and_build_failed() throws Exception { + builder.setWaitForResult(true); + builder.setSeverityCheck(true); + builder.assignSeverities(); + + doReturn("FINISHED").when(builder).getScanFinishedStatus(anyString()); + + try (FileReader reader = new FileReader("src/test/java/test_data/test_scanResult_mockData_1.json")) { + JsonObject returnData = new JsonParser().parse(reader).getAsJsonObject(); + doReturn(returnData).when(builder).fetchScanResult(any(QualysWASScanResultParser.class), anyString()); + } + + try (FileReader reader = new FileReader("src/test/java/test_data/test_failurePolicyEvaluationResult_buildFailed_mockData.json")) { + JsonObject returnData = new JsonParser().parse(reader).getAsJsonObject(); + doReturn(returnData).when(builder).evaluateFailurePolicy(any(JsonObject.class)); + } + + doReturn("12345678").when(builder).launchWasScan(any(QualysWASScanService.class)); + doReturn(true).when(builder).testConnection(); + + // Assert statements + int statusCode = catchSystemExit(builder::launchWebApplicationScan); + + assertEquals(1, statusCode); + } + + @Test + public void test_launch_scan_successfully_fetch_result_failure() throws Exception { + builder.setWaitForResult(true); + QualysWASScanService mockService = mock(QualysWASScanService.class); + + doReturn("FINISHED").when(builder).getScanFinishedStatus(anyString()); + + try (FileReader reader = new FileReader("src/test/java/test_data/test_scanResult_mockData_2.json")) { + JsonObject returnData = new JsonParser().parse(reader).getAsJsonObject(); + doReturn(returnData).when(builder).fetchScanResult(any(QualysWASScanResultParser.class), anyString()); + } + + doReturn("12345678").when(builder).launchWasScan(any(QualysWASScanService.class)); + doReturn(true).when(builder).testConnection(); + + // Assert statements + int statusCode = catchSystemExit(builder::launchWebApplicationScan); + + assertEquals(1, statusCode); + } + + @Test + public void test_evaluateFailurePolicy() throws Exception { + builder.setSeverityCheck(true); + builder.setSeverityLevel(1); + builder.assignSeverities(); + + try (FileReader reader = new FileReader("src/test/java/test_data/test_scanResult_mockData_1.json")) { + JsonObject returnData = new JsonParser().parse(reader).getAsJsonObject(); + JsonObject result = builder.evaluateFailurePolicy(returnData); + assertNotNull(result); + } + } + + @Test + public void test_getScanFinishedStatus() { + doReturn("FINISHED").when(builder).getScanFinishedStatus(anyString()); + String status = builder.getScanFinishedStatus("38931000"); + assertNotNull(status); + } + + @Test + public void test_isMandatoryParametersSet() { + doReturn(true).when(builder).isMandatoryParametersSet(); + boolean result = builder.isMandatoryParametersSet(); + assertTrue(result); + } + + @Test + public void test_returns_json_object_with_valid_scan_id() { + // Arrange + QualysWASScanResultParser resultParser = mock(QualysWASScanResultParser.class); + String scanId = "valid_scan_id"; + JsonObject expectedJson = new JsonObject(); + when(resultParser.fetchScanResult(scanId)).thenReturn(expectedJson); + + // Act + JsonObject actualJson = builder.fetchScanResult(resultParser, scanId); + + // Assert + assertEquals(expectedJson, actualJson); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanResultParserTest.java b/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanResultParserTest.java new file mode 100644 index 0000000..31396a6 --- /dev/null +++ b/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanResultParserTest.java @@ -0,0 +1,123 @@ +package com.example.GitHubActionsQWas.service; + +import com.example.GitHubActionsQWas.WASClient.QualysWASResponse; +import com.example.GitHubActionsQWas.WASClient.WASClient; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.FileReader; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +class QualysWASScanResultParserTest { + + @Test + public void test_instantiation_with_json_criteria_and_wasclient_object() { + String criteriaJson = "{\"failConditions\":{\"severities\":{\"1\":5,\"2\":10,\"3\":15,\"4\":20,\"5\":25},\"excludeQids\":[\"5-10\"]}}"; + WASClient mockClient = mock(WASClient.class); + + assertDoesNotThrow(() -> new QualysWASScanResultParser(criteriaJson, mockClient)); + } + + @Test + public void test_instantiation_with_empty_json_criteria_and_wasclient_object() { + String criteriaJson = "{\"failConditions\":{}}"; + WASClient mockClient = mock(WASClient.class); + + assertDoesNotThrow(() -> new QualysWASScanResultParser(criteriaJson, mockClient)); + } + + @Test + public void test_returns_json_object_with_valid_scan_id() throws Exception { + // Create a mock WASClient + WASClient clientMock = mock(WASClient.class); + + // Create a mock QualysWASResponse + QualysWASResponse responseMock = mock(QualysWASResponse.class); + + // Create a JsonObject for the scan result + JsonObject scanResult = new JsonObject(); + // Add necessary properties to the scan result + + // Set up the mock objects + when(clientMock.getScanResult(anyString())).thenReturn(responseMock); + when(responseMock.getResponse()).thenReturn(scanResult); + + // Create an instance of QualysWASScanResultParser + QualysWASScanResultParser parser = new QualysWASScanResultParser("{\"failConditions\":{}}", clientMock); + + // Call the fetchScanResult method with a valid scanId + JsonObject result = parser.fetchScanResult("validScanId"); + + // Assert that the returned JsonObject is the same as the scan result + assertEquals(scanResult, result); + } + + @Test + public void test_returns_json_object() throws Exception { + QualysWASScanResultParser parser = new QualysWASScanResultParser("{\"failConditions\":{}}", null); + JsonObject expectedResult = parser.returnObject; + + JsonObject result = parser.getResult(); + + assertEquals(expectedResult, result); + } + + @Test + public void test_correctly_evaluates_severity() throws Exception { + // Arrange + JsonObject statsData = new JsonObject(); + statsData.addProperty("nbVulnsLevel1", 3); + statsData.addProperty("nbVulnsLevel2", 5); + statsData.addProperty("nbVulnsLevel3", 2); + statsData.addProperty("nbVulnsLevel4", 0); + statsData.addProperty("nbVulnsLevel5", 0); + + QualysWASScanResultParser parser = new QualysWASScanResultParser("{\"failConditions\":{}}", null); + + // Act + boolean result = parser.evaluateSev(statsData); + + // Assert + assertTrue(result); + } + + @Test + public void test_success_with_vulnerabilities() throws Exception { + JsonObject response = new JsonObject(); + JsonObject serviceResponseObj = new JsonObject(); + serviceResponseObj.addProperty("responseCode", "success"); + JsonArray dataArr = new JsonArray(); + JsonObject scanObj = new JsonObject(); + JsonObject vulns = new JsonObject(); + JsonObject wasScan = new JsonObject(); + JsonObject statsData = new JsonObject(); + JsonObject globalStats = new JsonObject(); + vulns.addProperty("count", 1); + JsonArray vulnsList = new JsonArray(); + + try (FileReader reader = new FileReader("src/test/java/test_data/test_vulnerabilityArray_mockData.json")) { + JsonObject vuln = new JsonParser().parse(reader).getAsJsonObject(); + vulnsList.add(vuln.getAsJsonArray("list").get(0)); + } + + vulns.add("list", vulnsList); + scanObj.add("vulns", vulns); + statsData.add("global", globalStats); + scanObj.add("stats", statsData); + wasScan.add("WasScan", scanObj); + dataArr.add(wasScan); + serviceResponseObj.add("data", dataArr); + response.add("ServiceResponse", serviceResponseObj); + + QualysWASScanResultParser parser = spy(new QualysWASScanResultParser("{\"failConditions\":{\"severities\":{\"1\":5,\"2\":10,\"3\":15,\"4\":20,\"5\":25},\"excludeQids\":[\"5-150263\"]}}", null)); + doReturn(true).when(parser).evaluateSev(any(JsonObject.class)); + + Boolean result = parser.evaluate(response); + assertTrue(result); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanServiceTest.java b/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanServiceTest.java new file mode 100644 index 0000000..5153e29 --- /dev/null +++ b/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanServiceTest.java @@ -0,0 +1,128 @@ +package com.example.GitHubActionsQWas.service; + +import com.example.GitHubActionsQWas.WASClient.QualysWASResponse; +import com.example.GitHubActionsQWas.WASClient.WASClient; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class QualysWASScanServiceTest { + + @Test + public void test_instantiation_with_valid_parameters() { + WASClient apiClient = mock(WASClient.class); + QualysWASScanService service = QualysWASScanService.builder().build(); + service.setApiClient(apiClient); + // Set up test data + service.setWebAppId("webAppId"); + service.setScanName("scanName"); + service.setScanType("scanType"); + service.setAuthRecord("useDefault"); + service.setOptionProfile("useDefault"); + service.setCancelOptions(false); + service.setAuthRecordId("authRecordId"); + service.setOptionProfileId("optionProfileId"); + service.setCancelHours("cancelHours"); + service.setPollingIntervalForVulns(1); + service.setVulnsTimeout(1); + service.setPortalUrl("portalUrl"); + service.setApiServer("apiServer"); + service.setApiUser("apiUser"); + service.setApiPass("apiPass"); + service.setUseProxy(false); + service.setProxyServer("proxyServer"); + service.setProxyPort(1); + service.setProxyUsername("proxyUsername"); + service.setProxyPassword("proxyPassword"); + service.setFailOnScanError(true); + service.setFailConditionsConfigured(true); + service.setCriteriaObject(new JsonObject()); + + + assertNotNull(service.getApiClient()); + assertEquals(service.getWebAppId(), "webAppId"); + assertEquals(service.getScanName(), "scanName"); + assertEquals(service.getScanType(), "scanType"); + assertEquals(service.getAuthRecord(), "useDefault"); + assertEquals(service.getOptionProfile(), "useDefault"); + assertFalse(service.isCancelOptions()); + assertEquals(service.getAuthRecordId(), "authRecordId"); + assertEquals(service.getOptionProfileId(), "optionProfileId"); + assertEquals(service.getCancelHours(), "cancelHours"); + assertEquals(service.getPollingIntervalForVulns(), 1); + assertEquals(service.getVulnsTimeout(), 1); + assertEquals(service.getPortalUrl(), "portalUrl"); + assertEquals(service.getApiServer(), "apiServer"); + assertEquals(service.getApiUser(), "apiUser"); + assertEquals(service.getApiPass(), "apiPass"); + assertFalse(service.isUseProxy()); + assertEquals(service.getProxyServer(), "proxyServer"); + assertEquals(service.getProxyPort(), 1); + assertEquals(service.getProxyUsername(), "proxyUsername"); + assertEquals(service.getProxyPassword(), "proxyPassword"); + assertTrue(service.isFailOnScanError()); + assertTrue(service.isFailConditionsConfigured()); + assertNotNull(service.getCriteriaObject()); + + } + + @Test + public void test_launch_scan_with_valid_parameters_returns_scan_id() { + // Mock dependencies + WASClient apiClient = mock(WASClient.class); + QualysWASScanService service = QualysWASScanService.builder().build(); + service.setApiClient(apiClient); + + // Set up test data + service.setWebAppId("webAppId"); + service.setScanName("scanName"); + service.setScanType("scanType"); + service.setAuthRecord("useDefault"); + service.setOptionProfile("useDefault"); + service.setCancelOptions(false); + service.setAuthRecordId("authRecordId"); + service.setOptionProfileId("optionProfileId"); + service.setCancelHours("cancelHours"); + service.setPollingIntervalForVulns(1); + service.setVulnsTimeout(1); + service.setPortalUrl("portalUrl"); + service.setApiServer("apiServer"); + service.setApiUser("apiUser"); + service.setApiPass("apiPass"); + service.setUseProxy(false); + service.setProxyServer("proxyServer"); + service.setProxyPort(1); + service.setProxyUsername("proxyUsername"); + service.setProxyPassword("proxyPassword"); + service.setFailOnScanError(true); + + // Set up expected response + JsonObject responseObj = new JsonObject(); + JsonObject serviceResponseObj = new JsonObject(); + serviceResponseObj.addProperty("responseCode", "SUCCESS"); + JsonArray dataArr = new JsonArray(); + JsonObject dataObj = new JsonObject(); + JsonObject wasScanObj = new JsonObject(); + wasScanObj.addProperty("id", "scanId"); + dataObj.add("WasScan", wasScanObj); + dataArr.add(dataObj); + serviceResponseObj.add("data", dataArr); + responseObj.add("ServiceResponse", serviceResponseObj); + + // Set up mock API response + QualysWASResponse apiResponse = new QualysWASResponse(); + apiResponse.setResponse(responseObj); + when(apiClient.launchWASScan(any(JsonObject.class))).thenReturn(apiResponse); + + // Invoke the method under test + String scanId = service.launchScan(); + + // Verify the result + assertEquals("scanId", scanId); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanStatusServiceTest.java b/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanStatusServiceTest.java new file mode 100644 index 0000000..f2e0bfd --- /dev/null +++ b/src/test/java/com/example/GitHubActionsQWas/service/QualysWASScanStatusServiceTest.java @@ -0,0 +1,237 @@ +package com.example.GitHubActionsQWas.service; + +import com.example.GitHubActionsQWas.WASClient.QualysWASResponse; +import com.example.GitHubActionsQWas.WASClient.WASClient; +import com.google.gson.JsonObject; +import org.junit.Test; +import org.mockito.Mockito; + +import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class QualysWASScanStatusServiceTest { + private static final int TIMEOUT = (60 * 5) + 50; + + // The fetchScanStatus method returns the scan status when the scan is finished. + @Test + public void test_fetchScanStatus_returnsScanStatusWhenScanIsFinished() { + // Arrange + String scanId = "123"; + String portalUrl = "https://example.com"; + String scanType = "vulnerability"; + boolean severityCheck = true; + int interval = 1; + String expectedStatus = "finished"; + + WASClient mockClient = Mockito.mock(WASClient.class); + Mockito.when(mockClient.getScanFinishedStatus(scanId)).thenReturn(expectedStatus); + + QualysWASScanStatusService service = new QualysWASScanStatusService(mockClient); + + // Act + String actualStatus = service.fetchScanStatus(scanId, scanType, severityCheck, portalUrl, interval, TIMEOUT); + + // Assert + assertEquals(expectedStatus, actualStatus); + } + + // The fetchScanStatus method waits for the specified interval before making the next attempt to get the scan result. + @Test + public void test_fetchScanStatus_waitsForIntervalBeforeNextAttempt() { + // Arrange + String scanId = "123"; + String portalUrl = "https://example.com"; + int interval = 1; + + WASClient mockClient = Mockito.mock(WASClient.class); + Mockito.when(mockClient.getScanFinishedStatus(scanId)).thenReturn(null, "finished"); + + QualysWASScanStatusService service = new QualysWASScanStatusService(mockClient); + + // Act + long startTime = System.currentTimeMillis(); + service.fetchScanStatus(scanId, "vulnerability", true, portalUrl, interval, TIMEOUT); + long endTime = System.currentTimeMillis(); + + // Assert + long elapsedTime = endTime - startTime; + assertTrue(elapsedTime >= interval * 6 * 100); + } + + // The fetchScanStatus method waits for the scan to finish before returning the scan status. + @Test + public void test_fetchScanStatus_waitsForScanToFinishBeforeReturningStatus() { + // Arrange + String scanId = "123"; + String portalUrl = "https://example.com"; + int interval = 1; + String expectedStatus = "finished"; + + WASClient mockClient = Mockito.mock(WASClient.class); + Mockito.when(mockClient.getScanFinishedStatus(scanId)).thenReturn(null, expectedStatus); + + QualysWASScanStatusService service = new QualysWASScanStatusService(mockClient); + + // Act + String actualStatus = service.fetchScanStatus(scanId, "vulnerability", true, portalUrl, interval, TIMEOUT); + + // Assert + assertEquals(expectedStatus, actualStatus); + } + + // The fetchScanStatus method returns the scan status when the scan is finished within the timeout period. + @Test + public void test_fetchScanStatus_returnsScanStatusWithinTimeoutPeriod() { + // Arrange + String scanId = "123"; + String portalUrl = "https://example.com"; + int interval = 1; + String expectedStatus = "finished"; + + WASClient mockClient = Mockito.mock(WASClient.class); + Mockito.when(mockClient.getScanFinishedStatus(scanId)).thenReturn(null, expectedStatus); + + QualysWASScanStatusService service = new QualysWASScanStatusService(mockClient); + + // Act + String actualStatus = service.fetchScanStatus(scanId, "vulnerability", true, portalUrl, interval, TIMEOUT); + + // Assert + assertEquals(expectedStatus, actualStatus); + } + + // The fetchScanStatus method waits for the specified interval before making the next attempt to get the scan result when the scan is not finished. + @Test + public void test_fetchScanStatus_waitInterval() { + // Create a mock WASClient + WASClient clientMock = Mockito.mock(WASClient.class); + + // Create a QualysWASScanStatusService instance with the mock client + QualysWASScanStatusService service = new QualysWASScanStatusService(clientMock); + + // Set up the mock behavior for getScanFinishedStatus + Mockito.when(clientMock.getScanFinishedStatus(Mockito.anyString())).thenReturn(null, "finished"); + + // Set up the timeout and interval values + int timeout = 5; // in minutes + int interval = 1; // in minutes + + // Call the fetchScanStatus method + String scanId = "12345"; + String portalUrl = "https://example.com"; + String status = service.fetchScanStatus(scanId, "vulnerability", true, portalUrl, interval, timeout); + + // Verify that getScanFinishedStatus was called twice with the correct scanId + Mockito.verify(clientMock, Mockito.times(2)).getScanFinishedStatus(scanId); + + // Verify that the status is "finished" + assertEquals("finished", status); + } + + // The fetchScanStatus method dumps the error message to a file and exits the program if the timeout period is reached. + @Test + public void test_fetchScanStatus_timeout() throws Exception { + // Create a mock WASClient + WASClient mockClient = Mockito.mock(WASClient.class); + + // Create a QualysWASScanStatusService instance with the mock objects + QualysWASScanStatusService service = new QualysWASScanStatusService(mockClient); + + // Set the timeout and interval values + int timeout = 1; + int interval = 2; + + // Set the scanId and portalUrl values + String scanId = "12345"; + String portalUrl = "https://example.com"; + + Mockito.when(mockClient.getScanFinishedStatus(scanId)).thenReturn(null); + + int statusCode = catchSystemExit(() -> service.fetchScanStatus(scanId,"vulnerability", true, portalUrl, interval, timeout)); + + // Verify that the getScanFinishedStatus method was called multiple times with the correct scanId + Mockito.verify(mockClient, Mockito.atLeast(timeout)).getScanFinishedStatus(scanId); + + // Assert that the status is null + assertEquals(1, statusCode); + } + + // The fetchScanStatus method logs an error message when the scan result is not a JSON object. + @Test + public void test_fetchScanStatus_logsErrorMessageWhenScanResultIsNotJSONObject() { + // Create a mock WASClient + WASClient mockClient = Mockito.mock(WASClient.class); + + // Create a QualysWASScanStatusService instance with the mock client and logger + QualysWASScanStatusService service = new QualysWASScanStatusService(mockClient); + + // Set up the mock client to return a non-JSON response + QualysWASResponse mockResponse = new QualysWASResponse(); + mockResponse.response = new JsonObject(); + Mockito.when(mockClient.getScanFinishedStatus(Mockito.anyString())).thenReturn(""); + + // Call the fetchScanStatus method + String scanId = "12345"; + String portalUrl = "https://example.com"; + int interval = 1; + String status = service.fetchScanStatus(scanId,"vulnerability", true, portalUrl, interval, TIMEOUT); + + // Verify that the status is null + assertEquals("", status); + } + + + // The fetchScanStatus method waits for the specified interval before making the next attempt to get the scan result when the scan status is not available. + @Test + public void test_fetchScanStatus_waitsForInterval() { + // Create a mock WASClient + WASClient clientMock = Mockito.mock(WASClient.class); + + // Create a QualysWASScanStatusService instance with the mock client + QualysWASScanStatusService service = new QualysWASScanStatusService(clientMock); + + // Set up the mock behavior for getScanFinishedStatus + Mockito.when(clientMock.getScanFinishedStatus(Mockito.anyString())).thenReturn(null, "finished"); + + // Call the fetchScanStatus method with a scanId, portalUrl, and interval + String scanId = "12345"; + String portalUrl = "https://example.com"; + int interval = 1; + String status = service.fetchScanStatus(scanId,"vulnerability", true, portalUrl, interval, TIMEOUT); + + // Verify that getScanFinishedStatus was called twice with the correct scanId + Mockito.verify(clientMock, Mockito.times(2)).getScanFinishedStatus(scanId); + + // Verify that the returned status is "finished" + assertEquals("finished", status); + } + + // The fetchScanStatus method logs an error message when the scan status is not available within the timeout period. + @Test + public void test_fetchScanStatus_logsErrorMessageWhenScanStatusNotAvailableWithinTimeoutPeriod() throws Exception { + // Create a mock WASClient + WASClient mockClient = Mockito.mock(WASClient.class); + + // Create a QualysWASScanStatusService instance with the mock client + QualysWASScanStatusService service = new QualysWASScanStatusService(mockClient); + + // Set up the mock client to return null for scan status + Mockito.when(mockClient.getScanFinishedStatus(Mockito.anyString())).thenReturn(null); + + // Set up the timeout and interval values + int timeout = 1; // minutes + int interval = 2; // minute + + // Call the fetchScanStatus method + String scanId = "12345"; + String portalUrl = "https://example.com"; + + int statusCode = catchSystemExit(() -> service.fetchScanStatus(scanId,"vulnerability", true, portalUrl, interval, timeout)); + + // Verify that the mock client's getScanFinishedStatus method was called + Mockito.verify(mockClient, Mockito.atLeastOnce()).getScanFinishedStatus(scanId); + + assertEquals(1, statusCode); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/GitHubActionsQWas/util/HelperTest.java b/src/test/java/com/example/GitHubActionsQWas/util/HelperTest.java new file mode 100644 index 0000000..550bb5f --- /dev/null +++ b/src/test/java/com/example/GitHubActionsQWas/util/HelperTest.java @@ -0,0 +1,83 @@ +package com.example.GitHubActionsQWas.util; + +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import static org.junit.Assert.*; + +public class HelperTest { + // setTimeoutInMinutes method returns calculated timeout in minutes when timeout is in regex form + @Test + public void test_calculate_timeout_in_minutes_when_timeout_is_in_regex_form() { + int defaultTimeoutInMins = 60; + String timeout = "2*60*60"; + + int result = Helper.setTimeoutInMinutes("vulnsTimeout", defaultTimeoutInMins, timeout); + + assertEquals(7200, result); + } + + // setTimeoutInMinutes method returns default timeout when timeout is null or empty + @Test + public void test_setTimeoutInMinutes_default_timeout_when_timeout_is_null_or_empty() { + int defaultTimeoutInMins = 10; + String timeout = null; + + int result = Helper.setTimeoutInMinutes("timeout", defaultTimeoutInMins, timeout); + + assertEquals(defaultTimeoutInMins, result); + } + + // dumpDataIntoFile method creates directory and writes data to file successfully + @Test + public void test_dumpDataIntoFile_creates_directory_and_writes_data_to_file_successfully() { + // Arrange + String data = "Test data"; + String fileName = "test.txt"; + String expectedFilePath = "outputs/test.txt"; + + // Act + Helper.dumpDataIntoFile(data, fileName); + + // Assert + File file = new File(expectedFilePath); + assertTrue(file.exists()); + assertTrue(file.isFile()); + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String fileData = reader.readLine(); + assertEquals(data, fileData); + } catch (IOException e) { + fail("Exception occurred while reading the file: " + e.getMessage()); + } + } + + // setTimeoutInMinutes method returns default timeout when timeout is not a valid number + @Test + public void test_setTimeoutInMinutes_invalid_timeout_1() { + int defaultTimeout = 60; + String timeout = "invalid"; + + int result = Helper.setTimeoutInMinutes("timeout", defaultTimeout, timeout); + + assertEquals(defaultTimeout, result); + } + + // setTimeoutInMinutes method logs error and returns default timeout when timeout is not in regex form and cannot be parsed + @Test + public void test_setTimeoutInMinutes_invalid_timeout_2() { + // Arrange + int defaultTimeoutInMins = 60; + String timeout = "invalid_timeout"; + int expectedTimeout = defaultTimeoutInMins; + + // Act + int actualTimeout = Helper.setTimeoutInMinutes("vulnsTimeout", defaultTimeoutInMins, timeout); + + // Assert + assertEquals(expectedTimeout, actualTimeout); + } +} \ No newline at end of file diff --git a/src/test/java/test_data/test_failurePolicyEvaluationResult_buildFailed_mockData.json b/src/test/java/test_data/test_failurePolicyEvaluationResult_buildFailed_mockData.json new file mode 100644 index 0000000..d69f26e --- /dev/null +++ b/src/test/java/test_data/test_failurePolicyEvaluationResult_buildFailed_mockData.json @@ -0,0 +1,105 @@ +{ + "passed": false, + "result": { + "qids": null, + "severities": { + "1": { + "configured": 1, + "found": 0, + "result": true + }, + "2": { + "configured": 1, + "found": 1, + "result": true + }, + "3": { + "configured": 1, + "found": 1, + "result": true + }, + "4": { + "configured": 1, + "found": 0, + "result": true + }, + "5": { + "configured": 1, + "found": 0, + "result": true + } + }, + "vulnsTable": { + "list": [ + { + "WasScanVuln": { + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "authenticated": "false", + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "payload": "http://www.gxmail.com/webmail/", + "result": { + "base64": "true", + "value": "Y29tbWVudDogCk9yaWdpbmFsIFVSTCBpczogaHR0cDovL3d3dy5neG1haWwuY29tLwoKSFRUUC8xLjEgMjAwIE9L" + } + } + } + ], + "count": 1 + } + } + } + ], + "count": 1 + }, + "severity": "2", + "uri": "http://www.gxmail.com/webmail/", + "potential": "false", + "qid": 150004, + "title": "Path-Based Vulnerability" + } + }, + { + "WasScanVuln": { + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "authenticated": "false", + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "payload": "", + "result": { + "base64": "true", + "value": "SFRUUC8xLjEgMjAwIE9LCkRhdGU6IFdlZCwgMzEgSmFuIDIwMjQgMDk6NTk6MzIgR01UDQpTZXJ2ZXI6IEFwYWNoZQ0KVXBncmFkZTogaDIsaDJjDQpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQ0KTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQNCkFjY2VwdC1SYW5nZXM6IGJ5dGVzDQpDb250ZW50LUxlbmd0aDogNDI5DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KCiZsdDshRE9DVFlQRSBodG1sIFBVQkxJQyAiLS8vVzNDLy9EVEQgWEhUTUwgMS4wIFRyYW5zaXRpb25hbC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi94aHRtbDEvRFREL3hodG1sMS10cmFuc2l0aW9uYWwuZHRkIiZndDsmbHQ7aHRtbCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCImZ3Q7Jmx0O2hlYWQmZ3Q7CiZsdDttZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PWlzby04ODU5LTEiJmd0OwombHQ7dGl0bGUmZ3Q7Z3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluJmx0Oy90aXRsZSZndDsKJmx0Oy9oZWFkJmd0OwombHQ7Ym9keSZndDsKJmx0O3AgYWxpZ249ImNlbnRlciImZ3Q7Jmx0O2ltZyBzcmM9Imd4bWFpbC5wbmciIGFsdD0iZ3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluIiB3aWR0aD0iMzI3IiBoZWlnaHQ9IjE5OCImZ3Q7Jmx0Oy9wJmd0OwoKCgombHQ7L2JvZHkmZ3Q7Jmx0Oy9odG1sJmd0Ow==" + } + } + } + ], + "count": 1 + } + } + } + ], + "count": 1 + }, + "severity": "3", + "uri": "http://www.gxmail.com/", + "potential": "false", + "qid": 150263, + "title": "Insecure Transport" + } + } + ], + "count": 2 + } + }, + "failureMessage": "The vulnerabilities count by severity exceeded one of the configured threshold value : \nConfigured : \nSeverity 1: true\nSeverity 2: true\nSeverity 3: true\nSeverity 4: true\nSeverity 5: true\n\nFound : \nSeverity 1; Count: 0\nSeverity 2; Count: 1\nSeverity 3; Count: 1\nSeverity 4; Count: 0\nSeverity 5; Count: 0\n" +} \ No newline at end of file diff --git a/src/test/java/test_data/test_failurePolicyEvaluationResult_buildPassed_mockData.json b/src/test/java/test_data/test_failurePolicyEvaluationResult_buildPassed_mockData.json new file mode 100644 index 0000000..637e516 --- /dev/null +++ b/src/test/java/test_data/test_failurePolicyEvaluationResult_buildPassed_mockData.json @@ -0,0 +1,104 @@ +{ + "passed": true, + "result": { + "qids": null, + "severities": { + "1": { + "configured": 1, + "found": 0, + "result": true + }, + "2": { + "configured": 1, + "found": 1, + "result": true + }, + "3": { + "configured": 1, + "found": 1, + "result": true + }, + "4": { + "configured": 1, + "found": 0, + "result": true + }, + "5": { + "configured": 1, + "found": 0, + "result": true + } + }, + "vulnsTable": { + "list": [ + { + "WasScanVuln": { + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "authenticated": "false", + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "payload": "http://www.gxmail.com/webmail/", + "result": { + "base64": "true", + "value": "Y29tbWVudDogCk9yaWdpbmFsIFVSTCBpczogaHR0cDovL3d3dy5neG1haWwuY29tLwoKSFRUUC8xLjEgMjAwIE9L" + } + } + } + ], + "count": 1 + } + } + } + ], + "count": 1 + }, + "severity": "2", + "uri": "http://www.gxmail.com/webmail/", + "potential": "false", + "qid": 150004, + "title": "Path-Based Vulnerability" + } + }, + { + "WasScanVuln": { + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "authenticated": "false", + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "payload": "", + "result": { + "base64": "true", + "value": "SFRUUC8xLjEgMjAwIE9LCkRhdGU6IFdlZCwgMzEgSmFuIDIwMjQgMDk6NTk6MzIgR01UDQpTZXJ2ZXI6IEFwYWNoZQ0KVXBncmFkZTogaDIsaDJjDQpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQ0KTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQNCkFjY2VwdC1SYW5nZXM6IGJ5dGVzDQpDb250ZW50LUxlbmd0aDogNDI5DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KCiZsdDshRE9DVFlQRSBodG1sIFBVQkxJQyAiLS8vVzNDLy9EVEQgWEhUTUwgMS4wIFRyYW5zaXRpb25hbC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi94aHRtbDEvRFREL3hodG1sMS10cmFuc2l0aW9uYWwuZHRkIiZndDsmbHQ7aHRtbCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCImZ3Q7Jmx0O2hlYWQmZ3Q7CiZsdDttZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PWlzby04ODU5LTEiJmd0OwombHQ7dGl0bGUmZ3Q7Z3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluJmx0Oy90aXRsZSZndDsKJmx0Oy9oZWFkJmd0OwombHQ7Ym9keSZndDsKJmx0O3AgYWxpZ249ImNlbnRlciImZ3Q7Jmx0O2ltZyBzcmM9Imd4bWFpbC5wbmciIGFsdD0iZ3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluIiB3aWR0aD0iMzI3IiBoZWlnaHQ9IjE5OCImZ3Q7Jmx0Oy9wJmd0OwoKCgombHQ7L2JvZHkmZ3Q7Jmx0Oy9odG1sJmd0Ow==" + } + } + } + ], + "count": 1 + } + } + } + ], + "count": 1 + }, + "severity": "3", + "uri": "http://www.gxmail.com/", + "potential": "false", + "qid": 150263, + "title": "Insecure Transport" + } + } + ], + "count": 2 + } + } +} \ No newline at end of file diff --git a/src/test/java/test_data/test_scanResult_mockData_1.json b/src/test/java/test_data/test_scanResult_mockData_1.json new file mode 100644 index 0000000..32e417a --- /dev/null +++ b/src/test/java/test_data/test_scanResult_mockData_1.json @@ -0,0 +1,593 @@ +{ + "ServiceResponse": { + "data": [ + { + "WasScan": { + "stats": { + "byWasc": { + "list": [ + { + "WascStat": { + "nbLevel4": 0, + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 1, + "nbLevel5": 0, + "wasc": "WASC-15", + "nbLevel3": 0 + } + }, + { + "WascStat": { + "nbLevel4": 0, + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 1, + "nbLevel5": 0, + "wasc": "WASC-16", + "nbLevel3": 0 + } + }, + { + "WascStat": { + "nbLevel4": 0, + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 1, + "nbLevel5": 0, + "wasc": "WASC-17", + "nbLevel3": 0 + } + }, + { + "WascStat": { + "nbLevel4": 0, + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 0, + "nbLevel5": 0, + "wasc": "WASC-4", + "nbLevel3": 1 + } + } + ], + "count": 4 + }, + "byOwasp": { + "list": [ + { + "OwaspStat": { + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 1, + "nbLevel3": 0, + "nbLevel5": 0, + "owasp": "OWASP-A1", + "nbLevel4": 0 + } + }, + { + "OwaspStat": { + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 0, + "nbLevel3": 1, + "nbLevel5": 0, + "owasp": "OWASP-A2", + "nbLevel4": 0 + } + } + ], + "count": 2 + }, + "byGroup": { + "list": [ + { + "GroupStat": { + "group": "PATH", + "nbLevel4": 0, + "nbLevel1": 0, + "nbLevel5": 0, + "nbLevel2": 1, + "nbTotal": 1, + "nbLevel3": 0 + } + }, + { + "GroupStat": { + "group": "INFO", + "nbLevel4": 0, + "nbLevel1": 0, + "nbLevel5": 0, + "nbLevel2": 0, + "nbTotal": 1, + "nbLevel3": 1 + } + } + ], + "count": 2 + }, + "global": { + "nbVulnsLevel3": 1, + "nbVulnsLevel4": 0, + "nbScsLevel5": 0, + "nbVulnsTotal": 2, + "nbScsLevel1": 0, + "nbIgsLevel5": 0, + "nbIgsLevel3": 1, + "nbVulnsLevel5": 0, + "nbScsLevel2": 0, + "nbIgsLevel4": 0, + "nbScsLevel3": 0, + "nbIgsLevel2": 8, + "nbScsTotal": 0, + "nbVulnsLevel1": 0, + "nbIgsTotal": 21, + "nbScsLevel4": 0, + "nbIgsLevel1": 12, + "nbVulnsLevel2": 1 + } + }, + "type": "VULNERABILITY", + "sendOneMail": "false", + "progressiveScanning": "DISABLED", + "options": { + "list": [ + { + "WasScanOption": { + "name": "Web Application Authentication Record Name", + "value": "None" + } + }, + { + "WasScanOption": { + "name": "Sensitive Content: Credit Card Numbers", + "value": "false" + } + }, + { + "WasScanOption": { + "name": "Scan Intensity", + "value": "MEDIUM" + } + }, + { + "WasScanOption": { + "name": "Scanner Appliance", + "value": "External (IP: 64.39.111.235, Scanner: 12.16.55-1, WAS: 8.30.47-1, Signatures: 2.5.955-2)" + } + }, + { + "WasScanOption": { + "name": "Detection Scope", + "value": "CORE" + } + }, + { + "WasScanOption": { + "name": "Option Profile Name", + "value": "Initial WAS Options" + } + }, + { + "WasScanOption": { + "name": "Timeout Error Threshold", + "value": "100" + } + }, + { + "WasScanOption": { + "name": "Web Application Name", + "value": "WAS Test App www.gxmail.com" + } + }, + { + "WasScanOption": { + "name": "Target URL", + "value": "http://www.gxmail.com" + } + }, + { + "WasScanOption": { + "name": "Unexpected Error Threshold", + "value": "300" + } + }, + { + "WasScanOption": { + "name": "Crawling Form Submissions", + "value": "BOTH" + } + }, + { + "WasScanOption": { + "name": "Bruteforce Settings", + "value": "MINIMAL" + } + }, + { + "WasScanOption": { + "name": "Maximum Crawling Links", + "value": "300" + } + }, + { + "WasScanOption": { + "name": "Request Parameter Set", + "value": "Initial Parameters" + } + }, + { + "WasScanOption": { + "name": "Performance Settings", + "value": "Pre-defined" + } + }, + { + "WasScanOption": { + "name": "Sensitive Content: Social Security Numbers (US)", + "value": "false" + } + } + ], + "count": 16 + }, + "scanDuration": 1199, + "igs": { + "list": [ + { + "WasScanIg": { + "qid": 6, + "severity": "1", + "sslData": { + "ip": "144.208.71.150", + "protocol": "tcp", + "result": "#table\nIP_address Host_name\n144.208.71.150 No_registered_hostname\n" + }, + "data": { + "base64": "true", + "value": "I3RhYmxlCklQX2FkZHJlc3MgSG9zdF9uYW1lCgoxNDQuMjA4LjcxLjE1MCBOb19yZWdpc3RlcmVkX2hvc3RuYW1lCg==" + }, + "title": "DNS Host Name" + } + }, + { + "WasScanIg": { + "qid": 150018, + "severity": "2", + "data": { + "base64": "true", + "value": "ClRvdGFsIG51bWJlciBvZiB1bmlxdWUgbGlua3MgdGhhdCBlbmNvdW50ZXJlZCBjb25uZWN0aW9uIGVycm9yczogMQpMaW5rcyB3aXRoIGhpZ2hlc3QgbnVtYmVyIG9mIGNvbm5lY3Rpb24gZXJyb3JzOgogICAxIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8KClBoYXNlIHdpc2Ugc3VtbWFyeSBvZiB0aW1lb3V0IGFuZCBjb25uZWN0aW9uIGVycm9ycyBlbmNvdW50ZXJlZDogCmVQaGFzZUNyYXdsICAgICAgICAgICAgICAgICAgICAgICAgOiAgICAgICAgICAwICAgICAgICAgMQo=" + }, + "title": "Connection Error Occurred During Web Application Scan" + } + }, + { + "WasScanIg": { + "qid": 150208, + "severity": "2", + "data": { + "base64": "true", + "value": "ClJlZmVycmVyLVBvbGljeTogSGVhZGVyIG1pc3NpbmcKUmVzcG9uc2UgaGVhZGVycyBvbiBsaW5rOiBHRVQgaHR0cDovL3d3dy5neG1haWwuY29tLyByZXNwb25zZSBjb2RlOiAyMDAKRGF0ZTogVHVlLCAwOSBKYW4gMjAyNCAxMDo0NjoxNCBHTVQKU2VydmVyOiBBcGFjaGUKVXBncmFkZTogaDIsaDJjCkNvbm5lY3Rpb246IFVwZ3JhZGUsIGNsb3NlCkxhc3QtTW9kaWZpZWQ6IE1vbiwgMjMgSmFuIDIwMTcgMDQ6MzE6MzQgR01UCkFjY2VwdC1SYW5nZXM6IGJ5dGVzCkNvbnRlbnQtTGVuZ3RoOiA0MjkKQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwKCkhlYWRlciBtaXNzaW5nIG9uIHRoZSBmb2xsb3dpbmcgbGluayhzKToKKE9ubHkgZmlyc3QgNTAgc3VjaCBwYWdlcyBhcmUgbGlzdGVkKQoKR0VUIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gcmVzcG9uc2UgY29kZTogMjAwCg==" + }, + "title": "Missing header: Referrer-Policy" + } + }, + { + "WasScanIg": { + "qid": 150020, + "severity": "1", + "data": { + "base64": "true", + "value": "TGlua3Mgbm90IHBlcm1pdHRlZDoKKFRoaXMgbGlzdCBpbmNsdWRlcyBsaW5rcyBmcm9tIFFJRHM6IDE1MDAxMCwxNTAwNDEsMTUwMTQzLDE1MDE3MCkKCklQIGJhc2VkIGV4Y2x1ZGVkIGxpbmtzOgo=" + }, + "title": "Links Rejected By Crawl Scope or Exclusion List" + } + }, + { + "WasScanIg": { + "qid": 150021, + "severity": "1", + "data": { + "base64": "true", + "value": "TG9hZGVkIDAgZXhjbHVkZSBsaXN0IGVudHJpZXMuCkxvYWRlZCAwIGFsbG93IGxpc3QgZW50cmllcy4KSFRNTCBmb3JtIGF1dGhlbnRpY2F0aW9uIHVuYXZhaWxhYmxlLCBubyBXRUJBUFAgZW50cnkgZm91bmQKVGFyZ2V0IHdlYiBhcHBsaWNhdGlvbiBwYWdlIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gZmV0Y2hlZC4gU3RhdHVzIGNvZGU6MjAwLCBDb250ZW50LVR5cGU6dGV4dC9odG1sLCBsb2FkIHRpbWU6MjEgbWlsbGlzZWNvbmRzLgpCYXRjaCAjMCBWaXJ0dWFsSG9zdERpc2NvdmVyeTogZXN0aW1hdGVkIHRpbWUgJmx0OyAxMCBtaW51dGVzICg3MCB0ZXN0cywgMCBpbnB1dHMpClZpcnR1YWxIb3N0RGlzY292ZXJ5OiA3MCB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDY5ICByZXF1ZXN0cywgMjQgc2Vjb25kcy4gQ29tcGxldGVkIDY5IHJlcXVlc3RzIG9mIDcwIGVzdGltYXRlZCByZXF1ZXN0cyAoOTguNTcxNCUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjMCBDTVNEZXRlY3Rpb246IGVzdGltYXRlZCB0aW1lICZsdDsgMTAgbWludXRlcyAoMSB0ZXN0cywgMSBpbnB1dHMpCltDTVNEZXRlY3Rpb24gcGhhc2VdIDogTm8gcG90ZW50aWFsIENNUyBmb3VuZCB1c2luZyBCbGluZCBFbGVwaGFudCBhbGdvcml0aG0uIEFib3J0aW5nIHRoZSBDTVMgRGV0ZWN0aW9uIHBoYXNlCkNNU0RldGVjdGlvbjogMSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDU2ICByZXF1ZXN0cywgNSBzZWNvbmRzLiBDb21wbGV0ZWQgNTYgcmVxdWVzdHMgb2YgNTYgZXN0aW1hdGVkIHJlcXVlc3RzICgxMDAlKS4gQWxsIHRlc3RzIGNvbXBsZXRlZC4KQ29sbGVjdGVkIDEgbGlua3Mgb3ZlcmFsbCBpbiAwIGhvdXJzIDcgbWludXRlcyBkdXJhdGlvbi4KQmF0Y2ggIzAgQmFubmVyc1ZlcnNpb25SZXBvcnRpbmc6IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDEgdGVzdHMsIDEgaW5wdXRzKQpCYW5uZXJzVmVyc2lvblJlcG9ydGluZzogMSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDAgIHJlcXVlc3RzLCAwIHNlY29uZHMuIENvbXBsZXRlZCAwIHJlcXVlc3RzIG9mIDEgZXN0aW1hdGVkIHJlcXVlc3RzICgwJSkuIEFsbCB0ZXN0cyBjb21wbGV0ZWQuClBhdGggbWFuaXB1bGF0aW9uOiBFc3RpbWF0ZWQgcmVxdWVzdHMgKHBheWxvYWRzIHggbGlua3MpOiBmaWxlcyB3aXRoIGV4dGVuc2lvbjooMCB4IDApICsgZmlsZXM6KDAgeCAwKSArICBkaXJlY3RvcmllczooOSB4IDEpICsgIHBhdGhzOigwIHggMSkgPSB0b3RhbCAoOSkgCkJhdGNoICMwIFdTIERpcmVjdG9yeSBQYXRoIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoOSB0ZXN0cywgMSBpbnB1dHMpCldTIERpcmVjdG9yeSBQYXRoIG1hbmlwdWxhdGlvbjogOSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDkgIHJlcXVlc3RzLCA1IHNlY29uZHMuIENvbXBsZXRlZCA5IHJlcXVlc3RzIG9mIDkgZXN0aW1hdGVkIHJlcXVlc3RzICgxMDAlKS4gQWxsIHRlc3RzIGNvbXBsZXRlZC4KQmF0Y2ggIzAgV1MgZW51bWVyYXRpb246IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDExIHRlc3RzLCAxIGlucHV0cykKV1MgZW51bWVyYXRpb246IDExIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMTEgIHJlcXVlc3RzLCA1IHNlY29uZHMuIENvbXBsZXRlZCAxMSByZXF1ZXN0cyBvZiAxMSBlc3RpbWF0ZWQgcmVxdWVzdHMgKDEwMCUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjMSBVUkkgcGFyYW1ldGVyIG1hbmlwdWxhdGlvbiAobm8gYXV0aCk6IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDExMyB0ZXN0cywgMCBpbnB1dHMpCkJhdGNoICMxIFVSSSBwYXJhbWV0ZXIgbWFuaXB1bGF0aW9uIChubyBhdXRoKTogMTEzIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KQmF0Y2ggIzEgVVJJIGJsaW5kIFNRTCBtYW5pcHVsYXRpb24gKG5vIGF1dGgpOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICg4IHRlc3RzLCAwIGlucHV0cykKQmF0Y2ggIzEgVVJJIGJsaW5kIFNRTCBtYW5pcHVsYXRpb24gKG5vIGF1dGgpOiA4IHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KQmF0Y2ggIzEgVVJJIHBhcmFtZXRlciB0aW1lLWJhc2VkIHRlc3RzIChubyBhdXRoKTogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMTYgdGVzdHMsIDAgaW5wdXRzKQpCYXRjaCAjMSBVUkkgcGFyYW1ldGVyIHRpbWUtYmFzZWQgdGVzdHMgKG5vIGF1dGgpOiAxNiB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDAgIHJlcXVlc3RzLCAwIHNlY29uZHMuIE5vIHRlc3RzIHRvIGV4ZWN1dGUuCkJhdGNoICMxIFVSSSBwYXJhbWV0ZXIgdGltZS1iYXNlZCB0ZXN0cyBmb3IgQXBhY2hlIFN0cnV0cyBWdWxuZXJhYmlsaXRpZXMgKG5vIGF1dGgpOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICgxIHRlc3RzLCAwIGlucHV0cykKQmF0Y2ggIzEgVVJJIHBhcmFtZXRlciB0aW1lLWJhc2VkIHRlc3RzIGZvciBBcGFjaGUgU3RydXRzIFZ1bG5lcmFiaWxpdGllcyAobm8gYXV0aCk6IDEgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCAwICByZXF1ZXN0cywgMCBzZWNvbmRzLiBObyB0ZXN0cyB0byBleGVjdXRlLgpCYXRjaCAjNCBXZWJDZ2lPb2I6IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDEzMyB0ZXN0cywgMSBpbnB1dHMpCkJhdGNoICM0IFdlYkNnaU9vYjogMTMzIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMTAwICByZXF1ZXN0cywgNiBzZWNvbmRzLiBDb21wbGV0ZWQgMTAwIHJlcXVlc3RzIG9mIDE1NSBlc3RpbWF0ZWQgcmVxdWVzdHMgKDY0LjUxNjElKS4gQWxsIHRlc3RzIGNvbXBsZXRlZC4KTm8gWE1MIHJlcXVlc3RzIGZvdW5kLiBTa2lwcGluZyBYWEUgdGVzdHMuCkJhdGNoICM0IERPTSBYU1MgZXhwbG9pdGF0aW9uOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICg0IHRlc3RzLCAwIGlucHV0cykKQmF0Y2ggIzQgRE9NIFhTUyBleHBsb2l0YXRpb246IDQgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCAwICByZXF1ZXN0cywgMCBzZWNvbmRzLiBObyB0ZXN0cyB0byBleGVjdXRlLgpCYXRjaCAjNCBIVFRQIGNhbGwgbWFuaXB1bGF0aW9uOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICgzOCB0ZXN0cywgMCBpbnB1dHMpCkJhdGNoICM0IEhUVFAgY2FsbCBtYW5pcHVsYXRpb246IDM4IHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KQmF0Y2ggIzQgT3BlbiBSZWRpcmVjdCBhbmFseXNpczogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMiB0ZXN0cywgMCBpbnB1dHMpCkJhdGNoICM0IE9wZW4gUmVkaXJlY3QgYW5hbHlzaXM6IDIgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCAwICByZXF1ZXN0cywgMiBzZWNvbmRzLiBObyB0ZXN0cyB0byBleGVjdXRlLgpDU1JGIHRlc3RzIHdpbGwgbm90IGJlIGxhdW5jaGVkIGJlY2F1c2UgdGhlIHNjYW4gaXMgbm90IHN1Y2Nlc3NmdWxseSBhdXRoZW50aWNhdGVkLgpCYXRjaCAjNCBGaWxlIEluY2x1c2lvbiBhbmFseXNpczogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMSBpbnB1dHMpCkJhdGNoICM0IEZpbGUgSW5jbHVzaW9uIGFuYWx5c2lzOiAxIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gQ29tcGxldGVkIDAgcmVxdWVzdHMgb2YgMSBlc3RpbWF0ZWQgcmVxdWVzdHMgKDAlKS4gQWxsIHRlc3RzIGNvbXBsZXRlZC4KQmF0Y2ggIzQgQ29va2llIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoNDcgdGVzdHMsIDAgaW5wdXRzKQpCYXRjaCAjNCBDb29raWUgbWFuaXB1bGF0aW9uOiA0NyB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDAgIHJlcXVlc3RzLCAwIHNlY29uZHMuIE5vIHRlc3RzIHRvIGV4ZWN1dGUuCkJhdGNoICM0IEhlYWRlciBtYW5pcHVsYXRpb246IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDQ3IHRlc3RzLCAxIGlucHV0cykKQmF0Y2ggIzQgSGVhZGVyIG1hbmlwdWxhdGlvbjogNDcgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCA2MyAgcmVxdWVzdHMsIDUgc2Vjb25kcy4gQ29tcGxldGVkIDYzIHJlcXVlc3RzIG9mIDEzMCBlc3RpbWF0ZWQgcmVxdWVzdHMgKDQ4LjQ2MTUlKS4gWFNTIG9wdGltaXphdGlvbiByZW1vdmVkIDI5IGxpbmtzLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjNCBzaGVsbCBzaG9jayBkZXRlY3RvcjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMSBpbnB1dHMpCkJhdGNoICM0IHNoZWxsIHNob2NrIGRldGVjdG9yOiAxIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMSAgcmVxdWVzdHMsIDQgc2Vjb25kcy4gQ29tcGxldGVkIDEgcmVxdWVzdHMgb2YgMSBlc3RpbWF0ZWQgcmVxdWVzdHMgKDEwMCUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjNCBzaGVsbCBzaG9jayBkZXRlY3Rvcihmb3JtKTogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMCBpbnB1dHMpCkJhdGNoICM0IHNoZWxsIHNob2NrIGRldGVjdG9yKGZvcm0pOiAxIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KQ29va2llcyBXaXRob3V0IENvbnNlbnQgbm8gdGVzdHMgZW5hYmxlZC4KQmF0Y2ggIzUgSFRUUCBUaW1lIEJhbmRpdDogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMTAgaW5wdXRzKQpCYXRjaCAjNSBIVFRQIFRpbWUgQmFuZGl0OiAxIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KUGF0aCBtYW5pcHVsYXRpb246IEVzdGltYXRlZCByZXF1ZXN0cyAocGF5bG9hZHMgeCBsaW5rcyk6IGZpbGVzIHdpdGggZXh0ZW5zaW9uOigwIHggMCkgKyBmaWxlczooMCB4IDApICsgIGRpcmVjdG9yaWVzOig0IHggMSkgKyAgcGF0aHM6KDExIHggMSkgPSB0b3RhbCAoMTUpIApCYXRjaCAjNSBQYXRoIFhTUyBtYW5pcHVsYXRpb246IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDE1IHRlc3RzLCAxIGlucHV0cykKQmF0Y2ggIzUgUGF0aCBYU1MgbWFuaXB1bGF0aW9uOiAxNSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDE0ICByZXF1ZXN0cywgNSBzZWNvbmRzLiBDb21wbGV0ZWQgMTQgcmVxdWVzdHMgb2YgMTUgZXN0aW1hdGVkIHJlcXVlc3RzICg5My4zMzMzJSkuIEFsbCB0ZXN0cyBjb21wbGV0ZWQuClBhdGggbWFuaXB1bGF0aW9uOiBFc3RpbWF0ZWQgcmVxdWVzdHMgKHBheWxvYWRzIHggbGlua3MpOiBmaWxlcyB3aXRoIGV4dGVuc2lvbjooMCB4IDApICsgZmlsZXM6KDAgeCAwKSArICBkaXJlY3RvcmllczooMSB4IDEpICsgIHBhdGhzOigwIHggMSkgPSB0b3RhbCAoMSkgCkJhdGNoICM1IFRvbWNhdCBWdWxuIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMSBpbnB1dHMpCkJhdGNoICM1IFRvbWNhdCBWdWxuIG1hbmlwdWxhdGlvbjogMSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDEgIHJlcXVlc3RzLCAxOCBzZWNvbmRzLiBDb21wbGV0ZWQgMSByZXF1ZXN0cyBvZiAxIGVzdGltYXRlZCByZXF1ZXN0cyAoMTAwJSkuIEFsbCB0ZXN0cyBjb21wbGV0ZWQuClBhdGggbWFuaXB1bGF0aW9uOiBFc3RpbWF0ZWQgcmVxdWVzdHMgKHBheWxvYWRzIHggbGlua3MpOiBmaWxlcyB3aXRoIGV4dGVuc2lvbjooMCB4IDApICsgZmlsZXM6KDAgeCAwKSArICBkaXJlY3RvcmllczooMTYgeCAxKSArICBwYXRoczooMCB4IDEpID0gdG90YWwgKDE2KSAKQmF0Y2ggIzUgVGltZSBiYXNlZCBwYXRoIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMTYgdGVzdHMsIDIgaW5wdXRzKQpCYXRjaCAjNSBUaW1lIGJhc2VkIHBhdGggbWFuaXB1bGF0aW9uOiAxNiB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDE2ICByZXF1ZXN0cywgMjQwIHNlY29uZHMuIENvbXBsZXRlZCAxNiByZXF1ZXN0cyBvZiAxNiBlc3RpbWF0ZWQgcmVxdWVzdHMgKDEwMCUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpQYXRoIG1hbmlwdWxhdGlvbjogRXN0aW1hdGVkIHJlcXVlc3RzIChwYXlsb2FkcyB4IGxpbmtzKTogZmlsZXMgd2l0aCBleHRlbnNpb246KDEgeCAwKSArIGZpbGVzOigxMiB4IDApICsgIGRpcmVjdG9yaWVzOigxNDMgeCAxKSArICBwYXRoczooMTQgeCAxKSA9IHRvdGFsICgxNTcpIApCYXRjaCAjNSBQYXRoIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMTcwIHRlc3RzLCAxIGlucHV0cykKQmF0Y2ggIzUgUGF0aCBtYW5pcHVsYXRpb246IDE3MCB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDE1MSAgcmVxdWVzdHMsIDUgc2Vjb25kcy4gQ29tcGxldGVkIDE1MSByZXF1ZXN0cyBvZiAxNTcgZXN0aW1hdGVkIHJlcXVlc3RzICg5Ni4xNzgzJSkuIEFsbCB0ZXN0cyBjb21wbGV0ZWQuCldlYkNnaUhyc1Rlc3RzOiBubyB0ZXN0IGVuYWJsZWQKQmF0Y2ggIzUgV2ViQ2dpR2VuZXJpYzogZXN0aW1hdGVkIHRpbWUgJmx0OyAxMCBtaW51dGVzICg0NTEgdGVzdHMsIDEgaW5wdXRzKQpCYXRjaCAjNSBXZWJDZ2lHZW5lcmljOiA0NTEgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCAxNzcgIHJlcXVlc3RzLCA2IHNlY29uZHMuIENvbXBsZXRlZCAxNzcgcmVxdWVzdHMgb2YgNjA1IGVzdGltYXRlZCByZXF1ZXN0cyAoMjkuMjU2MiUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjNSBPcGVuIFJlZGlyZWN0IGFuYWx5c2lzOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICgyIHRlc3RzLCAwIGlucHV0cykKQmF0Y2ggIzUgT3BlbiBSZWRpcmVjdCBhbmFseXNpczogMiB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDAgIHJlcXVlc3RzLCA1IHNlY29uZHMuIE5vIHRlc3RzIHRvIGV4ZWN1dGUuCkR1cmF0aW9uIG9mIENyYXdsIFRpbWU6IDQ2MC4wMCAoc2Vjb25kcykKRHVyYXRpb24gb2YgVGVzdCBQaGFzZTogNzMyLjAwIChzZWNvbmRzKQpUb3RhbCBTY2FuIFRpbWU6IDExOTIuMDAgKHNlY29uZHMpCgpUb3RhbCByZXF1ZXN0cyBtYWRlOiA3MDAKQXZlcmFnZSBzZXJ2ZXIgcmVzcG9uc2UgdGltZTogMC41NyBzZWNvbmRzCgpBdmVyYWdlIGJyb3dzZXIgbG9hZCB0aW1lOiAwLjkzIHNlY29uZHMK" + }, + "title": "Scan Diagnostics" + } + }, + { + "WasScanIg": { + "qid": 150086, + "severity": "3", + "data": { + "base64": "true", + "value": "U2VydmVyIHJlc3BvbmRlZCAyMDAgdG8gdW5uZWNlc3NhcmlseSBsYXJnZSByYW5kb20gcmVxdWVzdCBib2R5KG92ZXIgNjQgS0IpIGZvciBVUkwgaHR0cDovL3d3dy5neG1haWwuY29tLywgc2lnbmlmaWNhbnRseSBpbmNyZWFzaW5nIGF0dGFja2VyJ3MgY2hhbmNlcyB0byBwcm9sb25nIHNsb3cgSFRUUCBQT1NUIGF0dGFjay4=" + }, + "title": "Server accepts unnecessarily large POST request body" + } + }, + { + "WasScanIg": { + "qid": 150247, + "severity": "1", + "data": { + "base64": "true", + "value": "Ck51bWJlciBvZiB0ZWNobm9sb2dpZXMgZGV0ZWN0ZWQ6IDEKVGVjaG5vbG9neSBuYW1lOiBBcGFjaGUKTWF0Y2hlZCBDb21wb25lbnRzOgpoZWFkZXIgbWF0Y2g6CiAgU2VydmVyOkFwYWNoZQpNYXRjaGVkIGxpbmtzOiByZXBvcnRpbmcgb25seSBmaXJzdCAzIGxpbmtzCmh0dHA6Ly93d3cuZ3htYWlsLmNvbS8KCg==" + }, + "title": "Web Server and Technologies Detected" + } + }, + { + "WasScanIg": { + "qid": 150245, + "severity": "1", + "data": { + "base64": "true", + "value": "WC1GcmFtZS1PcHRpb25zIGhlYWRlciBpcyBtaXNzaW5nIG9yIG5vdCBzZXQgdG8gREVOWSBvciBTQU1FT1JJR0lOIGZvciB0aGUgZm9sbG93aW5nIHBhZ2VzOgooT25seSBmaXJzdCAxMCBzdWNoIHBhZ2VzIGFyZSByZXBvcnRlZCkKCkdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vClJlc3BvbnNlIGNvZGU6IDIwMApSZXNwb25zZSBoZWFkZXJzOiAKRGF0ZTogVHVlLCAwOSBKYW4gMjAyNCAxMDo0NjoxNCBHTVQKU2VydmVyOiBBcGFjaGUKVXBncmFkZTogaDIsaDJjCkNvbm5lY3Rpb246IFVwZ3JhZGUsIGNsb3NlCkxhc3QtTW9kaWZpZWQ6IE1vbiwgMjMgSmFuIDIwMTcgMDQ6MzE6MzQgR01UCkFjY2VwdC1SYW5nZXM6IGJ5dGVzCkNvbnRlbnQtTGVuZ3RoOiA0MjkKQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwKCg==" + }, + "title": "Missing header: X-Frame-Options" + } + }, + { + "WasScanIg": { + "qid": 150152, + "severity": "1", + "data": { + "base64": "true", + "value": "VG90YWwgaW50ZXJuYWwgZm9ybXMgc2VlbiAodGhpcyBjb3VudCBpbmNsdWRlcyBkdXBsaWNhdGUgZm9ybXMpOiAwCgpDcmF3bGVkIGZvcm1zIChUb3RhbDogMCkKTk9URTogVGhpcyBkb2VzIG5vdCBpbmNsdWRlIGF1dGhlbnRpY2F0aW9uIGZvcm1zLiBBdXRoZW50aWNhdGlvbiBmb3JtcyBhcmUgcmVwb3J0ZWQgc2VwYXJhdGVseSBpbiBRSUQgMTUwMTE1Cg==" + }, + "title": "Forms Crawled" + } + }, + { + "WasScanIg": { + "qid": 150248, + "severity": "2", + "data": { + "base64": "true", + "value": "ClBlcm1pc3Npb25zLVBvbGljeTogSGVhZGVyIG1pc3NpbmcKUmVzcG9uc2UgaGVhZGVycyBvbiBsaW5rOiBHRVQgaHR0cDovL3d3dy5neG1haWwuY29tLyByZXNwb25zZSBjb2RlOiAyMDAKRGF0ZTogVHVlLCAwOSBKYW4gMjAyNCAxMDo0NjoxNCBHTVQKU2VydmVyOiBBcGFjaGUKVXBncmFkZTogaDIsaDJjCkNvbm5lY3Rpb246IFVwZ3JhZGUsIGNsb3NlCkxhc3QtTW9kaWZpZWQ6IE1vbiwgMjMgSmFuIDIwMTcgMDQ6MzE6MzQgR01UCkFjY2VwdC1SYW5nZXM6IGJ5dGVzCkNvbnRlbnQtTGVuZ3RoOiA0MjkKQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwKCkhlYWRlciBtaXNzaW5nIG9uIHRoZSBmb2xsb3dpbmcgbGluayhzKToKKE9ubHkgZmlyc3QgNTAgc3VjaCBwYWdlcyBhcmUgbGlzdGVkKQoKR0VUIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gcmVzcG9uc2UgY29kZTogMjAwCg==" + }, + "title": "Missing header: Permissions-Policy" + } + }, + { + "WasScanIg": { + "qid": 45038, + "severity": "1", + "data": { + "base64": "true", + "value": "U2NhbiBkdXJhdGlvbjogMTE5OSBzZWNvbmRzCgpTdGFydCB0aW1lOiBUdWUsIEphbiAwOSAyMDI0LCAxMDo0NDoxNyBHTVQKCkVuZCB0aW1lOiBUdWUsIEphbiAwOSAyMDI0LCAxMTowNDoxNiBHTVQK" + }, + "title": "Host Scan Time - Scanner" + } + }, + { + "WasScanIg": { + "qid": 150546, + "severity": "1", + "data": { + "base64": "true", + "value": "QmFzZSBVUkk6IGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8KUmVzcG9uc2UgQ29kZTogMjAwClJlc3BvbnNlIEhlYWRlcjogCiBEYXRlOiBUdWUsIDA5IEphbiAyMDI0IDEwOjQ2OjE0IEdNVAogU2VydmVyOiBBcGFjaGUKIFVwZ3JhZGU6IGgyLGgyYwogQ29ubmVjdGlvbjogVXBncmFkZSwgY2xvc2UKIExhc3QtTW9kaWZpZWQ6IE1vbiwgMjMgSmFuIDIwMTcgMDQ6MzE6MzQgR01UCiBBY2NlcHQtUmFuZ2VzOiBieXRlcwogQ29udGVudC1MZW5ndGg6IDQyOQogQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwKIApSZXNwb25zZSBCb2R5OiAKICZsdDshRE9DVFlQRSBodG1sIFBVQkxJQyAiLS8vVzNDLy9EVEQgWEhUTUwgMS4wIFRyYW5zaXRpb25hbC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi94aHRtbDEvRFREL3hodG1sMS10cmFuc2l0aW9uYWwuZHRkIiZndDsmbHQ7aHRtbCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCImZ3Q7Jmx0O2hlYWQmZ3Q7CiAmbHQ7bWV0YSBodHRwLWVxdWl2PSJDb250ZW50LVR5cGUiIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD1pc28tODg1OS0xIiZndDsKICZsdDt0aXRsZSZndDtneG1haWwuY29tIC0gUHJpdmF0ZSBkb21haW4mbHQ7L3RpdGxlJmd0OwogJmx0Oy9oZWFkJmd0OwogJmx0O2JvZHkmZ3Q7CiAmbHQ7cCBhbGlnbj0iY2VudGVyIiZndDsmbHQ7aW1nIHNyYz0iZ3htYWlsLnBuZyIgYWx0PSJneG1haWwuY29tIC0gUHJpdmF0ZSBkb21haW4iIHdpZHRoPSIzMjciIGhlaWdodD0iMTk4IiZndDsmbHQ7L3AmZ3Q7CiAKIAogCiAmbHQ7L2JvZHkmZ3Q7Jmx0Oy9odG1sJmd0OwogCg==" + }, + "title": "First Link Crawled Response Code Information" + } + }, + { + "WasScanIg": { + "qid": 150262, + "severity": "2", + "data": { + "base64": "true", + "value": "CkZlYXR1cmUtUG9saWN5OiBIZWFkZXIgbWlzc2luZwpSZXNwb25zZSBoZWFkZXJzIG9uIGxpbms6IEdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vIHJlc3BvbnNlIGNvZGU6IDIwMApEYXRlOiBUdWUsIDA5IEphbiAyMDI0IDEwOjQ2OjE0IEdNVApTZXJ2ZXI6IEFwYWNoZQpVcGdyYWRlOiBoMixoMmMKQ29ubmVjdGlvbjogVXBncmFkZSwgY2xvc2UKTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQKQWNjZXB0LVJhbmdlczogYnl0ZXMKQ29udGVudC1MZW5ndGg6IDQyOQpDb250ZW50LVR5cGU6IHRleHQvaHRtbAoKSGVhZGVyIG1pc3Npbmcgb24gdGhlIGZvbGxvd2luZyBsaW5rKHMpOgooT25seSBmaXJzdCA1MCBzdWNoIHBhZ2VzIGFyZSBsaXN0ZWQpCgpHRVQgaHR0cDovL3d3dy5neG1haWwuY29tLyByZXNwb25zZSBjb2RlOiAyMDAK" + }, + "title": "Missing header: Feature-Policy" + } + }, + { + "WasScanIg": { + "qid": 150202, + "severity": "2", + "data": { + "base64": "true", + "value": "ClgtQ29udGVudC1UeXBlLU9wdGlvbnM6IEhlYWRlciBtaXNzaW5nClJlc3BvbnNlIGhlYWRlcnMgb24gbGluazogR0VUIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gcmVzcG9uc2UgY29kZTogMjAwCkRhdGU6IFR1ZSwgMDkgSmFuIDIwMjQgMTA6NDY6MTQgR01UClNlcnZlcjogQXBhY2hlClVwZ3JhZGU6IGgyLGgyYwpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQpMYXN0LU1vZGlmaWVkOiBNb24sIDIzIEphbiAyMDE3IDA0OjMxOjM0IEdNVApBY2NlcHQtUmFuZ2VzOiBieXRlcwpDb250ZW50LUxlbmd0aDogNDI5CkNvbnRlbnQtVHlwZTogdGV4dC9odG1sCgpIZWFkZXIgbWlzc2luZyBvbiB0aGUgZm9sbG93aW5nIGxpbmsocyk6CihPbmx5IGZpcnN0IDUwIHN1Y2ggcGFnZXMgYXJlIGxpc3RlZCkKCkdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vIHJlc3BvbnNlIGNvZGU6IDIwMAo=" + }, + "title": "Missing header: X-Content-Type-Options" + } + }, + { + "WasScanIg": { + "qid": 45017, + "severity": "2", + "sslData": { + "sslDataInfoList": { + "list": [ + { + "SSLDataInfo": { + "sslDataCipherList": {}, + "sslDataPropList": {}, + "sslDataKexList": {} + } + } + ] + }, + "ip": "144.208.71.150", + "protocol": "tcp", + "result": "EulerOS_/_Ubuntu_/_Fedora_/_Tiny_Core_Linux_/_Linux_3.x_/_IBM_/_FortiSOAR_/_F5_Networks_Big-IP TCP/IP_Fingerprint M5933:7322::80\n" + }, + "data": { + "base64": "true", + "value": "RXVsZXJPU18vX1VidW50dV8vX0ZlZG9yYV8vX1RpbnlfQ29yZV9MaW51eF8vX0xpbnV4XzMueF8vX0lCTV8vX0ZvcnRpU09BUl8vX0Y1X05ldHdvcmtzX0JpZy1JUCBUQ1AvSVBfRmluZ2VycHJpbnQgTTU5MzM6NzMyMjo6ODAK" + }, + "title": "Operating System Detected" + } + }, + { + "WasScanIg": { + "qid": 150009, + "severity": "1", + "data": { + "base64": "true", + "value": "RHVyYXRpb24gb2YgY3Jhd2wgcGhhc2UgKHNlY29uZHMpOiA0NjAuMDAKTnVtYmVyIG9mIGxpbmtzOiAxCihUaGlzIG51bWJlciBleGNsdWRlcyBmb3JtIHJlcXVlc3RzIGFuZCBsaW5rcyByZS1yZXF1ZXN0ZWQgZHVyaW5nIGF1dGhlbnRpY2F0aW9uLikKCmh0dHA6Ly93d3cuZ3htYWlsLmNvbS8K" + }, + "title": "Links Crawled" + } + }, + { + "WasScanIg": { + "qid": 150142, + "severity": "1", + "data": { + "base64": "true", + "value": "VmlydHVhbCBob3N0IGRpc2NvdmVyZWQ6CgpEZXRlY3RlZCBiYXNlZCBvbjogVW5pcXVlIHBhZ2UgY29udGVudApWaXJ0dWFsIEhvc3Q6IHdlYm1haWwud3d3Lmd4bWFpbC5jb20KVVJJOiBodHRwOi8vd3d3Lmd4bWFpbC5jb20vCgpEZXRlY3RlZCBiYXNlZCBvbjogVW5pcXVlIHBhZ2UgY29udGVudApWaXJ0dWFsIEhvc3Q6IG1haWwuZ3htYWlsLmNvbQpVUkk6IGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8KCkRldGVjdGVkIGJhc2VkIG9uOiBVbmlxdWUgcGFnZSBjb250ZW50ClZpcnR1YWwgSG9zdDogd2VibWFpbC5neG1haWwuY29tClVSSTogaHR0cDovL3d3dy5neG1haWwuY29tLwo=" + }, + "title": "Virtual Host Discovered" + } + }, + { + "WasScanIg": { + "qid": 150206, + "severity": "2", + "data": { + "base64": "true", + "value": "CkNvbnRlbnQtU2VjdXJpdHktUG9saWN5OiBIZWFkZXIgbWlzc2luZwpSZXNwb25zZSBoZWFkZXJzIG9uIGxpbms6IEdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vIHJlc3BvbnNlIGNvZGU6IDIwMApEYXRlOiBUdWUsIDA5IEphbiAyMDI0IDEwOjQ2OjE0IEdNVApTZXJ2ZXI6IEFwYWNoZQpVcGdyYWRlOiBoMixoMmMKQ29ubmVjdGlvbjogVXBncmFkZSwgY2xvc2UKTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQKQWNjZXB0LVJhbmdlczogYnl0ZXMKQ29udGVudC1MZW5ndGg6IDQyOQpDb250ZW50LVR5cGU6IHRleHQvaHRtbAoKSGVhZGVyIG1pc3Npbmcgb24gdGhlIGZvbGxvd2luZyBsaW5rKHMpOgooT25seSBmaXJzdCA1MCBzdWNoIHBhZ2VzIGFyZSBsaXN0ZWQpCgpHRVQgaHR0cDovL3d3dy5neG1haWwuY29tLyByZXNwb25zZSBjb2RlOiAyMDAK" + }, + "title": "Content-Security-Policy Not Implemented" + } + }, + { + "WasScanIg": { + "qid": 150204, + "severity": "1", + "data": { + "base64": "true", + "value": "ClgtWHNzLVByb3RlY3Rpb246IEhlYWRlciBtaXNzaW5nClJlc3BvbnNlIGhlYWRlcnMgb24gbGluazogR0VUIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gcmVzcG9uc2UgY29kZTogMjAwCkRhdGU6IFR1ZSwgMDkgSmFuIDIwMjQgMTA6NDY6MTQgR01UClNlcnZlcjogQXBhY2hlClVwZ3JhZGU6IGgyLGgyYwpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQpMYXN0LU1vZGlmaWVkOiBNb24sIDIzIEphbiAyMDE3IDA0OjMxOjM0IEdNVApBY2NlcHQtUmFuZ2VzOiBieXRlcwpDb250ZW50LUxlbmd0aDogNDI5CkNvbnRlbnQtVHlwZTogdGV4dC9odG1sCgpIZWFkZXIgbWlzc2luZyBvbiB0aGUgZm9sbG93aW5nIGxpbmsocyk6CihPbmx5IGZpcnN0IDUwIHN1Y2ggcGFnZXMgYXJlIGxpc3RlZCkKCkdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vIHJlc3BvbnNlIGNvZGU6IDIwMAo=" + }, + "title": "Missing header: X-XSS-Protection" + } + } + ], + "count": 19 + }, + "status": "FINISHED", + "target": { + "cancelOption": "SPECIFIC", + "scannerAppliance": { + "type": "EXTERNAL" + }, + "randomizeScan": "false", + "webApp": { + "id": 1069358967, + "url": "http://www.gxmail.com", + "name": "WAS Test App www.gxmail.com" + } + }, + "id": 38847527, + "multi": "false", + "consolidatedStatus": "FINISHED", + "launchedDate": "2024-01-09T10:44:18Z", + "mode": "API", + "name": "New WAS Vulnerability Scan launched from API_2024-01-09-16-13", + "reference": "was/1704797014773.62436158", + "enableWAFAuth": "false", + "endScanDate": "2024-01-09T11:04:17Z", + "summary": { + "testDuration": 733, + "authStatus": "NONE", + "nbRequests": 700, + "linksCrawled": 1, + "resultsStatus": "SUCCESSFUL", + "crawlDuration": 460, + "os": "EulerOS / Ubuntu / Fedora / Tiny Core Linux / Linux 3.x / IBM / FortiSOAR / F5 Networks Big-IP" + }, + "launchedBy": { + "id": 105571763, + "firstName": "Prabhas", + "username": "quays_pg19", + "lastName": "Gupte" + }, + "sendMail": "true", + "sensitiveContents": { + "count": 0 + }, + "vulns": { + "list": [ + { + "WasScanVuln": { + "severity": "3", + "uri": "http://www.gxmail.com/", + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "authenticated": "false", + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "payload": "", + "result": { + "base64": "true", + "value": "SFRUUC8xLjEgMjAwIE9LCkRhdGU6IFR1ZSwgMDkgSmFuIDIwMjQgMTA6NDY6MTQgR01UDQpTZXJ2ZXI6IEFwYWNoZQ0KVXBncmFkZTogaDIsaDJjDQpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQ0KTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQNCkFjY2VwdC1SYW5nZXM6IGJ5dGVzDQpDb250ZW50LUxlbmd0aDogNDI5DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KCiZsdDshRE9DVFlQRSBodG1sIFBVQkxJQyAiLS8vVzNDLy9EVEQgWEhUTUwgMS4wIFRyYW5zaXRpb25hbC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi94aHRtbDEvRFREL3hodG1sMS10cmFuc2l0aW9uYWwuZHRkIiZndDsmbHQ7aHRtbCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCImZ3Q7Jmx0O2hlYWQmZ3Q7CiZsdDttZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PWlzby04ODU5LTEiJmd0OwombHQ7dGl0bGUmZ3Q7Z3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluJmx0Oy90aXRsZSZndDsKJmx0Oy9oZWFkJmd0OwombHQ7Ym9keSZndDsKJmx0O3AgYWxpZ249ImNlbnRlciImZ3Q7Jmx0O2ltZyBzcmM9Imd4bWFpbC5wbmciIGFsdD0iZ3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluIiB3aWR0aD0iMzI3IiBoZWlnaHQ9IjE5OCImZ3Q7Jmx0Oy9wJmd0OwoKCgombHQ7L2JvZHkmZ3Q7Jmx0Oy9odG1sJmd0Ow==" + } + } + } + ], + "count": 1 + } + } + } + ], + "count": 1 + }, + "potential": "false", + "qid": 150263, + "title": "Insecure Transport" + } + }, + { + "WasScanVuln": { + "severity": "2", + "uri": "http://www.gxmail.com/webmail/", + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "authenticated": "false", + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "payload": "http://www.gxmail.com/webmail/", + "result": { + "base64": "true", + "value": "Y29tbWVudDogCk9yaWdpbmFsIFVSTCBpczogaHR0cDovL3d3dy5neG1haWwuY29tLwoKSFRUUC8xLjEgMjAwIE9L" + } + } + } + ], + "count": 1 + } + } + } + ], + "count": 1 + }, + "potential": "false", + "qid": 150004, + "title": "Path-Based Vulnerability" + } + } + ], + "count": 2 + }, + "profile": { + "id": 50723, + "name": "Initial WAS Options" + } + } + } + ], + "count": 0, + "responseCode": "SUCCESS" + } +} \ No newline at end of file diff --git a/src/test/java/test_data/test_scanResult_mockData_2.json b/src/test/java/test_data/test_scanResult_mockData_2.json new file mode 100644 index 0000000..6449376 --- /dev/null +++ b/src/test/java/test_data/test_scanResult_mockData_2.json @@ -0,0 +1,589 @@ +{ + "data": [ + { + "WasScan": { + "stats": { + "byWasc": { + "list": [ + { + "WascStat": { + "nbLevel4": 0, + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 1, + "nbLevel5": 0, + "wasc": "WASC-15", + "nbLevel3": 0 + } + }, + { + "WascStat": { + "nbLevel4": 0, + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 1, + "nbLevel5": 0, + "wasc": "WASC-16", + "nbLevel3": 0 + } + }, + { + "WascStat": { + "nbLevel4": 0, + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 1, + "nbLevel5": 0, + "wasc": "WASC-17", + "nbLevel3": 0 + } + }, + { + "WascStat": { + "nbLevel4": 0, + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 0, + "nbLevel5": 0, + "wasc": "WASC-4", + "nbLevel3": 1 + } + } + ], + "count": 4 + }, + "byOwasp": { + "list": [ + { + "OwaspStat": { + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 1, + "nbLevel3": 0, + "nbLevel5": 0, + "owasp": "OWASP-A1", + "nbLevel4": 0 + } + }, + { + "OwaspStat": { + "nbLevel1": 0, + "nbTotal": 1, + "nbLevel2": 0, + "nbLevel3": 1, + "nbLevel5": 0, + "owasp": "OWASP-A2", + "nbLevel4": 0 + } + } + ], + "count": 2 + }, + "byGroup": { + "list": [ + { + "GroupStat": { + "group": "PATH", + "nbLevel4": 0, + "nbLevel1": 0, + "nbLevel5": 0, + "nbLevel2": 1, + "nbTotal": 1, + "nbLevel3": 0 + } + }, + { + "GroupStat": { + "group": "INFO", + "nbLevel4": 0, + "nbLevel1": 0, + "nbLevel5": 0, + "nbLevel2": 0, + "nbTotal": 1, + "nbLevel3": 1 + } + } + ], + "count": 2 + }, + "global": { + "nbVulnsLevel3": 1, + "nbVulnsLevel4": 0, + "nbScsLevel5": 0, + "nbVulnsTotal": 2, + "nbScsLevel1": 0, + "nbIgsLevel5": 0, + "nbIgsLevel3": 1, + "nbVulnsLevel5": 0, + "nbScsLevel2": 0, + "nbIgsLevel4": 0, + "nbScsLevel3": 0, + "nbIgsLevel2": 8, + "nbScsTotal": 0, + "nbVulnsLevel1": 0, + "nbIgsTotal": 21, + "nbScsLevel4": 0, + "nbIgsLevel1": 12, + "nbVulnsLevel2": 1 + } + }, + "type": "VULNERABILITY", + "sendOneMail": "false", + "progressiveScanning": "DISABLED", + "options": { + "list": [ + { + "WasScanOption": { + "name": "Web Application Authentication Record Name", + "value": "None" + } + }, + { + "WasScanOption": { + "name": "Sensitive Content: Credit Card Numbers", + "value": "false" + } + }, + { + "WasScanOption": { + "name": "Scan Intensity", + "value": "MEDIUM" + } + }, + { + "WasScanOption": { + "name": "Scanner Appliance", + "value": "External (IP: 64.39.111.235, Scanner: 12.16.55-1, WAS: 8.30.47-1, Signatures: 2.5.955-2)" + } + }, + { + "WasScanOption": { + "name": "Detection Scope", + "value": "CORE" + } + }, + { + "WasScanOption": { + "name": "Option Profile Name", + "value": "Initial WAS Options" + } + }, + { + "WasScanOption": { + "name": "Timeout Error Threshold", + "value": "100" + } + }, + { + "WasScanOption": { + "name": "Web Application Name", + "value": "WAS Test App www.gxmail.com" + } + }, + { + "WasScanOption": { + "name": "Target URL", + "value": "http://www.gxmail.com" + } + }, + { + "WasScanOption": { + "name": "Unexpected Error Threshold", + "value": "300" + } + }, + { + "WasScanOption": { + "name": "Crawling Form Submissions", + "value": "BOTH" + } + }, + { + "WasScanOption": { + "name": "Bruteforce Settings", + "value": "MINIMAL" + } + }, + { + "WasScanOption": { + "name": "Maximum Crawling Links", + "value": "300" + } + }, + { + "WasScanOption": { + "name": "Request Parameter Set", + "value": "Initial Parameters" + } + }, + { + "WasScanOption": { + "name": "Performance Settings", + "value": "Pre-defined" + } + }, + { + "WasScanOption": { + "name": "Sensitive Content: Social Security Numbers (US)", + "value": "false" + } + } + ], + "count": 16 + }, + "scanDuration": 1199, + "igs": { + "list": [ + { + "WasScanIg": { + "qid": 6, + "severity": "1", + "sslData": { + "ip": "144.208.71.150", + "protocol": "tcp", + "result": "#table\nIP_address Host_name\n144.208.71.150 No_registered_hostname\n" + }, + "data": { + "base64": "true", + "value": "I3RhYmxlCklQX2FkZHJlc3MgSG9zdF9uYW1lCgoxNDQuMjA4LjcxLjE1MCBOb19yZWdpc3RlcmVkX2hvc3RuYW1lCg==" + }, + "title": "DNS Host Name" + } + }, + { + "WasScanIg": { + "qid": 150018, + "severity": "2", + "data": { + "base64": "true", + "value": "ClRvdGFsIG51bWJlciBvZiB1bmlxdWUgbGlua3MgdGhhdCBlbmNvdW50ZXJlZCBjb25uZWN0aW9uIGVycm9yczogMQpMaW5rcyB3aXRoIGhpZ2hlc3QgbnVtYmVyIG9mIGNvbm5lY3Rpb24gZXJyb3JzOgogICAxIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8KClBoYXNlIHdpc2Ugc3VtbWFyeSBvZiB0aW1lb3V0IGFuZCBjb25uZWN0aW9uIGVycm9ycyBlbmNvdW50ZXJlZDogCmVQaGFzZUNyYXdsICAgICAgICAgICAgICAgICAgICAgICAgOiAgICAgICAgICAwICAgICAgICAgMQo=" + }, + "title": "Connection Error Occurred During Web Application Scan" + } + }, + { + "WasScanIg": { + "qid": 150208, + "severity": "2", + "data": { + "base64": "true", + "value": "ClJlZmVycmVyLVBvbGljeTogSGVhZGVyIG1pc3NpbmcKUmVzcG9uc2UgaGVhZGVycyBvbiBsaW5rOiBHRVQgaHR0cDovL3d3dy5neG1haWwuY29tLyByZXNwb25zZSBjb2RlOiAyMDAKRGF0ZTogVHVlLCAwOSBKYW4gMjAyNCAxMDo0NjoxNCBHTVQKU2VydmVyOiBBcGFjaGUKVXBncmFkZTogaDIsaDJjCkNvbm5lY3Rpb246IFVwZ3JhZGUsIGNsb3NlCkxhc3QtTW9kaWZpZWQ6IE1vbiwgMjMgSmFuIDIwMTcgMDQ6MzE6MzQgR01UCkFjY2VwdC1SYW5nZXM6IGJ5dGVzCkNvbnRlbnQtTGVuZ3RoOiA0MjkKQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwKCkhlYWRlciBtaXNzaW5nIG9uIHRoZSBmb2xsb3dpbmcgbGluayhzKToKKE9ubHkgZmlyc3QgNTAgc3VjaCBwYWdlcyBhcmUgbGlzdGVkKQoKR0VUIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gcmVzcG9uc2UgY29kZTogMjAwCg==" + }, + "title": "Missing header: Referrer-Policy" + } + }, + { + "WasScanIg": { + "qid": 150020, + "severity": "1", + "data": { + "base64": "true", + "value": "TGlua3Mgbm90IHBlcm1pdHRlZDoKKFRoaXMgbGlzdCBpbmNsdWRlcyBsaW5rcyBmcm9tIFFJRHM6IDE1MDAxMCwxNTAwNDEsMTUwMTQzLDE1MDE3MCkKCklQIGJhc2VkIGV4Y2x1ZGVkIGxpbmtzOgo=" + }, + "title": "Links Rejected By Crawl Scope or Exclusion List" + } + }, + { + "WasScanIg": { + "qid": 150021, + "severity": "1", + "data": { + "base64": "true", + "value": "TG9hZGVkIDAgZXhjbHVkZSBsaXN0IGVudHJpZXMuCkxvYWRlZCAwIGFsbG93IGxpc3QgZW50cmllcy4KSFRNTCBmb3JtIGF1dGhlbnRpY2F0aW9uIHVuYXZhaWxhYmxlLCBubyBXRUJBUFAgZW50cnkgZm91bmQKVGFyZ2V0IHdlYiBhcHBsaWNhdGlvbiBwYWdlIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gZmV0Y2hlZC4gU3RhdHVzIGNvZGU6MjAwLCBDb250ZW50LVR5cGU6dGV4dC9odG1sLCBsb2FkIHRpbWU6MjEgbWlsbGlzZWNvbmRzLgpCYXRjaCAjMCBWaXJ0dWFsSG9zdERpc2NvdmVyeTogZXN0aW1hdGVkIHRpbWUgJmx0OyAxMCBtaW51dGVzICg3MCB0ZXN0cywgMCBpbnB1dHMpClZpcnR1YWxIb3N0RGlzY292ZXJ5OiA3MCB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDY5ICByZXF1ZXN0cywgMjQgc2Vjb25kcy4gQ29tcGxldGVkIDY5IHJlcXVlc3RzIG9mIDcwIGVzdGltYXRlZCByZXF1ZXN0cyAoOTguNTcxNCUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjMCBDTVNEZXRlY3Rpb246IGVzdGltYXRlZCB0aW1lICZsdDsgMTAgbWludXRlcyAoMSB0ZXN0cywgMSBpbnB1dHMpCltDTVNEZXRlY3Rpb24gcGhhc2VdIDogTm8gcG90ZW50aWFsIENNUyBmb3VuZCB1c2luZyBCbGluZCBFbGVwaGFudCBhbGdvcml0aG0uIEFib3J0aW5nIHRoZSBDTVMgRGV0ZWN0aW9uIHBoYXNlCkNNU0RldGVjdGlvbjogMSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDU2ICByZXF1ZXN0cywgNSBzZWNvbmRzLiBDb21wbGV0ZWQgNTYgcmVxdWVzdHMgb2YgNTYgZXN0aW1hdGVkIHJlcXVlc3RzICgxMDAlKS4gQWxsIHRlc3RzIGNvbXBsZXRlZC4KQ29sbGVjdGVkIDEgbGlua3Mgb3ZlcmFsbCBpbiAwIGhvdXJzIDcgbWludXRlcyBkdXJhdGlvbi4KQmF0Y2ggIzAgQmFubmVyc1ZlcnNpb25SZXBvcnRpbmc6IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDEgdGVzdHMsIDEgaW5wdXRzKQpCYW5uZXJzVmVyc2lvblJlcG9ydGluZzogMSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDAgIHJlcXVlc3RzLCAwIHNlY29uZHMuIENvbXBsZXRlZCAwIHJlcXVlc3RzIG9mIDEgZXN0aW1hdGVkIHJlcXVlc3RzICgwJSkuIEFsbCB0ZXN0cyBjb21wbGV0ZWQuClBhdGggbWFuaXB1bGF0aW9uOiBFc3RpbWF0ZWQgcmVxdWVzdHMgKHBheWxvYWRzIHggbGlua3MpOiBmaWxlcyB3aXRoIGV4dGVuc2lvbjooMCB4IDApICsgZmlsZXM6KDAgeCAwKSArICBkaXJlY3RvcmllczooOSB4IDEpICsgIHBhdGhzOigwIHggMSkgPSB0b3RhbCAoOSkgCkJhdGNoICMwIFdTIERpcmVjdG9yeSBQYXRoIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoOSB0ZXN0cywgMSBpbnB1dHMpCldTIERpcmVjdG9yeSBQYXRoIG1hbmlwdWxhdGlvbjogOSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDkgIHJlcXVlc3RzLCA1IHNlY29uZHMuIENvbXBsZXRlZCA5IHJlcXVlc3RzIG9mIDkgZXN0aW1hdGVkIHJlcXVlc3RzICgxMDAlKS4gQWxsIHRlc3RzIGNvbXBsZXRlZC4KQmF0Y2ggIzAgV1MgZW51bWVyYXRpb246IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDExIHRlc3RzLCAxIGlucHV0cykKV1MgZW51bWVyYXRpb246IDExIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMTEgIHJlcXVlc3RzLCA1IHNlY29uZHMuIENvbXBsZXRlZCAxMSByZXF1ZXN0cyBvZiAxMSBlc3RpbWF0ZWQgcmVxdWVzdHMgKDEwMCUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjMSBVUkkgcGFyYW1ldGVyIG1hbmlwdWxhdGlvbiAobm8gYXV0aCk6IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDExMyB0ZXN0cywgMCBpbnB1dHMpCkJhdGNoICMxIFVSSSBwYXJhbWV0ZXIgbWFuaXB1bGF0aW9uIChubyBhdXRoKTogMTEzIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KQmF0Y2ggIzEgVVJJIGJsaW5kIFNRTCBtYW5pcHVsYXRpb24gKG5vIGF1dGgpOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICg4IHRlc3RzLCAwIGlucHV0cykKQmF0Y2ggIzEgVVJJIGJsaW5kIFNRTCBtYW5pcHVsYXRpb24gKG5vIGF1dGgpOiA4IHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KQmF0Y2ggIzEgVVJJIHBhcmFtZXRlciB0aW1lLWJhc2VkIHRlc3RzIChubyBhdXRoKTogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMTYgdGVzdHMsIDAgaW5wdXRzKQpCYXRjaCAjMSBVUkkgcGFyYW1ldGVyIHRpbWUtYmFzZWQgdGVzdHMgKG5vIGF1dGgpOiAxNiB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDAgIHJlcXVlc3RzLCAwIHNlY29uZHMuIE5vIHRlc3RzIHRvIGV4ZWN1dGUuCkJhdGNoICMxIFVSSSBwYXJhbWV0ZXIgdGltZS1iYXNlZCB0ZXN0cyBmb3IgQXBhY2hlIFN0cnV0cyBWdWxuZXJhYmlsaXRpZXMgKG5vIGF1dGgpOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICgxIHRlc3RzLCAwIGlucHV0cykKQmF0Y2ggIzEgVVJJIHBhcmFtZXRlciB0aW1lLWJhc2VkIHRlc3RzIGZvciBBcGFjaGUgU3RydXRzIFZ1bG5lcmFiaWxpdGllcyAobm8gYXV0aCk6IDEgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCAwICByZXF1ZXN0cywgMCBzZWNvbmRzLiBObyB0ZXN0cyB0byBleGVjdXRlLgpCYXRjaCAjNCBXZWJDZ2lPb2I6IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDEzMyB0ZXN0cywgMSBpbnB1dHMpCkJhdGNoICM0IFdlYkNnaU9vYjogMTMzIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMTAwICByZXF1ZXN0cywgNiBzZWNvbmRzLiBDb21wbGV0ZWQgMTAwIHJlcXVlc3RzIG9mIDE1NSBlc3RpbWF0ZWQgcmVxdWVzdHMgKDY0LjUxNjElKS4gQWxsIHRlc3RzIGNvbXBsZXRlZC4KTm8gWE1MIHJlcXVlc3RzIGZvdW5kLiBTa2lwcGluZyBYWEUgdGVzdHMuCkJhdGNoICM0IERPTSBYU1MgZXhwbG9pdGF0aW9uOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICg0IHRlc3RzLCAwIGlucHV0cykKQmF0Y2ggIzQgRE9NIFhTUyBleHBsb2l0YXRpb246IDQgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCAwICByZXF1ZXN0cywgMCBzZWNvbmRzLiBObyB0ZXN0cyB0byBleGVjdXRlLgpCYXRjaCAjNCBIVFRQIGNhbGwgbWFuaXB1bGF0aW9uOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICgzOCB0ZXN0cywgMCBpbnB1dHMpCkJhdGNoICM0IEhUVFAgY2FsbCBtYW5pcHVsYXRpb246IDM4IHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KQmF0Y2ggIzQgT3BlbiBSZWRpcmVjdCBhbmFseXNpczogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMiB0ZXN0cywgMCBpbnB1dHMpCkJhdGNoICM0IE9wZW4gUmVkaXJlY3QgYW5hbHlzaXM6IDIgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCAwICByZXF1ZXN0cywgMiBzZWNvbmRzLiBObyB0ZXN0cyB0byBleGVjdXRlLgpDU1JGIHRlc3RzIHdpbGwgbm90IGJlIGxhdW5jaGVkIGJlY2F1c2UgdGhlIHNjYW4gaXMgbm90IHN1Y2Nlc3NmdWxseSBhdXRoZW50aWNhdGVkLgpCYXRjaCAjNCBGaWxlIEluY2x1c2lvbiBhbmFseXNpczogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMSBpbnB1dHMpCkJhdGNoICM0IEZpbGUgSW5jbHVzaW9uIGFuYWx5c2lzOiAxIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gQ29tcGxldGVkIDAgcmVxdWVzdHMgb2YgMSBlc3RpbWF0ZWQgcmVxdWVzdHMgKDAlKS4gQWxsIHRlc3RzIGNvbXBsZXRlZC4KQmF0Y2ggIzQgQ29va2llIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoNDcgdGVzdHMsIDAgaW5wdXRzKQpCYXRjaCAjNCBDb29raWUgbWFuaXB1bGF0aW9uOiA0NyB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDAgIHJlcXVlc3RzLCAwIHNlY29uZHMuIE5vIHRlc3RzIHRvIGV4ZWN1dGUuCkJhdGNoICM0IEhlYWRlciBtYW5pcHVsYXRpb246IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDQ3IHRlc3RzLCAxIGlucHV0cykKQmF0Y2ggIzQgSGVhZGVyIG1hbmlwdWxhdGlvbjogNDcgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCA2MyAgcmVxdWVzdHMsIDUgc2Vjb25kcy4gQ29tcGxldGVkIDYzIHJlcXVlc3RzIG9mIDEzMCBlc3RpbWF0ZWQgcmVxdWVzdHMgKDQ4LjQ2MTUlKS4gWFNTIG9wdGltaXphdGlvbiByZW1vdmVkIDI5IGxpbmtzLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjNCBzaGVsbCBzaG9jayBkZXRlY3RvcjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMSBpbnB1dHMpCkJhdGNoICM0IHNoZWxsIHNob2NrIGRldGVjdG9yOiAxIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMSAgcmVxdWVzdHMsIDQgc2Vjb25kcy4gQ29tcGxldGVkIDEgcmVxdWVzdHMgb2YgMSBlc3RpbWF0ZWQgcmVxdWVzdHMgKDEwMCUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjNCBzaGVsbCBzaG9jayBkZXRlY3Rvcihmb3JtKTogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMCBpbnB1dHMpCkJhdGNoICM0IHNoZWxsIHNob2NrIGRldGVjdG9yKGZvcm0pOiAxIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KQ29va2llcyBXaXRob3V0IENvbnNlbnQgbm8gdGVzdHMgZW5hYmxlZC4KQmF0Y2ggIzUgSFRUUCBUaW1lIEJhbmRpdDogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMTAgaW5wdXRzKQpCYXRjaCAjNSBIVFRQIFRpbWUgQmFuZGl0OiAxIHZ1bG5zaWdzIHRlc3RzLCBjb21wbGV0ZWQgMCAgcmVxdWVzdHMsIDAgc2Vjb25kcy4gTm8gdGVzdHMgdG8gZXhlY3V0ZS4KUGF0aCBtYW5pcHVsYXRpb246IEVzdGltYXRlZCByZXF1ZXN0cyAocGF5bG9hZHMgeCBsaW5rcyk6IGZpbGVzIHdpdGggZXh0ZW5zaW9uOigwIHggMCkgKyBmaWxlczooMCB4IDApICsgIGRpcmVjdG9yaWVzOig0IHggMSkgKyAgcGF0aHM6KDExIHggMSkgPSB0b3RhbCAoMTUpIApCYXRjaCAjNSBQYXRoIFhTUyBtYW5pcHVsYXRpb246IGVzdGltYXRlZCB0aW1lICZsdDsgMSBtaW51dGUgKDE1IHRlc3RzLCAxIGlucHV0cykKQmF0Y2ggIzUgUGF0aCBYU1MgbWFuaXB1bGF0aW9uOiAxNSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDE0ICByZXF1ZXN0cywgNSBzZWNvbmRzLiBDb21wbGV0ZWQgMTQgcmVxdWVzdHMgb2YgMTUgZXN0aW1hdGVkIHJlcXVlc3RzICg5My4zMzMzJSkuIEFsbCB0ZXN0cyBjb21wbGV0ZWQuClBhdGggbWFuaXB1bGF0aW9uOiBFc3RpbWF0ZWQgcmVxdWVzdHMgKHBheWxvYWRzIHggbGlua3MpOiBmaWxlcyB3aXRoIGV4dGVuc2lvbjooMCB4IDApICsgZmlsZXM6KDAgeCAwKSArICBkaXJlY3RvcmllczooMSB4IDEpICsgIHBhdGhzOigwIHggMSkgPSB0b3RhbCAoMSkgCkJhdGNoICM1IFRvbWNhdCBWdWxuIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMSB0ZXN0cywgMSBpbnB1dHMpCkJhdGNoICM1IFRvbWNhdCBWdWxuIG1hbmlwdWxhdGlvbjogMSB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDEgIHJlcXVlc3RzLCAxOCBzZWNvbmRzLiBDb21wbGV0ZWQgMSByZXF1ZXN0cyBvZiAxIGVzdGltYXRlZCByZXF1ZXN0cyAoMTAwJSkuIEFsbCB0ZXN0cyBjb21wbGV0ZWQuClBhdGggbWFuaXB1bGF0aW9uOiBFc3RpbWF0ZWQgcmVxdWVzdHMgKHBheWxvYWRzIHggbGlua3MpOiBmaWxlcyB3aXRoIGV4dGVuc2lvbjooMCB4IDApICsgZmlsZXM6KDAgeCAwKSArICBkaXJlY3RvcmllczooMTYgeCAxKSArICBwYXRoczooMCB4IDEpID0gdG90YWwgKDE2KSAKQmF0Y2ggIzUgVGltZSBiYXNlZCBwYXRoIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMTYgdGVzdHMsIDIgaW5wdXRzKQpCYXRjaCAjNSBUaW1lIGJhc2VkIHBhdGggbWFuaXB1bGF0aW9uOiAxNiB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDE2ICByZXF1ZXN0cywgMjQwIHNlY29uZHMuIENvbXBsZXRlZCAxNiByZXF1ZXN0cyBvZiAxNiBlc3RpbWF0ZWQgcmVxdWVzdHMgKDEwMCUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpQYXRoIG1hbmlwdWxhdGlvbjogRXN0aW1hdGVkIHJlcXVlc3RzIChwYXlsb2FkcyB4IGxpbmtzKTogZmlsZXMgd2l0aCBleHRlbnNpb246KDEgeCAwKSArIGZpbGVzOigxMiB4IDApICsgIGRpcmVjdG9yaWVzOigxNDMgeCAxKSArICBwYXRoczooMTQgeCAxKSA9IHRvdGFsICgxNTcpIApCYXRjaCAjNSBQYXRoIG1hbmlwdWxhdGlvbjogZXN0aW1hdGVkIHRpbWUgJmx0OyAxIG1pbnV0ZSAoMTcwIHRlc3RzLCAxIGlucHV0cykKQmF0Y2ggIzUgUGF0aCBtYW5pcHVsYXRpb246IDE3MCB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDE1MSAgcmVxdWVzdHMsIDUgc2Vjb25kcy4gQ29tcGxldGVkIDE1MSByZXF1ZXN0cyBvZiAxNTcgZXN0aW1hdGVkIHJlcXVlc3RzICg5Ni4xNzgzJSkuIEFsbCB0ZXN0cyBjb21wbGV0ZWQuCldlYkNnaUhyc1Rlc3RzOiBubyB0ZXN0IGVuYWJsZWQKQmF0Y2ggIzUgV2ViQ2dpR2VuZXJpYzogZXN0aW1hdGVkIHRpbWUgJmx0OyAxMCBtaW51dGVzICg0NTEgdGVzdHMsIDEgaW5wdXRzKQpCYXRjaCAjNSBXZWJDZ2lHZW5lcmljOiA0NTEgdnVsbnNpZ3MgdGVzdHMsIGNvbXBsZXRlZCAxNzcgIHJlcXVlc3RzLCA2IHNlY29uZHMuIENvbXBsZXRlZCAxNzcgcmVxdWVzdHMgb2YgNjA1IGVzdGltYXRlZCByZXF1ZXN0cyAoMjkuMjU2MiUpLiBBbGwgdGVzdHMgY29tcGxldGVkLgpCYXRjaCAjNSBPcGVuIFJlZGlyZWN0IGFuYWx5c2lzOiBlc3RpbWF0ZWQgdGltZSAmbHQ7IDEgbWludXRlICgyIHRlc3RzLCAwIGlucHV0cykKQmF0Y2ggIzUgT3BlbiBSZWRpcmVjdCBhbmFseXNpczogMiB2dWxuc2lncyB0ZXN0cywgY29tcGxldGVkIDAgIHJlcXVlc3RzLCA1IHNlY29uZHMuIE5vIHRlc3RzIHRvIGV4ZWN1dGUuCkR1cmF0aW9uIG9mIENyYXdsIFRpbWU6IDQ2MC4wMCAoc2Vjb25kcykKRHVyYXRpb24gb2YgVGVzdCBQaGFzZTogNzMyLjAwIChzZWNvbmRzKQpUb3RhbCBTY2FuIFRpbWU6IDExOTIuMDAgKHNlY29uZHMpCgpUb3RhbCByZXF1ZXN0cyBtYWRlOiA3MDAKQXZlcmFnZSBzZXJ2ZXIgcmVzcG9uc2UgdGltZTogMC41NyBzZWNvbmRzCgpBdmVyYWdlIGJyb3dzZXIgbG9hZCB0aW1lOiAwLjkzIHNlY29uZHMK" + }, + "title": "Scan Diagnostics" + } + }, + { + "WasScanIg": { + "qid": 150086, + "severity": "3", + "data": { + "base64": "true", + "value": "U2VydmVyIHJlc3BvbmRlZCAyMDAgdG8gdW5uZWNlc3NhcmlseSBsYXJnZSByYW5kb20gcmVxdWVzdCBib2R5KG92ZXIgNjQgS0IpIGZvciBVUkwgaHR0cDovL3d3dy5neG1haWwuY29tLywgc2lnbmlmaWNhbnRseSBpbmNyZWFzaW5nIGF0dGFja2VyJ3MgY2hhbmNlcyB0byBwcm9sb25nIHNsb3cgSFRUUCBQT1NUIGF0dGFjay4=" + }, + "title": "Server accepts unnecessarily large POST request body" + } + }, + { + "WasScanIg": { + "qid": 150247, + "severity": "1", + "data": { + "base64": "true", + "value": "Ck51bWJlciBvZiB0ZWNobm9sb2dpZXMgZGV0ZWN0ZWQ6IDEKVGVjaG5vbG9neSBuYW1lOiBBcGFjaGUKTWF0Y2hlZCBDb21wb25lbnRzOgpoZWFkZXIgbWF0Y2g6CiAgU2VydmVyOkFwYWNoZQpNYXRjaGVkIGxpbmtzOiByZXBvcnRpbmcgb25seSBmaXJzdCAzIGxpbmtzCmh0dHA6Ly93d3cuZ3htYWlsLmNvbS8KCg==" + }, + "title": "Web Server and Technologies Detected" + } + }, + { + "WasScanIg": { + "qid": 150245, + "severity": "1", + "data": { + "base64": "true", + "value": "WC1GcmFtZS1PcHRpb25zIGhlYWRlciBpcyBtaXNzaW5nIG9yIG5vdCBzZXQgdG8gREVOWSBvciBTQU1FT1JJR0lOIGZvciB0aGUgZm9sbG93aW5nIHBhZ2VzOgooT25seSBmaXJzdCAxMCBzdWNoIHBhZ2VzIGFyZSByZXBvcnRlZCkKCkdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vClJlc3BvbnNlIGNvZGU6IDIwMApSZXNwb25zZSBoZWFkZXJzOiAKRGF0ZTogVHVlLCAwOSBKYW4gMjAyNCAxMDo0NjoxNCBHTVQKU2VydmVyOiBBcGFjaGUKVXBncmFkZTogaDIsaDJjCkNvbm5lY3Rpb246IFVwZ3JhZGUsIGNsb3NlCkxhc3QtTW9kaWZpZWQ6IE1vbiwgMjMgSmFuIDIwMTcgMDQ6MzE6MzQgR01UCkFjY2VwdC1SYW5nZXM6IGJ5dGVzCkNvbnRlbnQtTGVuZ3RoOiA0MjkKQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwKCg==" + }, + "title": "Missing header: X-Frame-Options" + } + }, + { + "WasScanIg": { + "qid": 150152, + "severity": "1", + "data": { + "base64": "true", + "value": "VG90YWwgaW50ZXJuYWwgZm9ybXMgc2VlbiAodGhpcyBjb3VudCBpbmNsdWRlcyBkdXBsaWNhdGUgZm9ybXMpOiAwCgpDcmF3bGVkIGZvcm1zIChUb3RhbDogMCkKTk9URTogVGhpcyBkb2VzIG5vdCBpbmNsdWRlIGF1dGhlbnRpY2F0aW9uIGZvcm1zLiBBdXRoZW50aWNhdGlvbiBmb3JtcyBhcmUgcmVwb3J0ZWQgc2VwYXJhdGVseSBpbiBRSUQgMTUwMTE1Cg==" + }, + "title": "Forms Crawled" + } + }, + { + "WasScanIg": { + "qid": 150248, + "severity": "2", + "data": { + "base64": "true", + "value": "ClBlcm1pc3Npb25zLVBvbGljeTogSGVhZGVyIG1pc3NpbmcKUmVzcG9uc2UgaGVhZGVycyBvbiBsaW5rOiBHRVQgaHR0cDovL3d3dy5neG1haWwuY29tLyByZXNwb25zZSBjb2RlOiAyMDAKRGF0ZTogVHVlLCAwOSBKYW4gMjAyNCAxMDo0NjoxNCBHTVQKU2VydmVyOiBBcGFjaGUKVXBncmFkZTogaDIsaDJjCkNvbm5lY3Rpb246IFVwZ3JhZGUsIGNsb3NlCkxhc3QtTW9kaWZpZWQ6IE1vbiwgMjMgSmFuIDIwMTcgMDQ6MzE6MzQgR01UCkFjY2VwdC1SYW5nZXM6IGJ5dGVzCkNvbnRlbnQtTGVuZ3RoOiA0MjkKQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwKCkhlYWRlciBtaXNzaW5nIG9uIHRoZSBmb2xsb3dpbmcgbGluayhzKToKKE9ubHkgZmlyc3QgNTAgc3VjaCBwYWdlcyBhcmUgbGlzdGVkKQoKR0VUIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gcmVzcG9uc2UgY29kZTogMjAwCg==" + }, + "title": "Missing header: Permissions-Policy" + } + }, + { + "WasScanIg": { + "qid": 45038, + "severity": "1", + "data": { + "base64": "true", + "value": "U2NhbiBkdXJhdGlvbjogMTE5OSBzZWNvbmRzCgpTdGFydCB0aW1lOiBUdWUsIEphbiAwOSAyMDI0LCAxMDo0NDoxNyBHTVQKCkVuZCB0aW1lOiBUdWUsIEphbiAwOSAyMDI0LCAxMTowNDoxNiBHTVQK" + }, + "title": "Host Scan Time - Scanner" + } + }, + { + "WasScanIg": { + "qid": 150546, + "severity": "1", + "data": { + "base64": "true", + "value": "QmFzZSBVUkk6IGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8KUmVzcG9uc2UgQ29kZTogMjAwClJlc3BvbnNlIEhlYWRlcjogCiBEYXRlOiBUdWUsIDA5IEphbiAyMDI0IDEwOjQ2OjE0IEdNVAogU2VydmVyOiBBcGFjaGUKIFVwZ3JhZGU6IGgyLGgyYwogQ29ubmVjdGlvbjogVXBncmFkZSwgY2xvc2UKIExhc3QtTW9kaWZpZWQ6IE1vbiwgMjMgSmFuIDIwMTcgMDQ6MzE6MzQgR01UCiBBY2NlcHQtUmFuZ2VzOiBieXRlcwogQ29udGVudC1MZW5ndGg6IDQyOQogQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwKIApSZXNwb25zZSBCb2R5OiAKICZsdDshRE9DVFlQRSBodG1sIFBVQkxJQyAiLS8vVzNDLy9EVEQgWEhUTUwgMS4wIFRyYW5zaXRpb25hbC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi94aHRtbDEvRFREL3hodG1sMS10cmFuc2l0aW9uYWwuZHRkIiZndDsmbHQ7aHRtbCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCImZ3Q7Jmx0O2hlYWQmZ3Q7CiAmbHQ7bWV0YSBodHRwLWVxdWl2PSJDb250ZW50LVR5cGUiIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD1pc28tODg1OS0xIiZndDsKICZsdDt0aXRsZSZndDtneG1haWwuY29tIC0gUHJpdmF0ZSBkb21haW4mbHQ7L3RpdGxlJmd0OwogJmx0Oy9oZWFkJmd0OwogJmx0O2JvZHkmZ3Q7CiAmbHQ7cCBhbGlnbj0iY2VudGVyIiZndDsmbHQ7aW1nIHNyYz0iZ3htYWlsLnBuZyIgYWx0PSJneG1haWwuY29tIC0gUHJpdmF0ZSBkb21haW4iIHdpZHRoPSIzMjciIGhlaWdodD0iMTk4IiZndDsmbHQ7L3AmZ3Q7CiAKIAogCiAmbHQ7L2JvZHkmZ3Q7Jmx0Oy9odG1sJmd0OwogCg==" + }, + "title": "First Link Crawled Response Code Information" + } + }, + { + "WasScanIg": { + "qid": 150262, + "severity": "2", + "data": { + "base64": "true", + "value": "CkZlYXR1cmUtUG9saWN5OiBIZWFkZXIgbWlzc2luZwpSZXNwb25zZSBoZWFkZXJzIG9uIGxpbms6IEdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vIHJlc3BvbnNlIGNvZGU6IDIwMApEYXRlOiBUdWUsIDA5IEphbiAyMDI0IDEwOjQ2OjE0IEdNVApTZXJ2ZXI6IEFwYWNoZQpVcGdyYWRlOiBoMixoMmMKQ29ubmVjdGlvbjogVXBncmFkZSwgY2xvc2UKTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQKQWNjZXB0LVJhbmdlczogYnl0ZXMKQ29udGVudC1MZW5ndGg6IDQyOQpDb250ZW50LVR5cGU6IHRleHQvaHRtbAoKSGVhZGVyIG1pc3Npbmcgb24gdGhlIGZvbGxvd2luZyBsaW5rKHMpOgooT25seSBmaXJzdCA1MCBzdWNoIHBhZ2VzIGFyZSBsaXN0ZWQpCgpHRVQgaHR0cDovL3d3dy5neG1haWwuY29tLyByZXNwb25zZSBjb2RlOiAyMDAK" + }, + "title": "Missing header: Feature-Policy" + } + }, + { + "WasScanIg": { + "qid": 150202, + "severity": "2", + "data": { + "base64": "true", + "value": "ClgtQ29udGVudC1UeXBlLU9wdGlvbnM6IEhlYWRlciBtaXNzaW5nClJlc3BvbnNlIGhlYWRlcnMgb24gbGluazogR0VUIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gcmVzcG9uc2UgY29kZTogMjAwCkRhdGU6IFR1ZSwgMDkgSmFuIDIwMjQgMTA6NDY6MTQgR01UClNlcnZlcjogQXBhY2hlClVwZ3JhZGU6IGgyLGgyYwpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQpMYXN0LU1vZGlmaWVkOiBNb24sIDIzIEphbiAyMDE3IDA0OjMxOjM0IEdNVApBY2NlcHQtUmFuZ2VzOiBieXRlcwpDb250ZW50LUxlbmd0aDogNDI5CkNvbnRlbnQtVHlwZTogdGV4dC9odG1sCgpIZWFkZXIgbWlzc2luZyBvbiB0aGUgZm9sbG93aW5nIGxpbmsocyk6CihPbmx5IGZpcnN0IDUwIHN1Y2ggcGFnZXMgYXJlIGxpc3RlZCkKCkdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vIHJlc3BvbnNlIGNvZGU6IDIwMAo=" + }, + "title": "Missing header: X-Content-Type-Options" + } + }, + { + "WasScanIg": { + "qid": 45017, + "severity": "2", + "sslData": { + "sslDataInfoList": { + "list": [ + { + "SSLDataInfo": { + "sslDataCipherList": {}, + "sslDataPropList": {}, + "sslDataKexList": {} + } + } + ] + }, + "ip": "144.208.71.150", + "protocol": "tcp", + "result": "EulerOS_/_Ubuntu_/_Fedora_/_Tiny_Core_Linux_/_Linux_3.x_/_IBM_/_FortiSOAR_/_F5_Networks_Big-IP TCP/IP_Fingerprint M5933:7322::80\n" + }, + "data": { + "base64": "true", + "value": "RXVsZXJPU18vX1VidW50dV8vX0ZlZG9yYV8vX1RpbnlfQ29yZV9MaW51eF8vX0xpbnV4XzMueF8vX0lCTV8vX0ZvcnRpU09BUl8vX0Y1X05ldHdvcmtzX0JpZy1JUCBUQ1AvSVBfRmluZ2VycHJpbnQgTTU5MzM6NzMyMjo6ODAK" + }, + "title": "Operating System Detected" + } + }, + { + "WasScanIg": { + "qid": 150009, + "severity": "1", + "data": { + "base64": "true", + "value": "RHVyYXRpb24gb2YgY3Jhd2wgcGhhc2UgKHNlY29uZHMpOiA0NjAuMDAKTnVtYmVyIG9mIGxpbmtzOiAxCihUaGlzIG51bWJlciBleGNsdWRlcyBmb3JtIHJlcXVlc3RzIGFuZCBsaW5rcyByZS1yZXF1ZXN0ZWQgZHVyaW5nIGF1dGhlbnRpY2F0aW9uLikKCmh0dHA6Ly93d3cuZ3htYWlsLmNvbS8K" + }, + "title": "Links Crawled" + } + }, + { + "WasScanIg": { + "qid": 150142, + "severity": "1", + "data": { + "base64": "true", + "value": "VmlydHVhbCBob3N0IGRpc2NvdmVyZWQ6CgpEZXRlY3RlZCBiYXNlZCBvbjogVW5pcXVlIHBhZ2UgY29udGVudApWaXJ0dWFsIEhvc3Q6IHdlYm1haWwud3d3Lmd4bWFpbC5jb20KVVJJOiBodHRwOi8vd3d3Lmd4bWFpbC5jb20vCgpEZXRlY3RlZCBiYXNlZCBvbjogVW5pcXVlIHBhZ2UgY29udGVudApWaXJ0dWFsIEhvc3Q6IG1haWwuZ3htYWlsLmNvbQpVUkk6IGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8KCkRldGVjdGVkIGJhc2VkIG9uOiBVbmlxdWUgcGFnZSBjb250ZW50ClZpcnR1YWwgSG9zdDogd2VibWFpbC5neG1haWwuY29tClVSSTogaHR0cDovL3d3dy5neG1haWwuY29tLwo=" + }, + "title": "Virtual Host Discovered" + } + }, + { + "WasScanIg": { + "qid": 150206, + "severity": "2", + "data": { + "base64": "true", + "value": "CkNvbnRlbnQtU2VjdXJpdHktUG9saWN5OiBIZWFkZXIgbWlzc2luZwpSZXNwb25zZSBoZWFkZXJzIG9uIGxpbms6IEdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vIHJlc3BvbnNlIGNvZGU6IDIwMApEYXRlOiBUdWUsIDA5IEphbiAyMDI0IDEwOjQ2OjE0IEdNVApTZXJ2ZXI6IEFwYWNoZQpVcGdyYWRlOiBoMixoMmMKQ29ubmVjdGlvbjogVXBncmFkZSwgY2xvc2UKTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQKQWNjZXB0LVJhbmdlczogYnl0ZXMKQ29udGVudC1MZW5ndGg6IDQyOQpDb250ZW50LVR5cGU6IHRleHQvaHRtbAoKSGVhZGVyIG1pc3Npbmcgb24gdGhlIGZvbGxvd2luZyBsaW5rKHMpOgooT25seSBmaXJzdCA1MCBzdWNoIHBhZ2VzIGFyZSBsaXN0ZWQpCgpHRVQgaHR0cDovL3d3dy5neG1haWwuY29tLyByZXNwb25zZSBjb2RlOiAyMDAK" + }, + "title": "Content-Security-Policy Not Implemented" + } + }, + { + "WasScanIg": { + "qid": 150204, + "severity": "1", + "data": { + "base64": "true", + "value": "ClgtWHNzLVByb3RlY3Rpb246IEhlYWRlciBtaXNzaW5nClJlc3BvbnNlIGhlYWRlcnMgb24gbGluazogR0VUIGh0dHA6Ly93d3cuZ3htYWlsLmNvbS8gcmVzcG9uc2UgY29kZTogMjAwCkRhdGU6IFR1ZSwgMDkgSmFuIDIwMjQgMTA6NDY6MTQgR01UClNlcnZlcjogQXBhY2hlClVwZ3JhZGU6IGgyLGgyYwpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQpMYXN0LU1vZGlmaWVkOiBNb24sIDIzIEphbiAyMDE3IDA0OjMxOjM0IEdNVApBY2NlcHQtUmFuZ2VzOiBieXRlcwpDb250ZW50LUxlbmd0aDogNDI5CkNvbnRlbnQtVHlwZTogdGV4dC9odG1sCgpIZWFkZXIgbWlzc2luZyBvbiB0aGUgZm9sbG93aW5nIGxpbmsocyk6CihPbmx5IGZpcnN0IDUwIHN1Y2ggcGFnZXMgYXJlIGxpc3RlZCkKCkdFVCBodHRwOi8vd3d3Lmd4bWFpbC5jb20vIHJlc3BvbnNlIGNvZGU6IDIwMAo=" + }, + "title": "Missing header: X-XSS-Protection" + } + } + ], + "count": 19 + }, + "status": "FINISHED", + "target": { + "cancelOption": "SPECIFIC", + "scannerAppliance": { + "type": "EXTERNAL" + }, + "randomizeScan": "false", + "webApp": { + "id": 1069358967, + "url": "http://www.gxmail.com", + "name": "WAS Test App www.gxmail.com" + } + }, + "id": 38847527, + "multi": "false", + "consolidatedStatus": "FINISHED", + "launchedDate": "2024-01-09T10:44:18Z", + "mode": "API", + "name": "New WAS Vulnerability Scan launched from API_2024-01-09-16-13", + "reference": "was/1704797014773.62436158", + "enableWAFAuth": "false", + "endScanDate": "2024-01-09T11:04:17Z", + "summary": { + "testDuration": 733, + "authStatus": "NONE", + "nbRequests": 700, + "linksCrawled": 1, + "resultsStatus": "SUCCESSFUL", + "crawlDuration": 460, + "os": "EulerOS / Ubuntu / Fedora / Tiny Core Linux / Linux 3.x / IBM / FortiSOAR / F5 Networks Big-IP" + }, + "launchedBy": { + "id": 105571763, + "firstName": "Prabhas", + "username": "quays_pg19", + "lastName": "Gupte" + }, + "sendMail": "true", + "sensitiveContents": { + "count": 0 + }, + "vulns": { + "list": [ + { + "WasScanVuln": { + "severity": "3", + "uri": "http://www.gxmail.com/", + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "authenticated": "false", + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "payload": "", + "result": { + "base64": "true", + "value": "SFRUUC8xLjEgMjAwIE9LCkRhdGU6IFR1ZSwgMDkgSmFuIDIwMjQgMTA6NDY6MTQgR01UDQpTZXJ2ZXI6IEFwYWNoZQ0KVXBncmFkZTogaDIsaDJjDQpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQ0KTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQNCkFjY2VwdC1SYW5nZXM6IGJ5dGVzDQpDb250ZW50LUxlbmd0aDogNDI5DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KCiZsdDshRE9DVFlQRSBodG1sIFBVQkxJQyAiLS8vVzNDLy9EVEQgWEhUTUwgMS4wIFRyYW5zaXRpb25hbC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi94aHRtbDEvRFREL3hodG1sMS10cmFuc2l0aW9uYWwuZHRkIiZndDsmbHQ7aHRtbCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCImZ3Q7Jmx0O2hlYWQmZ3Q7CiZsdDttZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PWlzby04ODU5LTEiJmd0OwombHQ7dGl0bGUmZ3Q7Z3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluJmx0Oy90aXRsZSZndDsKJmx0Oy9oZWFkJmd0OwombHQ7Ym9keSZndDsKJmx0O3AgYWxpZ249ImNlbnRlciImZ3Q7Jmx0O2ltZyBzcmM9Imd4bWFpbC5wbmciIGFsdD0iZ3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluIiB3aWR0aD0iMzI3IiBoZWlnaHQ9IjE5OCImZ3Q7Jmx0Oy9wJmd0OwoKCgombHQ7L2JvZHkmZ3Q7Jmx0Oy9odG1sJmd0Ow==" + } + } + } + ], + "count": 1 + } + } + } + ], + "count": 1 + }, + "potential": "false", + "qid": 150263, + "title": "Insecure Transport" + } + }, + { + "WasScanVuln": { + "severity": "2", + "uri": "http://www.gxmail.com/webmail/", + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "authenticated": "false", + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "payload": "http://www.gxmail.com/webmail/", + "result": { + "base64": "true", + "value": "Y29tbWVudDogCk9yaWdpbmFsIFVSTCBpczogaHR0cDovL3d3dy5neG1haWwuY29tLwoKSFRUUC8xLjEgMjAwIE9L" + } + } + } + ], + "count": 1 + } + } + } + ], + "count": 1 + }, + "potential": "false", + "qid": 150004, + "title": "Path-Based Vulnerability" + } + } + ], + "count": 2 + }, + "profile": { + "id": 50723, + "name": "Initial WAS Options" + } + } + } + ] +} \ No newline at end of file diff --git a/src/test/java/test_data/test_vulnerabilityArray_mockData.json b/src/test/java/test_data/test_vulnerabilityArray_mockData.json new file mode 100644 index 0000000..a36317d --- /dev/null +++ b/src/test/java/test_data/test_vulnerabilityArray_mockData.json @@ -0,0 +1,71 @@ +{ + "list": [ + { + "WasScanVuln": { + "severity": "3", + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "result": { + "base64": "true", + "value": "SFRUUC8xLjEgMjAwIE9LCkRhdGU6IFR1ZSwgMDkgSmFuIDIwMjQgMTA6NDY6MTQgR01UDQpTZXJ2ZXI6IEFwYWNoZQ0KVXBncmFkZTogaDIsaDJjDQpDb25uZWN0aW9uOiBVcGdyYWRlLCBjbG9zZQ0KTGFzdC1Nb2RpZmllZDogTW9uLCAyMyBKYW4gMjAxNyAwNDozMTozNCBHTVQNCkFjY2VwdC1SYW5nZXM6IGJ5dGVzDQpDb250ZW50LUxlbmd0aDogNDI5DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KCiZsdDshRE9DVFlQRSBodG1sIFBVQkxJQyAiLS8vVzNDLy9EVEQgWEhUTUwgMS4wIFRyYW5zaXRpb25hbC8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9UUi94aHRtbDEvRFREL3hodG1sMS10cmFuc2l0aW9uYWwuZHRkIiZndDsmbHQ7aHRtbCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCImZ3Q7Jmx0O2hlYWQmZ3Q7CiZsdDttZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PWlzby04ODU5LTEiJmd0OwombHQ7dGl0bGUmZ3Q7Z3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluJmx0Oy90aXRsZSZndDsKJmx0Oy9oZWFkJmd0OwombHQ7Ym9keSZndDsKJmx0O3AgYWxpZ249ImNlbnRlciImZ3Q7Jmx0O2ltZyBzcmM9Imd4bWFpbC5wbmciIGFsdD0iZ3htYWlsLmNvbSAtIFByaXZhdGUgZG9tYWluIiB3aWR0aD0iMzI3IiBoZWlnaHQ9IjE5OCImZ3Q7Jmx0Oy9wJmd0OwoKCgombHQ7L2JvZHkmZ3Q7Jmx0Oy9odG1sJmd0Ow==" + }, + "payload": "" + } + } + ], + "count": 1 + }, + "authenticated": "false" + } + } + ], + "count": 1 + }, + "potential": "false", + "qid": 150263, + "uri": "http://www.gxmail.com/", + "title": "Insecure Transport" + } + }, + { + "WasScanVuln": { + "severity": "2", + "instances": { + "list": [ + { + "WasScanVulnInstance": { + "payloads": { + "list": [ + { + "WasScanVulnPayload": { + "result": { + "base64": "true", + "value": "Y29tbWVudDogCk9yaWdpbmFsIFVSTCBpczogaHR0cDovL3d3dy5neG1haWwuY29tLwoKSFRUUC8xLjEgMjAwIE9L" + }, + "payload": "http://www.gxmail.com/webmail/" + } + } + ], + "count": 1 + }, + "authenticated": "false" + } + } + ], + "count": 1 + }, + "potential": "false", + "qid": 150004, + "uri": "http://www.gxmail.com/webmail/", + "title": "Path-Based Vulnerability" + } + } + ], + "count": 2 +} \ No newline at end of file