diff --git a/.github/actions/delete-preview/Dockerfile b/.github/actions/delete-preview/Dockerfile index fe13e78bf64cec..8a1dd13521aadc 100644 --- a/.github/actions/delete-preview/Dockerfile +++ b/.github/actions/delete-preview/Dockerfile @@ -1,4 +1,4 @@ -FROM eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 +FROM eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 COPY entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/deploy-gitpod/Dockerfile b/.github/actions/deploy-gitpod/Dockerfile index fe13e78bf64cec..8a1dd13521aadc 100644 --- a/.github/actions/deploy-gitpod/Dockerfile +++ b/.github/actions/deploy-gitpod/Dockerfile @@ -1,4 +1,4 @@ -FROM eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 +FROM eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 COPY entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/deploy-monitoring-satellite/Dockerfile b/.github/actions/deploy-monitoring-satellite/Dockerfile index fe13e78bf64cec..8a1dd13521aadc 100644 --- a/.github/actions/deploy-monitoring-satellite/Dockerfile +++ b/.github/actions/deploy-monitoring-satellite/Dockerfile @@ -1,4 +1,4 @@ -FROM eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 +FROM eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 COPY entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/preview-create/Dockerfile b/.github/actions/preview-create/Dockerfile index fe13e78bf64cec..8a1dd13521aadc 100644 --- a/.github/actions/preview-create/Dockerfile +++ b/.github/actions/preview-create/Dockerfile @@ -1,4 +1,4 @@ -FROM eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 +FROM eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 COPY entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index de8f5cb44405aa..2f0d3bdce6ff53 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,17 @@ on: type: string description: "Whether to recreate the VM" default: "false" + simulate_scheduled_run: + required: false + type: boolean + description: "Simulate a scheduled run" + default: false + schedule: + # Run at midnight UTC every day + # Purpose: This scheduled run performs regular vulnerability scans of the codebase + # and sends notifications to Slack when new critical vulnerabilities are found. + # The scan results are used to maintain security standards and address issues promptly. + - cron: '0 0 * * *' jobs: create-runner: @@ -36,6 +47,7 @@ jobs: cancel-in-progress: true outputs: is_main_branch: ${{ (github.head_ref || github.ref) == 'refs/heads/main' }} + is_scheduled_run: ${{ github.event_name == 'schedule' || inputs.simulate_scheduled_run == true }} version: ${{ steps.branches.outputs.sanitized-branch-name }}-gha.${{github.run_number}} preview_enable: ${{ contains( steps.pr-details.outputs.pr_body, '[x] /werft with-preview') || (steps.output.outputs.with_integration_tests != '') }} preview_name: ${{ github.head_ref || github.ref_name }} @@ -98,14 +110,15 @@ jobs: name: Build previewctl if: | (needs.configuration.outputs.pr_no_diff_skip != 'true') && - (needs.configuration.outputs.preview_enable == 'true') + (needs.configuration.outputs.preview_enable == 'true') && + (needs.configuration.outputs.is_scheduled_run != 'true') needs: [ configuration, create-runner ] concurrency: group: ${{ github.ref == 'refs/heads/main' && github.run_id || github.sha }}-build-previewctl cancel-in-progress: ${{ needs.configuration.outputs.is_main_branch == 'false' }} runs-on: ${{ needs.create-runner.outputs.label }} container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 steps: - uses: actions/checkout@v4 - name: Setup Environment @@ -126,7 +139,8 @@ jobs: if: | (needs.configuration.outputs.pr_no_diff_skip != 'true') && (needs.configuration.outputs.preview_enable == 'true') && - (needs.configuration.outputs.is_main_branch != 'true') + (needs.configuration.outputs.is_main_branch != 'true') && + (needs.configuration.outputs.is_scheduled_run != 'true') runs-on: ${{ needs.create-runner.outputs.label }} concurrency: group: ${{ github.ref == 'refs/heads/main' && github.run_id || github.sha }}-infrastructure @@ -154,6 +168,8 @@ jobs: name: Build Gitpod needs: [ configuration, create-runner ] runs-on: ${{ needs.create-runner.outputs.label }} + outputs: + affected_packages: ${{ steps.check_vulnerabilities.outputs.affected_packages }} concurrency: group: ${{ github.ref == 'refs/heads/main' && github.run_id || github.sha }}-build-gitpod cancel-in-progress: ${{ needs.configuration.outputs.is_main_branch == 'false' }} @@ -172,7 +188,7 @@ jobs: ports: - 6379:6379 container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 env: DB_HOST: "mysql" DB_PORT: "23306" @@ -299,7 +315,7 @@ jobs: exit $RESULT - name: Tag the release - if: github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/main' && needs.configuration.outputs.is_scheduled_run != 'true' run: | git config --global user.name $GITHUB_USER git config --global user.email $GITHUB_EMAIL @@ -309,36 +325,83 @@ jobs: GITHUB_USER: roboquat GITHUB_EMAIL: roboquat@gitpod.io VERSION: ${{ needs.configuration.outputs.version }} - - trivy-scan: - name: "Scan Images for Vulnerabilities" - needs: - - configuration - - build-gitpod - - create-runner - runs-on: ${{ needs.create-runner.outputs.label }} - container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 - steps: - - uses: actions/checkout@v4 - - name: Setup Environment - uses: ./.github/actions/setup-environment - with: - identity_provider: ${{ github.ref == 'refs/heads/main' && secrets.CORE_DEV_PROVIDER || secrets.DEV_PREVIEW_PROVIDER }} - service_account: ${{ github.ref == 'refs/heads/main' && secrets.CORE_DEV_SA || secrets.DEV_PREVIEW_SA }} - leeway_segment_key: ${{ secrets.LEEWAY_SEGMENT_KEY }} - - name: Scan Images for Vulnerabilities + - name: Scan for Vulnerabilities + id: scan shell: bash env: - INSTALLER_IMAGE_BASE_REPO: ${{needs.configuration.outputs.image_repo_base}} + VERSION: ${{needs.configuration.outputs.version}} + PUBLISH_TO_NPM: ${{ needs.configuration.outputs.publish_to_npm == 'true' || needs.configuration.outputs.is_main_branch == 'true' }} + PUBLISH_TO_JBPM: ${{ needs.configuration.outputs.publish_to_jbmp == 'true' || needs.configuration.outputs.is_main_branch == 'true' }} + LEEWAY_REMOTE_CACHE_BUCKET: ${{needs.configuration.outputs.leeway_cache_bucket}} + IMAGE_REPO_BASE: ${{needs.configuration.outputs.image_repo_base}}/build + run: | + [[ "$PR_NO_CACHE" = "true" ]] && CACHE="none" || CACHE="remote" + [[ "$PR_NO_TEST" = "true" ]] && TEST="--dont-test" || TEST="" + [[ "${PUBLISH_TO_NPM}" = 'true' ]] && NPM_PUBLISH_TRIGGER=$(date +%s%3N) || NPM_PUBLISH_TRIGGER="false" + + sboms_dir=$(mktemp -d) + CI= leeway sbom export components:needs-vuln-scan --with-dependencies --output-dir "$sboms_dir" \ + -Dversion=$VERSION \ + --docker-build-options network=host \ + --max-concurrent-tasks 1 \ + -DlocalAppVersion=$VERSION \ + -DpublishToNPM="${PUBLISH_TO_NPM}" \ + -DnpmPublishTrigger="${NPM_PUBLISH_TRIGGER}" \ + -DpublishToJBMarketplace="${PUBLISH_TO_JBPM}" \ + -DimageRepoBase=$IMAGE_REPO_BASE + + scans_dir=$(mktemp -d) + CI= leeway sbom scan components:needs-vuln-scan --with-dependencies --output-dir "$scans_dir" \ + -Dversion=$VERSION \ + --docker-build-options network=host \ + --max-concurrent-tasks 1 \ + -DlocalAppVersion=$VERSION \ + -DpublishToNPM="${PUBLISH_TO_NPM}" \ + -DnpmPublishTrigger="${NPM_PUBLISH_TRIGGER}" \ + -DpublishToJBMarketplace="${PUBLISH_TO_JBPM}" \ + -DimageRepoBase=$IMAGE_REPO_BASE || RESULT=$? + + { + echo "leeway_sboms_dir=$sboms_dir" + echo "leeway_vulnerability_reports_dir=$scans_dir" + } >> $GITHUB_OUTPUT + + cat "$scans_dir/vulnerability-summary.md" >> $GITHUB_STEP_SUMMARY + + exit $RESULT + - name: Check for Critical Vulnerabilities + if: needs.configuration.outputs.is_scheduled_run == 'true' + id: check_vulnerabilities + shell: bash run: | - ./scripts/trivy/trivy-scan-images.sh ${{ needs.configuration.outputs.version }} CRITICAL - exit $? + # Parse vulnerability-stats.json from the scans directory + CRITICAL_PACKAGES=$(jq -r '.[] | select(.critical > 0) | "\(.name): \(.critical) critical vulnerabilities"' "${{ steps.scan.outputs.leeway_vulnerability_reports_dir }}/vulnerability-stats.json") + # If there are critical packages, list them and fail the build + if [ -n "$CRITICAL_PACKAGES" ]; then + echo "::error::Critical vulnerabilities found in the following packages:" + echo "$CRITICAL_PACKAGES" | tee -a $GITHUB_STEP_SUMMARY + echo "affected_packages<> $GITHUB_OUTPUT + echo "$CRITICAL_PACKAGES" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + exit 1 + else + echo "No critical vulnerabilities found." + fi + - name: Upload SBOMs + uses: actions/upload-artifact@v4 + with: + name: sboms + path: ${{ steps.scan.outputs.leeway_sboms_dir }} + - name: Upload vulnerability reports + uses: actions/upload-artifact@v4 + with: + name: vulnerability-reports + path: ${{ steps.scan.outputs.leeway_vulnerability_reports_dir }} install-app: runs-on: ${{ needs.create-runner.outputs.label }} - needs: [ configuration, build-gitpod, trivy-scan, create-runner ] - if: ${{ needs.configuration.outputs.is_main_branch == 'true' }} + needs: [ configuration, build-gitpod, create-runner ] + if: ${{ needs.configuration.outputs.is_main_branch == 'true' && needs.configuration.outputs.is_scheduled_run != 'true' }} strategy: fail-fast: false matrix: @@ -375,9 +438,9 @@ jobs: - configuration - build-previewctl - build-gitpod - - trivy-scan - infrastructure - create-runner + if: needs.configuration.outputs.is_scheduled_run != 'true' runs-on: ${{ needs.create-runner.outputs.label }} concurrency: group: ${{ github.ref == 'refs/heads/main' && github.run_id || github.sha }}-install @@ -428,7 +491,7 @@ jobs: name: "Install Monitoring Satellite" needs: [ infrastructure, build-previewctl, create-runner ] runs-on: ${{ needs.create-runner.outputs.label }} - if: needs.configuration.outputs.with_monitoring == 'true' + if: needs.configuration.outputs.with_monitoring == 'true' && needs.configuration.outputs.is_scheduled_run != 'true' concurrency: group: ${{ github.ref == 'refs/heads/main' && github.run_id || github.sha }}-monitoring cancel-in-progress: true @@ -458,8 +521,8 @@ jobs: - create-runner runs-on: ${{ needs.create-runner.outputs.label }} container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 - if: needs.configuration.outputs.with_integration_tests != '' + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 + if: needs.configuration.outputs.with_integration_tests != '' && needs.configuration.outputs.is_scheduled_run != 'true' concurrency: group: ${{ needs.configuration.outputs.preview_name }}-integration-test cancel-in-progress: true @@ -489,7 +552,7 @@ jobs: - configuration - build-gitpod - create-runner - if: needs.configuration.outputs.is_main_branch == 'true' + if: needs.configuration.outputs.is_main_branch == 'true' && needs.configuration.outputs.is_scheduled_run != 'true' uses: ./.github/workflows/workspace-integration-tests.yml with: version: ${{ needs.configuration.outputs.version }} @@ -501,7 +564,7 @@ jobs: - configuration - build-gitpod - create-runner - if: needs.configuration.outputs.is_main_branch == 'true' + if: needs.configuration.outputs.is_main_branch == 'true' && needs.configuration.outputs.is_scheduled_run != 'true' uses: ./.github/workflows/code-updates.yml secrets: inherit @@ -511,10 +574,31 @@ jobs: - configuration - build-gitpod - create-runner - if: needs.configuration.outputs.is_main_branch == 'true' + if: needs.configuration.outputs.is_main_branch == 'true' && needs.configuration.outputs.is_scheduled_run != 'true' uses: ./.github/workflows/jetbrains-updates.yml secrets: inherit + notify-scheduled-failure: + name: "Notify on scheduled run failure" + if: needs.configuration.outputs.is_scheduled_run == 'true' && failure() + needs: + - configuration + - build-gitpod + - workspace-integration-tests-main + - ide-code-updates + - ide-jb-updates + runs-on: ubuntu-latest + steps: + - name: Slack Notification + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{ secrets.WORKSPACE_SLACK_WEBHOOK }} + SLACK_ICON_EMOJI: ":x:" + SLACK_USERNAME: "Scheduled Build" + SLACK_COLOR: "danger" + SLACK_MESSAGE: "⚠️ Security Alert: Daily vulnerability scan detected critical vulnerabilities in the following packages:\n${{ needs.build-gitpod.outputs.affected_packages }}" + SLACK_FOOTER: "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Workflow Logs>" + delete-runner: if: always() needs: @@ -523,11 +607,11 @@ jobs: - build-previewctl - infrastructure - build-gitpod - - trivy-scan - install-app - install - monitoring - integration-test + - notify-scheduled-failure uses: gitpod-io/gce-github-runner/.github/workflows/delete-vm.yml@main secrets: gcp_credentials: ${{ secrets.SELF_HOSTED_GITHUB_RUNNER_GCP_CREDENTIALS }} diff --git a/.github/workflows/code-nightly.yml b/.github/workflows/code-nightly.yml index da1700eed14edf..644080fec06dc8 100644 --- a/.github/workflows/code-nightly.yml +++ b/.github/workflows/code-nightly.yml @@ -18,7 +18,7 @@ jobs: runs-on: ${{ needs.create-runner.outputs.label }} needs: [create-runner] container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-environment diff --git a/.github/workflows/ide-integration-tests.yml b/.github/workflows/ide-integration-tests.yml index 87dc0c551df0fe..d9a83804613bd9 100644 --- a/.github/workflows/ide-integration-tests.yml +++ b/.github/workflows/ide-integration-tests.yml @@ -43,7 +43,7 @@ jobs: runs-on: ${{ needs.create-runner.outputs.label }} needs: [create-runner] container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 outputs: name: ${{ steps.configuration.outputs.name }} version: ${{ steps.configuration.outputs.version }} @@ -131,7 +131,7 @@ jobs: needs: [configuration, infrastructure, create-runner] runs-on: ${{ needs.create-runner.outputs.label }} container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 volumes: - /var/tmp:/var/tmp - /tmp:/tmp diff --git a/.github/workflows/jetbrains-auto-update-template.yml b/.github/workflows/jetbrains-auto-update-template.yml index cf262e6a6cc03d..945a479af9839c 100644 --- a/.github/workflows/jetbrains-auto-update-template.yml +++ b/.github/workflows/jetbrains-auto-update-template.yml @@ -23,7 +23,7 @@ jobs: update-jetbrains: runs-on: ${{ needs.create-runner.outputs.label }} container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 needs: [ create-runner ] steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/jetbrains-integration-test.yml b/.github/workflows/jetbrains-integration-test.yml index 75564321c27e21..fac228c97d4ee3 100644 --- a/.github/workflows/jetbrains-integration-test.yml +++ b/.github/workflows/jetbrains-integration-test.yml @@ -39,7 +39,7 @@ jobs: gcp_credentials: ${{ secrets.SELF_HOSTED_GITHUB_RUNNER_GCP_CREDENTIALS }} jetbrains-smoke-test-linux: container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 runs-on: ${{ needs.create-runner.outputs.label }} needs: [create-runner] steps: diff --git a/.github/workflows/preview-env-check-regressions.yml b/.github/workflows/preview-env-check-regressions.yml index 1470bcc1084fba..57e7f64f4be458 100644 --- a/.github/workflows/preview-env-check-regressions.yml +++ b/.github/workflows/preview-env-check-regressions.yml @@ -99,7 +99,7 @@ jobs: if: ${{ needs.configuration.outputs.skip == 'false' }} runs-on: ${{ needs.create-runner.outputs.label }} container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 volumes: - /var/tmp:/var/tmp - /tmp:/tmp diff --git a/.github/workflows/preview-env-gc.yml b/.github/workflows/preview-env-gc.yml index dbf3fde5e940c0..4c4c7459270400 100644 --- a/.github/workflows/preview-env-gc.yml +++ b/.github/workflows/preview-env-gc.yml @@ -18,7 +18,7 @@ jobs: runs-on: ${{ needs.create-runner.outputs.label }} needs: [create-runner] container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 outputs: names: ${{ steps.set-matrix.outputs.names }} count: ${{ steps.set-matrix.outputs.count }} diff --git a/.github/workflows/workspace-integration-tests.yml b/.github/workflows/workspace-integration-tests.yml index 769c877cac6bd8..be509588cbaef6 100644 --- a/.github/workflows/workspace-integration-tests.yml +++ b/.github/workflows/workspace-integration-tests.yml @@ -61,7 +61,7 @@ jobs: runs-on: ${{ needs.create-runner.outputs.label }} needs: [create-runner] container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 outputs: name: ${{ steps.configuration.outputs.name }} version: ${{ steps.configuration.outputs.version }} @@ -166,7 +166,7 @@ jobs: needs: [configuration, infrastructure, create-runner] runs-on: ${{ needs.create-runner.outputs.label }} container: - image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 + image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 steps: - uses: actions/checkout@v4 - name: Integration Test diff --git a/.gitpod.yml b/.gitpod.yml index 23049f47590b5c..4125c8d03181aa 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,4 +1,4 @@ -image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32399 +image: eu.gcr.io/gitpod-core-dev/dev/dev-environment:main-gha.32507 workspaceLocation: gitpod/gitpod-ws.code-workspace checkoutLocation: gitpod ports: diff --git a/WORKSPACE.yaml b/WORKSPACE.yaml index 5de69948366928..5d812f4f0da70c 100644 --- a/WORKSPACE.yaml +++ b/WORKSPACE.yaml @@ -31,6 +31,20 @@ defaultArgs: provenance: enabled: true slsa: true +sbom: + enabled: true + ignoreVulnerabilities: + - vulnerability: GHSA-fx4w-v43j-vc45 + reason: | + This vulnerability in TypeORM's findOne / findOneOrFail functions can improperly interpret a crafted JSON object + and concatenate it into raw SQL, potentially allowing SQL injection attacks. + + In Gitpod’s usage, TypeORM is not exposed to arbitrary user input. For example, DB migrations run preset queries; + the server/bridge code does not hand raw JSON from external sources to findOne. Therefore, there is no path for + injecting malicious JSON into a query, rendering the vulnerability non-exploitable. + - vulnerability: GHSA-2jcg-qqmg-46q6 + reason: | + This is a false positive. See https://github.com/browserify/resolve/issues/303 environmentManifest: - name: "go" command: ["sh", "-c", "go version | sed s/arm/amd/"] diff --git a/components/BUILD.yaml b/components/BUILD.yaml index d847b05a7cd52f..34467793e192cc 100644 --- a/components/BUILD.yaml +++ b/components/BUILD.yaml @@ -9,6 +9,7 @@ packages: - version deps: - :all-docker + - :needs-vuln-scan - :docker-versions - :publish-api - dev:all-app @@ -95,6 +96,33 @@ packages: - ["sh", "-c", "echo \"version: ${version}\" >> versions.yaml"] - ["sh", "-c", "dev-version-manifest--app/version-manifest >> versions.yaml"] - ["sh", "-c", "rm -r components* dev-*"] + - name: needs-vuln-scan + type: generic + deps: + - components/blobserve:docker + - components/content-service:docker + - components/dashboard:docker + - components/docker-up:docker + - components/ee/agent-smith:docker + - components/gitpod-db:docker + - components/ide-metrics:docker + - components/ide-proxy:docker + - components/ide-service:docker + - components/image-builder-bob:docker + - components/image-builder-mk3:docker + - components/node-labeler:docker + - components/openvsx-proxy:docker + - components/proxy:docker + - components/public-api-server:docker + - components/registry-facade:docker + - components/server:docker + - components/service-waiter:docker + - components/supervisor:docker + - components/workspacekit:docker + - components/ws-daemon:docker + - components/ws-manager-bridge:docker + - components/ws-manager-mk2:docker + - components/ws-proxy:docker - name: publish-api type: generic deps: