Fix: Unauthenticated access to customer order confirmation PDFs via /ftp #631
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: "CI/CD Pipeline" | |
| on: | |
| push: | |
| branches-ignore: | |
| - l10n_develop | |
| - gh-pages | |
| paths-ignore: | |
| - '*.md' | |
| - 'LICENSE' | |
| - 'monitoring/grafana-dashboard.json' | |
| - 'screenshots/**' | |
| tags-ignore: | |
| - '*' | |
| pull_request: | |
| paths-ignore: | |
| - '*.md' | |
| - 'LICENSE' | |
| - 'data/static/i18n/*.json' | |
| - 'frontend/src/assets/i18n/*.json' | |
| env: | |
| NODE_DEFAULT_VERSION: 24 | |
| NODE_OPTIONS: "--max_old_space_size=4096" | |
| CYCLONEDX_NPM_VERSION: '^2.0.0||^3.0.0||^4.0.0' # keep in sync with package.json | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Use Node.js 24" | |
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0 | |
| with: | |
| node-version: ${{ env.NODE_DEFAULT_VERSION }} | |
| - name: "Install application minimalistically" | |
| run: | | |
| npm install --ignore-scripts | |
| cd frontend | |
| npm install --ignore-scripts | |
| - name: "Lint source code" | |
| run: npm run lint | |
| - name: "Lint customization configs" | |
| run: > | |
| npm run lint:config -- -f ./config/7ms.yml && | |
| npm run lint:config -- -f ./config/addo.yml && | |
| npm run lint:config -- -f ./config/bodgeit.yml && | |
| npm run lint:config -- -f ./config/ctf.yml && | |
| npm run lint:config -- -f ./config/default.yml && | |
| npm run lint:config -- -f ./config/fbctf.yml && | |
| npm run lint:config -- -f ./config/juicebox.yml && | |
| npm run lint:config -- -f ./config/mozilla.yml && | |
| npm run lint:config -- -f ./config/oss.yml && | |
| npm run lint:config -- -f ./config/quiet.yml && | |
| npm run lint:config -- -f ./config/tutorial.yml && | |
| npm run lint:config -- -f ./config/unsafe.yml | |
| coding-challenge-rsn: | |
| runs-on: windows-latest | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Use Node.js 24" | |
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0 | |
| with: | |
| node-version: ${{ env.NODE_DEFAULT_VERSION }} | |
| - name: "Install application" | |
| run: npm install | |
| - name: "Check coding challenges for accidental code discrepancies" | |
| run: npm run rsn | |
| frontend-test: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| node-version: [22, 24] | |
| steps: | |
| - name: "Check out Git repository" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Use Node.js ${{ matrix.node-version }}" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0 | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| - name: "Install application" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| run: npm install | |
| - name: "Execute frontend unit tests" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: nick-invision/retry@7152eba30c6575329ac0576536151aca5a72780e #v3.0.0 | |
| with: | |
| shell: bash | |
| timeout_minutes: 10 | |
| max_attempts: 3 | |
| command: npm run test:frontend:coverage | |
| - name: "Copy frontend unit test coverage data" | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24' | |
| run: | | |
| cp frontend/coverage/frontend/lcov.info frontend-lcov.info | |
| sed -i s/SF:/SF:frontend\\//g frontend-lcov.info | |
| shell: bash | |
| - name: "Upload frontend unit test coverage data" | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24' | |
| uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b #v4.5.0 | |
| with: | |
| name: frontend-test-lcov | |
| path: | | |
| frontend-lcov.info | |
| server-test: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| node-version: [22, 24, 25] | |
| steps: | |
| - name: "Check out Git repository" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Use Node.js ${{ matrix.node-version }}" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0 | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| - name: "Install application" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| run: npm install | |
| - name: "Execute server unit tests" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: nick-invision/retry@7152eba30c6575329ac0576536151aca5a72780e #v3.0.0 | |
| with: | |
| timeout_minutes: 10 | |
| max_attempts: 3 | |
| command: npm run test:server:coverage | |
| - name: "Copy server unit test coverage data" | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24' | |
| run: | | |
| cp coverage/server-tests/lcov.info server-lcov.info | |
| shell: bash | |
| - name: "Upload server unit test coverage data" | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24' | |
| uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b #v4.5.0 | |
| with: | |
| name: server-test-lcov | |
| path: | | |
| server-lcov.info | |
| api-test: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| node-version: [22, 24, 25] | |
| steps: | |
| - name: "Check out Git repository" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Use Node.js ${{ matrix.node-version }}" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0 | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| - name: "Install application" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| run: npm install | |
| - name: "Execute integration tests" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| uses: nick-invision/retry@7152eba30c6575329ac0576536151aca5a72780e #v3.0.0 | |
| env: | |
| NODE_ENV: test | |
| ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }} | |
| with: | |
| timeout_minutes: 5 | |
| max_attempts: 3 | |
| command: npm run test:api:coverage | |
| - name: "Copy API test coverage data" | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24' | |
| run: cp coverage/api-tests/lcov.info api-lcov.info | |
| - name: "Upload API test coverage data" | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24' | |
| uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b #v4.5.0 | |
| with: | |
| name: api-test-lcov | |
| path: | | |
| api-lcov.info | |
| coverage-report: | |
| needs: [frontend-test, server-test, api-test] | |
| runs-on: ubuntu-latest | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Download frontend test coverage data" | |
| uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #v4.1.8 | |
| with: | |
| name: frontend-test-lcov | |
| - name: "Download server test coverage data" | |
| uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #v4.1.8 | |
| with: | |
| name: server-test-lcov | |
| - name: "Download API test coverage data" | |
| uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #v4.1.8 | |
| with: | |
| name: api-test-lcov | |
| - name: "Publish coverage to Coveralls" | |
| uses: coverallsapp/github-action@v2 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| files: frontend-lcov.info server-lcov.info api-lcov.info | |
| custom-config-test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Use Node.js 24" | |
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0 | |
| with: | |
| node-version: ${{ env.NODE_DEFAULT_VERSION }} | |
| - name: "Install application" | |
| if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '24') | |
| run: npm install | |
| - name: "Execute server tests for each custom configuration" | |
| uses: nick-invision/retry@7152eba30c6575329ac0576536151aca5a72780e #v3.0.0 | |
| with: | |
| timeout_minutes: 30 | |
| max_attempts: 3 | |
| command: > | |
| NODE_ENV=7ms npm run test:server && | |
| NODE_ENV=addo npm run test:server && | |
| NODE_ENV=bodgeit npm run test:server && | |
| NODE_ENV=ctf npm run test:server && | |
| NODE_ENV=fbctf npm run test:server && | |
| NODE_ENV=juicebox npm run test:server && | |
| NODE_ENV=mozilla npm run test:server && | |
| NODE_ENV=oss npm run test:server && | |
| NODE_ENV=quiet npm run test:server && | |
| NODE_ENV=tutorial npm run test:server && | |
| NODE_ENV=unsafe npm run test:server | |
| e2e-test: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| browser: [chrome] # FIXME Switch back to [chrome, firefox] after debugging extreme flakiness of Firefox on CI/CD | |
| fail-fast: false | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Use Node.js 24" | |
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0 | |
| with: | |
| node-version: ${{ env.NODE_DEFAULT_VERSION }} | |
| - name: "Install CLI tools" | |
| run: npm install -g @angular/cli | |
| - name: "Install application" | |
| run: npm install | |
| - name: "Execute end-to-end tests on Ubuntu" | |
| if: ${{ matrix.os == 'ubuntu-latest' }} | |
| uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b #v6.7.8 | |
| with: | |
| install: false | |
| browser: ${{ matrix.browser }} | |
| start: npm start | |
| wait-on: http://localhost:3000 | |
| record: true | |
| group: ${{ matrix.browser }} @ ${{ matrix.os }} | |
| env: | |
| SOLUTIONS_WEBHOOK: ${{ secrets.E2E_SOLUTIONS_WEBHOOK }} | |
| ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }} | |
| CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: "Execute end-to-end tests on Mac" | |
| if: ${{ matrix.os == 'macos-latest' }} | |
| uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b #v6.7.8 | |
| with: | |
| install: false | |
| browser: ${{ matrix.browser }} | |
| start: npm start | |
| wait-on: http://localhost:3000 | |
| record: true | |
| group: ${{ matrix.browser }} @ ${{ matrix.os }} | |
| env: | |
| CYPRESS_CACHE_FOLDER: /Users/runner/Library/Caches/Cypress | |
| ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }} | |
| CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| smoke-test: | |
| runs-on: ubuntu-latest | |
| env: | |
| TYPESCRIPT_VERSION: '~5.3.3' # keep in sync with package.json | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Use Node.js 24" | |
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0 | |
| with: | |
| node-version: ${{ env.NODE_DEFAULT_VERSION }} | |
| - name: "Install CLI tools" | |
| run: | | |
| npm install -g typescript@${{ env.TYPESCRIPT_VERSION }} | |
| npm install -g @cyclonedx/cyclonedx-npm@$CYCLONEDX_NPM_VERSION | |
| npm install -g grunt-cli | |
| - name: "Set packaging options for Grunt" | |
| run: | | |
| echo "PCKG_OS_NAME=linux" >> $GITHUB_ENV | |
| echo "PCKG_NODE_VERSION=24" >> $GITHUB_ENV | |
| echo "PCKG_CPU_ARCH=x64" >> $GITHUB_ENV | |
| - name: "Package application" | |
| run: | | |
| npm install --production | |
| npm run package:ci | |
| - name: "Unpack application archive" | |
| run: | | |
| cd dist | |
| tar -zxf juice-shop-*.tgz | |
| - name: "Execute smoke test" | |
| run: | | |
| cd dist/juice-shop_* | |
| npm start & | |
| cd ../.. | |
| chmod +x test/smoke/smoke-test.sh | |
| test/smoke/smoke-test.sh http://localhost:3000 | |
| docker-test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Execute smoke test on Docker" | |
| run: docker compose -f docker-compose.test.yml up --exit-code-from sut | |
| docker: | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') | |
| needs: [frontend-test, server-test, api-test, e2e-test, custom-config-test, docker-test] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Set up QEMU" | |
| uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf #v3.2.0 | |
| - name: "Set up Docker Buildx" | |
| uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 #v3.8.0 | |
| - name: "Login to DockerHub" | |
| uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: "Set tag & labels for ${{ github.ref }}" | |
| run: | | |
| if [ "$GITHUB_REF" == "refs/heads/master" ]; then | |
| echo "DOCKER_TAG=latest" >> $GITHUB_ENV | |
| else | |
| echo "DOCKER_TAG=snapshot" >> $GITHUB_ENV | |
| fi | |
| echo "VCS_REF=`git rev-parse --short HEAD`" >> $GITHUB_ENV | |
| echo "BUILD_DATE=`date -u +”%Y-%m-%dT%H:%M:%SZ”`" >> $GITHUB_ENV | |
| - name: "Build and push for AMD64 and ARM64 processors" | |
| uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 #v6.1.0 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: | | |
| bkimminich/juice-shop:${{ env.DOCKER_TAG }} | |
| build-args: | | |
| VCS_REF=${{ env.VCS_REF }} | |
| BUILD_DATE=${{ env.BUILD_DATE }} | |
| CYCLONEDX_NPM_VERSION=${{ env.CYCLONEDX_NPM_VERSION }} | |
| heroku: | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') | |
| needs: [frontend-test, server-test, api-test, e2e-test, custom-config-test] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: "Check out Git repository" | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 | |
| - name: "Install Heroku CLI" | |
| run: curl https://cli-assets.heroku.com/install.sh | sh | |
| - name: "Set Heroku app & branch for ${{ github.ref }}" | |
| run: | | |
| if [ "$GITHUB_REF" == "refs/heads/master" ]; then | |
| echo "HEROKU_APP=juice-shop" >> $GITHUB_ENV | |
| echo "HEROKU_BRANCH=master" >> $GITHUB_ENV | |
| else | |
| echo "HEROKU_APP=juice-shop-staging" >> $GITHUB_ENV | |
| echo "HEROKU_BRANCH=develop" >> $GITHUB_ENV | |
| fi | |
| - name: "Deploy ${{ github.ref }} to Heroku" | |
| uses: akhileshns/heroku-deploy@581dd286c962b6972d427fcf8980f60755c15520 #v3.13.15 | |
| with: | |
| heroku_api_key: ${{ secrets.HEROKU_API_KEY }} | |
| heroku_app_name: ${{ env.HEROKU_APP }} | |
| heroku_email: bjoern.kimminich@owasp.org | |
| branch: ${{ env.HEROKU_BRANCH }} | |
| notify-slack: | |
| if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && (success() || failure()) | |
| needs: | |
| - docker | |
| - heroku | |
| - lint | |
| - coding-challenge-rsn | |
| - smoke-test | |
| - coverage-report | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: "Slack workflow notification" | |
| uses: Gamesight/slack-workflow-status@68bf00d0dbdbcb206c278399aa1ef6c14f74347a #v1.3.0 | |
| with: | |
| repo_token: ${{ secrets.GITHUB_TOKEN }} | |
| slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }} |