From a59ede20c76e89ca83f9152b337015a14f308cad Mon Sep 17 00:00:00 2001 From: Piyush Gupta <56182734+gupta-piyush19@users.noreply.github.com> Date: Fri, 1 Aug 2025 20:05:11 +0530 Subject: [PATCH] fix: one leet security issues (#6303) --- .github/actions/cache-build-web/action.yml | 4 +- .../upload-sentry-sourcemaps/action.yml | 39 ++++++++++++------- .github/workflows/deploy-formbricks-cloud.yml | 5 ++- .github/workflows/docker-build-validation.yml | 11 ++++-- .../release-docker-github-experimental.yml | 8 ++-- .github/workflows/release-docker-github.yml | 15 ++++++- .github/workflows/release-helm-chart.yml | 30 +++++++++++--- .github/workflows/tolgee.yml | 10 ++++- .../workflows/upload-sentry-sourcemaps.yml | 13 +++---- 9 files changed, 93 insertions(+), 42 deletions(-) diff --git a/.github/actions/cache-build-web/action.yml b/.github/actions/cache-build-web/action.yml index 8c91d80d15..4db8d682c6 100644 --- a/.github/actions/cache-build-web/action.yml +++ b/.github/actions/cache-build-web/action.yml @@ -62,10 +62,12 @@ runs: shell: bash - name: Fill ENCRYPTION_KEY, ENTERPRISE_LICENSE_KEY and E2E_TESTING in .env + env: + E2E_TESTING_MODE: ${{ inputs.e2e_testing_mode }} run: | RANDOM_KEY=$(openssl rand -hex 32) sed -i "s/ENCRYPTION_KEY=.*/ENCRYPTION_KEY=${RANDOM_KEY}/" .env - echo "E2E_TESTING=${{ inputs.e2e_testing_mode }}" >> .env + echo "E2E_TESTING=$E2E_TESTING_MODE" >> .env shell: bash - run: | diff --git a/.github/actions/upload-sentry-sourcemaps/action.yml b/.github/actions/upload-sentry-sourcemaps/action.yml index c8a86eb5f9..c3bd49596b 100644 --- a/.github/actions/upload-sentry-sourcemaps/action.yml +++ b/.github/actions/upload-sentry-sourcemaps/action.yml @@ -1,23 +1,23 @@ -name: 'Upload Sentry Sourcemaps' -description: 'Extract sourcemaps from Docker image and upload to Sentry' +name: "Upload Sentry Sourcemaps" +description: "Extract sourcemaps from Docker image and upload to Sentry" inputs: docker_image: - description: 'Docker image to extract sourcemaps from' + description: "Docker image to extract sourcemaps from" required: true release_version: - description: 'Sentry release version (e.g., v1.2.3)' + description: "Sentry release version (e.g., v1.2.3)" required: true sentry_auth_token: - description: 'Sentry authentication token' + description: "Sentry authentication token" required: true environment: - description: 'Sentry environment (e.g., production, staging)' + description: "Sentry environment (e.g., production, staging)" required: false - default: 'staging' + default: "staging" runs: - using: 'composite' + using: "composite" steps: - name: Checkout code uses: actions/checkout@v4 @@ -26,13 +26,12 @@ runs: - name: Validate Sentry auth token shell: bash + env: + SENTRY_TOKEN: ${{ inputs.sentry_auth_token }} run: | set -euo pipefail echo "๐Ÿ” Validating Sentry authentication token..." - # Assign token to local variable for secure handling - SENTRY_TOKEN="${{ inputs.sentry_auth_token }}" - # Test the token by making a simple API call to Sentry response=$(curl -s -w "%{http_code}" -o /tmp/sentry_response.json \ -H "Authorization: Bearer $SENTRY_TOKEN" \ @@ -57,13 +56,23 @@ runs: - name: Extract sourcemaps from Docker image shell: bash + env: + DOCKER_IMAGE: ${{ inputs.docker_image }} run: | set -euo pipefail - echo "๐Ÿ“ฆ Extracting sourcemaps from Docker image: ${{ inputs.docker_image }}" + + # Validate docker image format (basic validation) + if [[ ! "$DOCKER_IMAGE" =~ ^[a-zA-Z0-9._/-]+:[a-zA-Z0-9._-]+$ ]] && [[ ! "$DOCKER_IMAGE" =~ ^[a-zA-Z0-9._/-]+@sha256:[A-Fa-f0-9]{64}$ ]]; then + echo "โŒ Error: Invalid docker image format. Must be in format 'image:tag' or 'image@sha256:hash'" + echo "Provided: $DOCKER_IMAGE" + exit 1 + fi + + echo "๐Ÿ“ฆ Extracting sourcemaps from Docker image: $DOCKER_IMAGE" # Create temporary container from the image and capture its ID echo "Creating temporary container..." - CONTAINER_ID=$(docker create "${{ inputs.docker_image }}") + CONTAINER_ID=$(docker create "$DOCKER_IMAGE") echo "Container created with ID: $CONTAINER_ID" # Set up cleanup function to ensure container is removed on script exit @@ -82,7 +91,7 @@ runs: # Exit with the original exit code to preserve script success/failure status exit $original_exit_code } - + # Register cleanup function to run on script exit (success or failure) trap cleanup_container EXIT @@ -113,7 +122,7 @@ runs: with: environment: ${{ inputs.environment }} version: ${{ inputs.release_version }} - sourcemaps: './extracted-next/' + sourcemaps: "./extracted-next/" - name: Clean up extracted files shell: bash diff --git a/.github/workflows/deploy-formbricks-cloud.yml b/.github/workflows/deploy-formbricks-cloud.yml index 64fc0dc1e1..096cee1bba 100644 --- a/.github/workflows/deploy-formbricks-cloud.yml +++ b/.github/workflows/deploy-formbricks-cloud.yml @@ -106,15 +106,16 @@ jobs: env: CF_ZONE_ID: ${{ secrets.CLOUDFLARE_ZONE_ID }} CF_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + ENVIRONMENT: ${{ inputs.ENVIRONMENT }} run: | # Set hostname based on environment - if [[ "${{ inputs.ENVIRONMENT }}" == "production" ]]; then + if [[ "$ENVIRONMENT" == "production" ]]; then PURGE_HOST="app.formbricks.com" else PURGE_HOST="stage.app.formbricks.com" fi - echo "Purging Cloudflare cache for host: $PURGE_HOST (environment: ${{ inputs.ENVIRONMENT }}, zone: $CF_ZONE_ID)" + echo "Purging Cloudflare cache for host: $PURGE_HOST (environment: $ENVIRONMENT, zone: $CF_ZONE_ID)" # Prepare JSON payload for selective cache purge json_payload=$(cat << EOF diff --git a/.github/workflows/docker-build-validation.yml b/.github/workflows/docker-build-validation.yml index ecde9c4f09..5432bca79a 100644 --- a/.github/workflows/docker-build-validation.yml +++ b/.github/workflows/docker-build-validation.yml @@ -47,12 +47,14 @@ jobs: - name: Build Docker Image uses: docker/build-push-action@v6 + env: + GITHUB_SHA: ${{ github.sha }} with: context: . file: ./apps/web/Dockerfile push: false load: true - tags: formbricks-test:${{ github.sha }} + tags: formbricks-test:${{ env.GITHUB_SHA }} cache-from: type=gha cache-to: type=gha,mode=max secrets: | @@ -89,6 +91,9 @@ jobs: - name: Test Docker Image with Health Check shell: bash + env: + GITHUB_SHA: ${{ github.sha }} + DUMMY_ENCRYPTION_KEY: ${{ secrets.DUMMY_ENCRYPTION_KEY }} run: | echo "๐Ÿงช Testing if the Docker image starts correctly..." @@ -100,8 +105,8 @@ jobs: $DOCKER_RUN_ARGS \ -p 3000:3000 \ -e DATABASE_URL="postgresql://test:test@host.docker.internal:5432/formbricks" \ - -e ENCRYPTION_KEY="${{ secrets.DUMMY_ENCRYPTION_KEY }}" \ - -d formbricks-test:${{ github.sha }} + -e ENCRYPTION_KEY="$DUMMY_ENCRYPTION_KEY" \ + -d "formbricks-test:$GITHUB_SHA" # Start health check polling immediately (every 5 seconds for up to 5 minutes) echo "๐Ÿฅ Polling /health endpoint every 5 seconds for up to 5 minutes..." diff --git a/.github/workflows/release-docker-github-experimental.yml b/.github/workflows/release-docker-github-experimental.yml index 8f838e0e84..c3c5eb831b 100644 --- a/.github/workflows/release-docker-github-experimental.yml +++ b/.github/workflows/release-docker-github-experimental.yml @@ -44,11 +44,11 @@ jobs: - name: Generate SemVer version from branch or tag id: generate_version + env: + REF_NAME: ${{ github.ref_name }} + REF_TYPE: ${{ github.ref_type }} run: | - # Get reference name and type - REF_NAME="${{ github.ref_name }}" - REF_TYPE="${{ github.ref_type }}" - + # Get reference name and type from environment variables echo "Reference type: $REF_TYPE" echo "Reference name: $REF_NAME" diff --git a/.github/workflows/release-docker-github.yml b/.github/workflows/release-docker-github.yml index 7e367277b3..f3e9f2c56f 100644 --- a/.github/workflows/release-docker-github.yml +++ b/.github/workflows/release-docker-github.yml @@ -9,7 +9,7 @@ on: workflow_call: inputs: IS_PRERELEASE: - description: 'Whether this is a prerelease (affects latest tag)' + description: "Whether this is a prerelease (affects latest tag)" required: false type: boolean default: false @@ -52,9 +52,20 @@ jobs: id: extract_release_tag run: | # Extract version from tag (e.g., refs/tags/v1.2.3 -> 1.2.3) - TAG=${{ github.ref }} + TAG="$GITHUB_REF" TAG=${TAG#refs/tags/v} + + # Validate the extracted tag format + if [[ ! "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then + echo "โŒ Error: Invalid release tag format after extraction. Must be semver (e.g., 1.2.3, 1.2.3-alpha)" + echo "Original ref: $GITHUB_REF" + echo "Extracted tag: $TAG" + exit 1 + fi + + # Safely add to environment variables echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV + echo "VERSION=$TAG" >> $GITHUB_OUTPUT echo "Using tag-based version: $TAG" diff --git a/.github/workflows/release-helm-chart.yml b/.github/workflows/release-helm-chart.yml index fd3bb99022..53ecc725a3 100644 --- a/.github/workflows/release-helm-chart.yml +++ b/.github/workflows/release-helm-chart.yml @@ -26,8 +26,23 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Extract release version - run: echo "VERSION=${{ github.event.release.tag_name }}" >> $GITHUB_ENV + - name: Validate input version + env: + INPUT_VERSION: ${{ inputs.VERSION }} + run: | + set -euo pipefail + # Validate input version format (expects clean semver without 'v' prefix) + if [[ ! "$INPUT_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then + echo "โŒ Error: Invalid version format. Must be clean semver (e.g., 1.2.3, 1.2.3-alpha)" + echo "Expected: clean version without 'v' prefix" + echo "Provided: $INPUT_VERSION" + exit 1 + fi + + # Store validated version in environment variable + echo "VERSION<> $GITHUB_ENV + echo "$INPUT_VERSION" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV - name: Set up Helm uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3.5 @@ -35,15 +50,18 @@ jobs: version: latest - name: Log in to GitHub Container Registry - run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_ACTOR: ${{ github.actor }} + run: printf '%s' "$GITHUB_TOKEN" | helm registry login ghcr.io --username "$GITHUB_ACTOR" --password-stdin - name: Install YQ uses: dcarbone/install-yq-action@4075b4dca348d74bd83f2bf82d30f25d7c54539b # v1.3.1 - name: Update Chart.yaml with new version run: | - yq -i ".version = \"${{ inputs.VERSION }}\"" helm-chart/Chart.yaml - yq -i ".appVersion = \"v${{ inputs.VERSION }}\"" helm-chart/Chart.yaml + yq -i ".version = \"$VERSION\"" helm-chart/Chart.yaml + yq -i ".appVersion = \"v$VERSION\"" helm-chart/Chart.yaml - name: Package Helm chart run: | @@ -51,4 +69,4 @@ jobs: - name: Push Helm chart to GitHub Container Registry run: | - helm push formbricks-${{ inputs.VERSION }}.tgz oci://ghcr.io/formbricks/helm-charts + helm push "formbricks-$VERSION.tgz" oci://ghcr.io/formbricks/helm-charts diff --git a/.github/workflows/tolgee.yml b/.github/workflows/tolgee.yml index 3a328daa5c..7ac8b940ae 100644 --- a/.github/workflows/tolgee.yml +++ b/.github/workflows/tolgee.yml @@ -27,10 +27,18 @@ jobs: - name: Get source branch name id: branch-name + env: + RAW_BRANCH: ${{ github.head_ref }} run: | - RAW_BRANCH="${{ github.head_ref }}" + # Validate and sanitize branch name - only allow alphanumeric, dots, underscores, hyphens, and forward slashes SOURCE_BRANCH=$(echo "$RAW_BRANCH" | sed 's/[^a-zA-Z0-9._\/-]//g') + # Additional validation - ensure branch name is not empty after sanitization + if [[ -z "$SOURCE_BRANCH" ]]; then + echo "โŒ Error: Branch name is empty after sanitization" + echo "Original branch: $RAW_BRANCH" + exit 1 + fi # Safely add to environment variables using GitHub's recommended method # This prevents environment variable injection attacks diff --git a/.github/workflows/upload-sentry-sourcemaps.yml b/.github/workflows/upload-sentry-sourcemaps.yml index 7af92ebc10..62bd1aff9f 100644 --- a/.github/workflows/upload-sentry-sourcemaps.yml +++ b/.github/workflows/upload-sentry-sourcemaps.yml @@ -23,7 +23,7 @@ jobs: upload-sourcemaps: name: Upload Sourcemaps to Sentry runs-on: ubuntu-latest - + steps: - name: Checkout uses: actions/checkout@v4.2.2 @@ -31,16 +31,13 @@ jobs: fetch-depth: 0 - name: Set Docker Image - run: | - if [ -n "${{ inputs.tag_version }}" ]; then - echo "DOCKER_IMAGE=${{ inputs.docker_image }}:${{ inputs.tag_version }}" >> $GITHUB_ENV - else - echo "DOCKER_IMAGE=${{ inputs.docker_image }}:${{ inputs.release_version }}" >> $GITHUB_ENV - fi + run: echo "DOCKER_IMAGE=${DOCKER_IMAGE}" >> $GITHUB_ENV + env: + DOCKER_IMAGE: ${{ inputs.docker_image }}:${{ inputs.tag_version != '' && inputs.tag_version || inputs.release_version }} - name: Upload Sourcemaps to Sentry uses: ./.github/actions/upload-sentry-sourcemaps with: docker_image: ${{ env.DOCKER_IMAGE }} release_version: ${{ inputs.release_version }} - sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }} \ No newline at end of file + sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }}