├── LICENSE ├── anchore-engine └── docker-compose.yml ├── dependency_track └── docker-compose.yml ├── docker-compose.override.yml ├── docker-compose.yml ├── juice-shop ├── Jenkinsfile └── frontend │ ├── .browserslistrc │ ├── .editorconfig │ ├── .eslintrc.js │ ├── .gitignore │ ├── .npmrc │ ├── .stylelintrc.js │ └── src │ └── polyfills.ts └── readme /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Chris Jackson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /anchore-engine/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # This is a docker-compose file for development purposes. It references unstable 2 | # developer builds from the HEAD of master branch in 3 | # https://github.com/anchore/anchore-engine For a compose file intended for use 4 | # with a released version, see 5 | # https://docs.anchore.com/current/docs/engine/quickstart/ 6 | # 7 | --- 8 | version: "2.1" 9 | volumes: 10 | anchore-db-volume: 11 | # Set this to 'true' to use an external volume. In which case, it must be 12 | # created manually with "docker volume create anchore-db-volume" 13 | external: false 14 | 15 | networks: 16 | default: 17 | driver: bridge 18 | name: lab 19 | 20 | services: 21 | # The primary API endpoint service 22 | api: 23 | image: anchore/anchore-engine:v0.7.3 24 | depends_on: 25 | - db 26 | - catalog 27 | ports: 28 | - "8228:8228" 29 | logging: 30 | driver: "json-file" 31 | options: 32 | max-size: 100m 33 | environment: 34 | - ANCHORE_ENDPOINT_HOSTNAME=api 35 | - ANCHORE_DB_HOST=db 36 | - ANCHORE_DB_PASSWORD=mysecretpassword 37 | command: ["anchore-manager", "service", "start", "apiext"] 38 | restart: unless-stopped 39 | 40 | # Catalog is the primary persistence and state manager of the system 41 | catalog: 42 | image: anchore/anchore-engine:v0.7.3 43 | depends_on: 44 | - db 45 | logging: 46 | driver: "json-file" 47 | options: 48 | max-size: 100m 49 | expose: 50 | - 8228 51 | environment: 52 | - ANCHORE_ENDPOINT_HOSTNAME=catalog 53 | - ANCHORE_DB_HOST=db 54 | - ANCHORE_DB_PASSWORD=mysecretpassword 55 | command: ["anchore-manager", "service", "start", "catalog"] 56 | restart: unless-stopped 57 | queue: 58 | image: anchore/anchore-engine:v0.7.3 59 | depends_on: 60 | - db 61 | - catalog 62 | expose: 63 | - 8228 64 | logging: 65 | driver: "json-file" 66 | options: 67 | max-size: 100m 68 | environment: 69 | - ANCHORE_ENDPOINT_HOSTNAME=queue 70 | - ANCHORE_DB_HOST=db 71 | - ANCHORE_DB_PASSWORD=mysecretpassword 72 | command: ["anchore-manager", "service", "start", "simplequeue"] 73 | restart: unless-stopped 74 | policy-engine: 75 | image: anchore/anchore-engine:v0.7.3 76 | depends_on: 77 | - db 78 | - catalog 79 | expose: 80 | - 8228 81 | logging: 82 | driver: "json-file" 83 | options: 84 | max-size: 100m 85 | environment: 86 | - ANCHORE_ENDPOINT_HOSTNAME=policy-engine 87 | - ANCHORE_DB_HOST=db 88 | - ANCHORE_DB_PASSWORD=mysecretpassword 89 | command: ["anchore-manager", "service", "start", "policy_engine"] 90 | restart: unless-stopped 91 | analyzer: 92 | image: anchore/anchore-engine:v0.7.3 93 | depends_on: 94 | - db 95 | - catalog 96 | expose: 97 | - 8228 98 | logging: 99 | driver: "json-file" 100 | options: 101 | max-size: 100m 102 | environment: 103 | - ANCHORE_ENDPOINT_HOSTNAME=analyzer 104 | - ANCHORE_DB_HOST=db 105 | - ANCHORE_DB_PASSWORD=mysecretpassword 106 | volumes: 107 | - /analysis_scratch 108 | command: ["anchore-manager", "service", "start", "analyzer"] 109 | restart: unless-stopped 110 | db: 111 | image: "postgres:9" 112 | volumes: 113 | - anchore-db-volume:/var/lib/postgresql/data 114 | environment: 115 | - POSTGRES_PASSWORD=mysecretpassword 116 | expose: 117 | - 5432 118 | logging: 119 | driver: "json-file" 120 | options: 121 | max-size: 100m 122 | healthcheck: 123 | test: ["CMD-SHELL", "pg_isready -U postgres"] 124 | restart: unless-stopped 125 | -------------------------------------------------------------------------------- /dependency_track/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | ##################################################### 4 | # This Docker Compose file contains two services 5 | # Dependency-Track API Server 6 | # Dependency-Track FrontEnd 7 | ##################################################### 8 | 9 | volumes: 10 | dependency-track: 11 | 12 | services: 13 | dtrack-apiserver: 14 | image: dependencytrack/apiserver 15 | # environment: 16 | # The Dependency-Track container can be configured using any of the 17 | # available configuration properties defined in: 18 | # https://docs.dependencytrack.org/getting-started/configuration/ 19 | # All properties are upper case with periods replaced by underscores. 20 | # 21 | # Database Properties 22 | # - ALPINE_DATABASE_MODE=external 23 | # - ALPINE_DATABASE_URL=jdbc:postgresql://postgres10:5432/dtrack 24 | # - ALPINE_DATABASE_DRIVER=org.postgresql.Driver 25 | # - ALPINE_DATABASE_USERNAME=dtrack 26 | # - ALPINE_DATABASE_PASSWORD=changeme 27 | # - ALPINE_DATABASE_POOL_ENABLED=true 28 | # - ALPINE_DATABASE_POOL_MAX_SIZE=20 29 | # - ALPINE_DATABASE_POOL_MIN_IDLE=10 30 | # - ALPINE_DATABASE_POOL_IDLE_TIMEOUT=300000 31 | # - ALPINE_DATABASE_POOL_MAX_LIFETIME=600000 32 | # 33 | # Optional LDAP Properties 34 | # - ALPINE_LDAP_ENABLED=true 35 | # - ALPINE_LDAP_SERVER_URL=ldap://ldap.example.com:389 36 | # - ALPINE_LDAP_BASEDN=dc=example,dc=com 37 | # - ALPINE_LDAP_SECURITY_AUTH=simple 38 | # - ALPINE_LDAP_BIND_USERNAME= 39 | # - ALPINE_LDAP_BIND_PASSWORD= 40 | # - ALPINE_LDAP_AUTH_USERNAME_FORMAT=%s@example.com 41 | # - ALPINE_LDAP_ATTRIBUTE_NAME=userPrincipalName 42 | # - ALPINE_LDAP_ATTRIBUTE_MAIL=mail 43 | # - ALPINE_LDAP_GROUPS_FILTER=(&(objectClass=group)(objectCategory=Group)) 44 | # - ALPINE_LDAP_USER_GROUPS_FILTER=(member:1.2.840.113556.1.4.1941:={USER_DN}) 45 | # - ALPINE_LDAP_GROUPS_SEARCH_FILTER=(&(objectClass=group)(objectCategory=Group)(cn=*{SEARCH_TERM}*)) 46 | # - ALPINE_LDAP_USERS_SEARCH_FILTER=(&(objectClass=user)(objectCategory=Person)(cn=*{SEARCH_TERM}*)) 47 | # - ALPINE_LDAP_USER_PROVISIONING=false 48 | # - ALPINE_LDAP_TEAM_SYNCHRONIZATION=false 49 | # 50 | # Optional OpenID Connect (OIDC) Properties 51 | # - ALPINE_OIDC_ENABLED=true 52 | # - ALPINE_OIDC_ISSUER=https://auth.example.com/auth/realms/example 53 | # - ALPINE_OIDC_CLIENT_ID= 54 | # - ALPINE_OIDC_USERNAME_CLAIM=preferred_username 55 | # - ALPINE_OIDC_TEAMS_CLAIM=groups 56 | # - ALPINE_OIDC_USER_PROVISIONING=true 57 | # - ALPINE_OIDC_TEAM_SYNCHRONIZATION=true 58 | # 59 | # Optional HTTP Proxy Settings 60 | # - ALPINE_HTTP_PROXY_ADDRESS=proxy.example.com 61 | # - ALPINE_HTTP_PROXY_PORT=8888 62 | # - ALPINE_HTTP_PROXY_USERNAME= 63 | # - ALPINE_HTTP_PROXY_PASSWORD= 64 | # - ALPINE_NO_PROXY= 65 | # 66 | # Optional HTTP Outbound Connection Timeout Settings. All values are in seconds. 67 | # - ALPINE_HTTP_TIMEOUT_CONNECTION=30 68 | # - ALPINE_HTTP_TIMEOUT_SOCKET=30 69 | # - ALPINE_HTTP_TIMEOUT_POOL=60 70 | # 71 | # Optional Cross-Origin Resource Sharing (CORS) Headers 72 | # - ALPINE_CORS_ENABLED=true 73 | # - ALPINE_CORS_ALLOW_ORIGIN=* 74 | # - ALPINE_CORS_ALLOW_METHODS=GET, POST, PUT, DELETE, OPTIONS 75 | # - ALPINE_CORS_ALLOW_HEADERS=Origin, Content-Type, Authorization, X-Requested-With, Content-Length, Accept, Origin, X-Api-Key, X-Total-Count, * 76 | # - ALPINE_CORS_EXPOSE_HEADERS=Origin, Content-Type, Authorization, X-Requested-With, Content-Length, Accept, Origin, X-Api-Key, X-Total-Count 77 | # - ALPINE_CORS_ALLOW_CREDENTIALS=true 78 | # - ALPINE_CORS_MAX_AGE=3600 79 | deploy: 80 | resources: 81 | limits: 82 | memory: 12288m 83 | reservations: 84 | memory: 8192m 85 | restart_policy: 86 | condition: on-failure 87 | ports: 88 | - '8081:8080' 89 | volumes: 90 | - 'dependency-track:/data' 91 | restart: unless-stopped 92 | 93 | dtrack-frontend: 94 | image: dependencytrack/frontend 95 | depends_on: 96 | - dtrack-apiserver 97 | environment: 98 | # The base URL of the API server. 99 | # NOTE: 100 | # * This URL must be reachable by the browsers of your users. 101 | # * The frontend container itself does NOT communicate with the API server directly, it just serves static files. 102 | # * When deploying to dedicated servers, please use the external IP or domain of the API server. 103 | - API_BASE_URL=http://localhost:8081 104 | # - "OIDC_ISSUER=" 105 | # - "OIDC_CLIENT_ID=" 106 | # - "OIDC_SCOPE=" 107 | # - "OIDC_FLOW=" 108 | # - "OIDC_LOGIN_BUTTON_TEXT=" 109 | # volumes: 110 | # - "/host/path/to/config.json:/app/static/config.json" 111 | ports: 112 | - "8080:8080" 113 | restart: unless-stopped 114 | 115 | -------------------------------------------------------------------------------- /docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "3.5" 3 | 4 | services: 5 | jenkins: 6 | user: "1000:134" 7 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "3.5" 3 | 4 | networks: 5 | default: 6 | driver: bridge 7 | name: lab 8 | 9 | services: 10 | gitlab: 11 | container_name: gitlab 12 | environment: 13 | # These settings will be evaluated on load - see 14 | # https://docs.gitlab.com/omnibus/docker/#pre-configure-docker-container 15 | GITLAB_OMNIBUS_CONFIG: | 16 | external_url "http://gitlab.demo.local/"; 17 | prometheus_monitoring['enable'] = false 18 | gitlab_rails['display_initial_root_password'] = true 19 | gitlab_rails['usage_ping_enabled'] = false 20 | image: gitlab/gitlab-ce 21 | networks: 22 | default: 23 | aliases: 24 | - gitlab.demo.local 25 | ports: 26 | - "80:80" 27 | - "7722:22" 28 | restart: unless-stopped 29 | stop_grace_period: 10m 30 | volumes: 31 | - gitlab_config:/etc/gitlab 32 | - gitlab_data:/var/opt/gitlab 33 | - gitlab_logs:/var/log/gitlab 34 | 35 | jenkins: 36 | container_name: jenkins 37 | environment: 38 | - JAVA_OPTS=-Dhudson.model.DirectoryBrowserSupport.CSP="sandbox allow-scripts; script-src 'unsafe-inline'; style-src 'unsafe-inline';" # Allow inline JavaScript 39 | - PLUGINS_FORCE_UPGRADE=true # Enforce upgrade of native plugins at startup 40 | image: jenkinsci/blueocean 41 | networks: 42 | default: 43 | aliases: 44 | - jenkins.demo.local 45 | ports: 46 | - "8080:8080" 47 | restart: unless-stopped 48 | user: :900 # part of the docker group as the user needs to be able to start containers 49 | volumes: 50 | - jenkins_home:/var/jenkins_home:rw # Workspace home 51 | - /var/run/docker.sock:/var/run/docker.sock:ro # Allows Jenkins to stop/start containers 52 | 53 | registry: 54 | container_name: registry 55 | image: registry:2 56 | ports: 57 | - "5000:5000" 58 | restart: unless-stopped 59 | networks: 60 | default: 61 | aliases: 62 | - registry.demo.local 63 | volumes: 64 | - registry:/var/lib/registry 65 | 66 | sonarqube: 67 | container_name: sonarqube 68 | image: sonarqube:7.9-community 69 | networks: 70 | default: 71 | aliases: 72 | - sonarqube.demo.local 73 | ports: 74 | - "9000:9000" 75 | restart: unless-stopped 76 | stop_grace_period: 10m 77 | volumes: 78 | - sonarqube_conf:/opt/sonarqube/conf 79 | - sonarqube_data:/opt/sonarqube/data 80 | - sonarqube_extensions:/opt/sonarqube/extensions 81 | - sonarqube_logs:/opt/sonarqube/logs 82 | - sonarqube_temp:/opt/sonarqube/temp 83 | 84 | volumes: 85 | gitlab_config: 86 | gitlab_data: 87 | gitlab_logs: 88 | jenkins_home: 89 | name: jenkins_home 90 | registry: 91 | sonarqube_conf: 92 | sonarqube_data: 93 | sonarqube_extensions: 94 | sonarqube_logs: 95 | sonarqube_temp: 96 | driver_opts: 97 | type: tmpfs 98 | device: tmpfs 99 | -------------------------------------------------------------------------------- /juice-shop/Jenkinsfile: -------------------------------------------------------------------------------- 1 | // This pipeline performs a full suite of automated security testing 2 | // - lint: Lint Docker image 3 | // - detect new secrets: Detect new secrets 4 | // - sonarscanner: Scan source code 5 | // - build: Build Docker image 6 | // - push: Push Docker image to registry 7 | // - dependency check: Test for insecure third party libraries 8 | // - sidecar: Run sidecar 9 | // - scan: Scan container image 10 | // - nikto: Perform a Nikto scan 11 | 12 | pipeline { 13 | environment { // Environment variables defined for all steps 14 | DOCKER_IMAGE = "registry.demo.local:5000/juice-shop" 15 | TOOLS_IMAGE = "registry.demo.local:5000/tools-image" 16 | JENKINS_UID = 1000 // User ID under which Jenkins runs 17 | JENKINS_GID = 134 // Group ID under which Jenkins runs 18 | SONAR_KEY = "juice-shop" 19 | } 20 | 21 | agent any 22 | 23 | stages { 24 | stage("lint") { 25 | agent { 26 | docker { 27 | image "docker.io/hadolint/hadolint:v1.18.0" 28 | reuseNode true 29 | } 30 | } 31 | steps { 32 | sh label: "Lint Dockerfile", script: "hadolint Dockerfile > hadolint-results.txt" 33 | } 34 | } 35 | 36 | // Detect new secrets added since last successful build 37 | stage("detect new secrets") { 38 | agent { 39 | docker { 40 | image "${TOOLS_IMAGE}" 41 | // Make sure that username can be mapped correctly 42 | args "--volume /etc/passwd:/etc/passwd:ro" 43 | reuseNode true 44 | } 45 | } 46 | steps { 47 | // Determine commit of previous successful build when this is master 48 | script { 49 | def result = sh label: "detect-secrets", 50 | script: """\ 51 | detect-secrets-hook --no-verify \ 52 | -v \ 53 | \$(git diff-tree --no-commit-id --name-only -r ${GIT_COMMIT} | xargs -n1) 54 | """, 55 | returnStatus: true 56 | // command for baseline --baseline .secrets.baseline.json \ 57 | // Exit code 1 is generated when secrets are detected or no baseline is present 58 | // Exit code 3 is generated only when .secrets.baseline.json is updated, 59 | // eg. when the line numbers don't match anymore 60 | if (result == 1) { 61 | // There are (unaudited) secrets detected: fail stage 62 | unstable(message: "unaudited secrets have been found") 63 | } 64 | } 65 | } 66 | } 67 | 68 | stage("sonarscanner") { 69 | agent { 70 | docker { 71 | image "${TOOLS_IMAGE}" 72 | // Make sure that username can be mapped correctly 73 | args "--volume /etc/passwd:/etc/passwd:ro --network lab" 74 | reuseNode true 75 | } 76 | } 77 | steps { 78 | withSonarQubeEnv("sonarqube.demo.local") { 79 | //sh label: "install prerequisites", 80 | // script: "npm install -D typescript" 81 | sh label: "sonar-scanner", 82 | script: """\ 83 | sonar-scanner \ 84 | '-Dsonar.buildString=${BRANCH_NAME}-${BUILD_ID}' \ 85 | '-Dsonar.projectKey=${SONAR_KEY}' \ 86 | '-Dsonar.projectVersion=${BUILD_ID}' \ 87 | '-Dsonar.sources=${WORKSPACE}' 88 | """ 89 | } 90 | } 91 | } 92 | 93 | stage("Dependency-Check") { 94 | agent { 95 | docker { 96 | image "owasp/dependency-check" 97 | // Set user to root, as the container runs by default under 100:101 98 | args '''\ 99 | --user 0 \ 100 | --volume dependency-check:/usr/share/dependency-check/data:rw \ 101 | --volume ${WORKSPACE}:/src:ro \ 102 | --volume ${WORKSPACE}/reports:/reports:rw \ 103 | --entrypoint "" 104 | ''' 105 | reuseNode true 106 | } 107 | } 108 | steps { 109 | script { 110 | // Fail stage when a vulnerability having a base CVSS score of 6 or higher is found 111 | warnError('Dependency check CVSS score of 6 or greater found') { 112 | sh label: "dependency-check", returnStatus: true, 113 | script: """\ 114 | mkdir -p reports &>/dev/null 115 | # Fix permissions as this container is being run as root 116 | chown "${JENKINS_UID}:${JENKINS_GID}" reports 117 | /usr/share/dependency-check/bin/dependency-check.sh \ 118 | --failOnCVSS 6 \ 119 | --out "${WORKSPACE}/reports" \ 120 | --project "${JOB_BASE_NAME}" \ 121 | --scan "/src" 122 | # Fix permissions as this container is being run as root 123 | chown "${JENKINS_UID}:${JENKINS_GID}" reports/dependency-check-report.html 124 | """ 125 | } 126 | } 127 | } 128 | } 129 | 130 | stage("Build image") { 131 | steps { 132 | script { 133 | // Use commit tag if it has been tagged 134 | tag = sh(returnStdout: true, script: "git tag --contains").trim() 135 | if ("$tag" == "") { 136 | if ("${BRANCH_NAME}" == "master") { 137 | tag = "latest" 138 | } else { 139 | tag = "${BRANCH_NAME}" 140 | } 141 | } 142 | image = docker.build("$DOCKER_IMAGE:$tag") 143 | } 144 | } 145 | } 146 | 147 | stage("Push to registry") { 148 | steps { 149 | script { 150 | sh label: "Push to registry", script: "docker push ${DOCKER_IMAGE}:$tag" 151 | } 152 | } 153 | } 154 | 155 | stage("Launch sidecar") { 156 | steps { 157 | sh label: "Start sidecar container", 158 | script: """\ 159 | docker run --detach \ 160 | --network lab \ 161 | --name ${JOB_BASE_NAME}-${BUILD_ID} \ 162 | --rm \ 163 | ${DOCKER_IMAGE}:${tag} 164 | """ 165 | } 166 | } 167 | 168 | stage("Scan container") { 169 | agent { 170 | docker { 171 | image "$TOOLS_IMAGE" 172 | // Make sure that the container can access anchore-engine_api_1 173 | args "--network=lab" 174 | reuseNode true 175 | } 176 | } 177 | 178 | steps { 179 | script{ 180 | warnError('Stop Vulnerabilites found') { 181 | writeFile file: 'anchore_images', text: DOCKER_IMAGE 182 | anchore engineRetries: '900', name: 'anchore_images' 183 | } 184 | } 185 | } 186 | } 187 | 188 | stage("nikto") { 189 | agent { 190 | docker { 191 | image "$TOOLS_IMAGE" 192 | // Make sure that the container can access the sidecar 193 | args "--network=lab" 194 | reuseNode true 195 | } 196 | } 197 | steps { 198 | script { 199 | warnError('Nikto Vulnerabilites found') { 200 | // Fail stage when Nikto finds something 201 | sh label: "nikto", returnStatus: true, 202 | script: """\ 203 | mkdir -p reports &>/dev/null 204 | curl --max-time 120 \ 205 | --retry 60 \ 206 | --retry-connrefused \ 207 | --retry-delay 5 \ 208 | --fail \ 209 | --silent http://${JOB_BASE_NAME}-${BUILD_ID}:3000 || exit 1 210 | rm reports/nikto.html &> /dev/null 211 | nikto.pl -ask no \ 212 | -nointeractive \ 213 | -output reports/nikto.html \ 214 | -Plugins '@@ALL;-sitefiles' \ 215 | -Tuning x7 \ 216 | -host http://${JOB_BASE_NAME}-${BUILD_ID}:3000 > nikto.pl-results.txt 217 | """ 218 | } 219 | } 220 | } 221 | } 222 | 223 | stage("OWASP ZAP") { 224 | agent { 225 | docker { 226 | image "owasp/zap2docker-weekly" 227 | // Make sure that the container can access the sidecar 228 | args "-u 0 --network=lab --tty --volume ${WORKSPACE}:/zap/wrk:rw" 229 | reuseNode true 230 | } 231 | } 232 | steps { 233 | script { 234 | warnError('OWASP ZAP vulnerabilites found') { 235 | sh label: "OWASP ZAP", returnStatus: true, 236 | script: """\ 237 | mkdir -p ${WORKSPACE}/reports &>/dev/null \ 238 | curl --max-time 120 \ 239 | --retry 60 \ 240 | --retry-connrefused \ 241 | --retry-delay 5 \ 242 | --fail \ 243 | --silent http://${JOB_BASE_NAME}-${BUILD_ID}:3000 || exit 1 244 | zap-baseline.py \ 245 | -m 5 \ 246 | -T 5\ 247 | -I \ 248 | -r reports/zapreport.html \ 249 | -t "http://${JOB_BASE_NAME}-${BUILD_ID}:3000" 250 | cp /zap/wrk/reports/zapreport.html /var/jenkins_home/workspace/Juice-shop_master/reports/zapreport.html 251 | """ 252 | } 253 | } 254 | } 255 | } 256 | } 257 | 258 | post { 259 | always { 260 | sh label: "Stop sidecar container", script: "docker stop ${JOB_BASE_NAME}-${BUILD_ID}" 261 | archiveArtifacts artifacts: "*-results.txt" 262 | publishHTML([ 263 | allowMissing: true, 264 | alwaysLinkToLastBuild: true, 265 | keepAll: false, 266 | reportDir: "reports", 267 | reportFiles: "dependency-check-report.html", 268 | reportName: "Dependency Check Report" 269 | ]) 270 | publishHTML([ 271 | allowMissing: true, 272 | alwaysLinkToLastBuild: true, 273 | keepAll: true, 274 | reportDir: "reports", 275 | reportFiles: "nikto.html", 276 | reportName: "Nikto.pl scanreport" 277 | ]) 278 | publishHTML([ 279 | allowMissing: true, 280 | alwaysLinkToLastBuild: true, 281 | keepAll: true, 282 | reportDir: "reports", 283 | reportFiles: "zapreport.html", 284 | reportName: "OWASP ZAP scanreport" 285 | ]) 286 | } 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /juice-shop/frontend/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 0.5% 2 | last 2 versions 3 | Firefox ESR 4 | not dead 5 | not IE <= 11 6 | not ios_saf 15.2-15.3 7 | not safari 15.2-15.3 8 | -------------------------------------------------------------------------------- /juice-shop/frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /juice-shop/frontend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2022 Bjoern Kimminich & the OWASP Juice Shop contributors. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | 6 | module.exports = { 7 | extends: 'standard-with-typescript', 8 | root: true, 9 | parserOptions: { 10 | project: './src/tsconfig.*.json', 11 | sourceType: 'module' 12 | }, 13 | rules: { // FIXME Remaining linting errors since migrating from StandardJS-style TSLint. Significant refactoring expected in order to turn on! 14 | '@typescript-eslint/strict-boolean-expressions': 'off', 15 | '@typescript-eslint/consistent-type-assertions': 'off', 16 | '@typescript-eslint/no-invalid-void-type': 'off', 17 | '@typescript-eslint/no-floating-promises': 'off', 18 | '@typescript-eslint/explicit-function-return-type': 'off' 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /juice-shop/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | package-lock.json 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | *.sublime-workspace 20 | 21 | # IDE - VSCode 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | 28 | # misc 29 | /.angular/cache 30 | /.sass-cache 31 | /connect.lock 32 | /coverage 33 | /libpeerconnection.log 34 | npm-debug.log 35 | yarn-error.log 36 | testem.log 37 | /typings 38 | 39 | # System Files 40 | .DS_Store 41 | Thumbs.db 42 | -------------------------------------------------------------------------------- /juice-shop/frontend/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /juice-shop/frontend/.stylelintrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2022 Bjoern Kimminich & the OWASP Juice Shop contributors. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | 6 | module.exports = { 7 | extends: 'stylelint-config-sass-guidelines', 8 | plugins: [ 9 | 'stylelint-scss' 10 | ], 11 | rules: { 12 | 'selector-max-id': 1, 13 | 'selector-max-compound-selectors': 4, 14 | 'selector-pseudo-element-no-unknown': [ 15 | true, 16 | { 17 | 'ignorePseudoElements': ['ng-deep'] 18 | } 19 | ], 20 | 'property-no-vendor-prefix': null, 21 | 'value-no-vendor-prefix': null, 22 | 'selector-no-vendor-prefix': null, 23 | 'selector-no-qualifying-type': null, 24 | 'selector-class-pattern': null 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /juice-shop/frontend/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2022 Bjoern Kimminich & the OWASP Juice Shop contributors. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | 6 | /** 7 | * This file includes polyfills needed by Angular and is loaded before the app. 8 | * You can add your own extra polyfills to this file. 9 | * 10 | * This file is divided into 2 sections: 11 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 12 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 13 | * file. 14 | * 15 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 16 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 17 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 18 | * 19 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 20 | */ 21 | 22 | /** ************************************************************************************************* 23 | * BROWSER POLYFILLS 24 | */ 25 | 26 | /** IE9, IE10 and IE11 requires all of the following polyfills. */ 27 | // import 'core-js/es6/symbol'; 28 | // import 'core-js/es6/object'; 29 | // import 'core-js/es6/function'; 30 | // import 'core-js/es6/parse-int'; 31 | // import 'core-js/es6/parse-float'; 32 | // import 'core-js/es6/number'; 33 | // import 'core-js/es6/math'; 34 | // import 'core-js/es6/string'; 35 | // import 'core-js/es6/date'; 36 | // import 'core-js/es6/array'; 37 | // import 'core-js/es6/regexp'; 38 | // import 'core-js/es6/map'; 39 | // import 'core-js/es6/weak-map'; 40 | // import 'core-js/es6/set'; 41 | 42 | /** IE10 and IE11 requires the following for the Reflect API. */ 43 | // import 'core-js/es6/reflect'; 44 | 45 | /** Evergreen browsers require these. */ 46 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. 47 | //import 'core-js/es7/reflect' 48 | 49 | /** 50 | * By default, zone.js will patch all possible macroTask and DomEvents 51 | * user can disable parts of macroTask/DomEvents patch by setting following flags 52 | */ 53 | 54 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 55 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 56 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 57 | 58 | /* 59 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 60 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 61 | */ 62 | // (window as any).__Zone_enable_cross_context_check = true; 63 | 64 | /** ************************************************************************************************* 65 | * Zone JS is required by default for Angular itself. 66 | */ 67 | import 'zone.js' // Included with Angular CLI. 68 | (window as any).global = window 69 | 70 | /** ************************************************************************************************* 71 | * APPLICATION IMPORTS 72 | */ 73 | -------------------------------------------------------------------------------- /readme: -------------------------------------------------------------------------------- 1 | More to come. These files will allow you to use docker-compose to start a DevSecOps lab in containers on your local laptop. This was built on Ubuntu 20.04 LTS 2 | 3 | This lab environment code has been forked from Peter Mosmans DevSecOps repository. https://github.com/PeterMosmans/devsecops-lab. 4 | 5 | His courses on DevSecOps and security testing on Pluralsight can be found here: https://app.pluralsight.com/profile/author/peter-mosmans 6 | 7 | They are not only excellent, but will give a deepdive on how to get this code working and how to use all of the security tests. 8 | 9 | 10 | --------------------------------------------------------------------------------