From 6a5312e2c5c03dc7128d08742b1e462b9ca8cafd Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Thu, 24 Sep 2026 20:51:31 +0530 Subject: [PATCH 01/16] ci: add CodeQL and Grype image scan workflows Signed-off-by: Raman Tehlan --- .github/workflows/codeql.yml | 105 +++++++++++++++++++++++++++++++ .github/workflows/image-scan.yml | 20 ++++++ 2 files changed, 125 insertions(+) create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/image-scan.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..90d224e62 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,105 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + # Temporary: remove after first successful run + workflow_dispatch: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '23 18 * * 2' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: javascript-typescript + build-mode: none + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - name: Run manual build steps + if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml new file mode 100644 index 000000000..456c27cce --- /dev/null +++ b/.github/workflows/image-scan.yml @@ -0,0 +1,20 @@ +name: Scan and Generate Grype Report + +on: + # Temporary: remove after first successful run + workflow_dispatch: + pull_request: + schedule: + - cron: '0 9 * * *' + +jobs: + image-scan: + name: Image Vulnerability Scan + uses: truefoundry/workflows/.github/workflows/update-grype-report.yml@main + with: + enable_ecr_auth: true + image_artifact_name: ${{ github.event.repository.name }} + artifactory_repository_url: ${{ vars.TRUEFOUNDRY_ARTIFACTORY_PRIVATE_REPOSITORY }} + secrets: + ecr_iam_role_arn: ${{ secrets.AWS_DEVTEST_ECR_IAM_ROLE_ARN }} + workflow_repo_token: ${{ secrets.TF_GITHUB_CI_ADMIN_TOKEN }} From 7c2cef046bf63ddf9213ad04fc3b769350c2f3b6 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Thu, 24 Sep 2026 21:20:49 +0530 Subject: [PATCH 02/16] ci: grant image scan job the permissions its called workflow needs Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 456c27cce..17e8f9d27 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -7,9 +7,15 @@ on: schedule: - cron: '0 9 * * *' +permissions: {} + jobs: image-scan: name: Image Vulnerability Scan + # The called workflow commits .grype.yaml updates and assumes the ECR role. + permissions: + contents: write + id-token: write uses: truefoundry/workflows/.github/workflows/update-grype-report.yml@main with: enable_ecr_auth: true From 6b075621524fe12459135080f7dbc0754d467719 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Thu, 24 Sep 2026 21:27:23 +0530 Subject: [PATCH 03/16] ci: call public Grype workflow like CruiseKube Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 17e8f9d27..5c3ea886b 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -7,20 +7,11 @@ on: schedule: - cron: '0 9 * * *' -permissions: {} - jobs: image-scan: name: Image Vulnerability Scan - # The called workflow commits .grype.yaml updates and assumes the ECR role. - permissions: - contents: write - id-token: write - uses: truefoundry/workflows/.github/workflows/update-grype-report.yml@main + uses: truefoundry/github-workflows-public/.github/workflows/update-grype-report.yml@main with: - enable_ecr_auth: true - image_artifact_name: ${{ github.event.repository.name }} - artifactory_repository_url: ${{ vars.TRUEFOUNDRY_ARTIFACTORY_PRIVATE_REPOSITORY }} - secrets: - ecr_iam_role_arn: ${{ secrets.AWS_DEVTEST_ECR_IAM_ROLE_ARN }} - workflow_repo_token: ${{ secrets.TF_GITHUB_CI_ADMIN_TOKEN }} + dockerfile_path: 'Dockerfile' + image_artifact_name: 'trueforge' + artifactory_repository_url: ${{ vars.TRUEFOUNDRY_ARTIFACTORY_PUBLIC_REPOSITORY }} From c42363fe3ea5040e8519cff1d1dd099f1c2c3aef Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Thu, 24 Sep 2026 21:33:28 +0530 Subject: [PATCH 04/16] ci: pass Chart appVersion into the Grype image build Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 5c3ea886b..98431dc02 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -8,10 +8,25 @@ on: - cron: '0 9 * * *' jobs: + resolve: + name: Resolve APP_VERSION + runs-on: ubuntu-latest + outputs: + app_version: ${{ steps.app.outputs.app_version }} + steps: + - uses: actions/checkout@v7 + - id: app + run: | + APP_VERSION=$(yq -r '.appVersion' charts/trueforge/Chart.yaml) + echo "app_version=$APP_VERSION" >> "$GITHUB_OUTPUT" + image-scan: name: Image Vulnerability Scan + needs: [resolve] uses: truefoundry/github-workflows-public/.github/workflows/update-grype-report.yml@main with: dockerfile_path: 'Dockerfile' image_artifact_name: 'trueforge' artifactory_repository_url: ${{ vars.TRUEFOUNDRY_ARTIFACTORY_PUBLIC_REPOSITORY }} + image_build_args: | + APP_VERSION=${{ needs.resolve.outputs.app_version }} From 2f0085a1d6bc9406ed35db27d49e95f551cb6852 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 11:04:35 +0530 Subject: [PATCH 05/16] ci: drop the CodeQL workflow for now Keep the Grype image scan and add CodeQL in a later change. Signed-off-by: Raman Tehlan --- .github/workflows/codeql.yml | 105 ----------------------------------- 1 file changed, 105 deletions(-) delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 90d224e62..000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,105 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL Advanced" - -on: - # Temporary: remove after first successful run - workflow_dispatch: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - schedule: - - cron: '23 18 * * 2' - -jobs: - analyze: - name: Analyze (${{ matrix.language }}) - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners (GitHub.com only) - # Consider using larger runners or machines with greater resources for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - permissions: - # required for all workflows - security-events: write - - # required to fetch internal or private CodeQL packs - packages: read - - # only required for workflows in private repositories - actions: read - contents: read - - strategy: - fail-fast: false - matrix: - include: - - language: actions - build-mode: none - - language: javascript-typescript - build-mode: none - - language: python - build-mode: none - # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' - # Use `c-cpp` to analyze code written in C, C++ or both - # Use 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, - # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. - # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how - # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages - steps: - - name: Checkout repository - uses: actions/checkout@v7 - - # Add any setup steps before running the `github/codeql-action/init` action. - # This includes steps like installing compilers or runtimes (`actions/setup-node` - # or others). This is typically only required for manual builds. - # - name: Setup runtime (example) - # uses: actions/setup-example@v1 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v4 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - name: Run manual build steps - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 - with: - category: "/language:${{matrix.language}}" From 37cbd62d1f6f85f24fdc77d4a7039dfc75073737 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 11:42:12 +0530 Subject: [PATCH 06/16] ci: pass Grype build args as a single line The called workflow runs image_build_args through toJSON, so the block scalar's trailing newline reached Docker as a literal "\n" and npm rejected the package tag. Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 98431dc02..89ae82330 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -28,5 +28,6 @@ jobs: dockerfile_path: 'Dockerfile' image_artifact_name: 'trueforge' artifactory_repository_url: ${{ vars.TRUEFOUNDRY_ARTIFACTORY_PUBLIC_REPOSITORY }} - image_build_args: | - APP_VERSION=${{ needs.resolve.outputs.app_version }} + # Single-line on purpose: the called workflow passes this through toJSON, + # so a block scalar's trailing newline would leak into the build arg. + image_build_args: APP_VERSION=${{ needs.resolve.outputs.app_version }} From 41173ad1de4994dc08191ced383e2aa94e2873eb Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 11:49:20 +0530 Subject: [PATCH 07/16] ci: restore the CodeQL workflow Bring back Actions, JavaScript/TypeScript, and Python analysis so it can be run on this branch. Signed-off-by: Raman Tehlan --- .github/workflows/codeql.yml | 105 +++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..90d224e62 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,105 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + # Temporary: remove after first successful run + workflow_dispatch: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '23 18 * * 2' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: javascript-typescript + build-mode: none + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - name: Run manual build steps + if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{matrix.language}}" From be40ded2e852f0cdaae4ab3d43e4e3a643c87f5f Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 11:55:54 +0530 Subject: [PATCH 08/16] ci: upload the Grype SARIF report to code scanning The shared workflow only keeps JSON for the ignore-list PR, so scan the same image separately and publish it under Security. Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 89ae82330..2f4e34338 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -31,3 +31,45 @@ jobs: # Single-line on purpose: the called workflow passes this through toJSON, # so a block scalar's trailing newline would leak into the build arg. image_build_args: APP_VERSION=${{ needs.resolve.outputs.app_version }} + + # The shared workflow writes JSON for the ignore-list PR and does not publish it. + # This job scans the same image to SARIF so findings land in Security > Code scanning. + upload-grype: + name: Upload Grype results + needs: [resolve] + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + steps: + - uses: actions/checkout@v7 + + - uses: docker/setup-buildx-action@v3 + + - name: Build image + uses: docker/build-push-action@v6 + with: + load: true + file: Dockerfile + context: . + platforms: linux/amd64 + provenance: false + tags: trueforge:grype-report + build-args: APP_VERSION=${{ needs.resolve.outputs.app_version }} + + - name: Scan image + id: scan + uses: anchore/scan-action@v6 + with: + image: trueforge:grype-report + fail-build: false + output-format: sarif + # Include every severity. fail-build is off, so findings are reported, not gating. + severity-cutoff: negligible + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: ${{ steps.scan.outputs.sarif }} + category: grype-trueforge From 73e0238c2a43f804396dd261bb079c67d72f51d5 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 12:22:09 +0530 Subject: [PATCH 09/16] fix: base the production image on Debian 13 Debian 12 has no fix for the critical perl and glibc findings. Trixie does, and upgrading at build time picks up those packages. Signed-off-by: Raman Tehlan --- Dockerfile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index afb5dc4b2..affdd1db4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,13 +9,21 @@ # Example: # docker build --build-arg APP_VERSION=0.1.0 -t trueforge:0.1.0 . -FROM node:24-slim AS runner +# Debian 13. node:24-slim is still Debian 12, which has no fix for the critical +# perl-base and glibc CVEs (fixed in trixie perl 5.40.1-6+deb13u1 and +# glibc 2.41-12+deb13u4). +FROM node:24-trixie-slim AS runner WORKDIR /app # HOST=0.0.0.0 so Kubernetes Service/probe traffic reaches the process. ENV NODE_ENV=production \ STANDALONE=false \ HOST=0.0.0.0 +# Pick up security updates newer than the base image snapshot. +RUN apt-get update \ + && apt-get upgrade -y --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + ARG APP_VERSION RUN test -n "$APP_VERSION" || (echo "APP_VERSION build-arg is required" >&2 && exit 1) From 72d7251da4b6acee1b040effe291cd97c167163d Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 12:34:04 +0530 Subject: [PATCH 10/16] Revert "fix: base the production image on Debian 13" This reverts commit 73e0238c2a43f804396dd261bb079c67d72f51d5. Signed-off-by: Raman Tehlan --- Dockerfile | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index affdd1db4..afb5dc4b2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,21 +9,13 @@ # Example: # docker build --build-arg APP_VERSION=0.1.0 -t trueforge:0.1.0 . -# Debian 13. node:24-slim is still Debian 12, which has no fix for the critical -# perl-base and glibc CVEs (fixed in trixie perl 5.40.1-6+deb13u1 and -# glibc 2.41-12+deb13u4). -FROM node:24-trixie-slim AS runner +FROM node:24-slim AS runner WORKDIR /app # HOST=0.0.0.0 so Kubernetes Service/probe traffic reaches the process. ENV NODE_ENV=production \ STANDALONE=false \ HOST=0.0.0.0 -# Pick up security updates newer than the base image snapshot. -RUN apt-get update \ - && apt-get upgrade -y --no-install-recommends \ - && rm -rf /var/lib/apt/lists/* - ARG APP_VERSION RUN test -n "$APP_VERSION" || (echo "APP_VERSION build-arg is required" >&2 && exit 1) From a3289556f60129a4e4d5b30eaf2be02f9c5893df Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 12:42:25 +0530 Subject: [PATCH 11/16] ci: set explicit token permissions on the image scan Code scanning flagged the missing permissions block. The shared workflow still needs contents write so it can update the ignore list. Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 2f4e34338..89fc86241 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -7,10 +7,14 @@ on: schedule: - cron: '0 9 * * *' +permissions: {} + jobs: resolve: name: Resolve APP_VERSION runs-on: ubuntu-latest + permissions: + contents: read outputs: app_version: ${{ steps.app.outputs.app_version }} steps: @@ -23,6 +27,9 @@ jobs: image-scan: name: Image Vulnerability Scan needs: [resolve] + # The shared workflow commits .grype.yaml and opens the ignore-list pull request. + permissions: + contents: write uses: truefoundry/github-workflows-public/.github/workflows/update-grype-report.yml@main with: dockerfile_path: 'Dockerfile' From 6eaf7a0065c6cee475c97a5c7a35f3fd2cd11719 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 12:48:42 +0530 Subject: [PATCH 12/16] ci: let the image scan job open pull requests The ignore-list update pushes a branch and opens a pull request, so the job token needs both contents and pull-requests write. Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 89fc86241..e9b40d7ba 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -27,9 +27,10 @@ jobs: image-scan: name: Image Vulnerability Scan needs: [resolve] - # The shared workflow commits .grype.yaml and opens the ignore-list pull request. + # The shared workflow commits .grype.yaml (contents) and opens the ignore-list pull request. permissions: contents: write + pull-requests: write uses: truefoundry/github-workflows-public/.github/workflows/update-grype-report.yml@main with: dockerfile_path: 'Dockerfile' From 1b066eedccaddf96f1a8bd5b407353b3024865f3 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 12:51:04 +0530 Subject: [PATCH 13/16] ci: drop pull-requests write from the image scan The ignore-list pull request is not wanted, so the job token stays limited to the contents write the shared workflow declares. Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index e9b40d7ba..7f623ec5c 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -27,10 +27,10 @@ jobs: image-scan: name: Image Vulnerability Scan needs: [resolve] - # The shared workflow commits .grype.yaml (contents) and opens the ignore-list pull request. + # The shared workflow declares contents write, so the caller must grant at least that. + # No pull-requests scope on purpose: the ignore-list PR is not wanted here. permissions: contents: write - pull-requests: write uses: truefoundry/github-workflows-public/.github/workflows/update-grype-report.yml@main with: dockerfile_path: 'Dockerfile' From 6fa1497741a1a2fb5c986baa900fd43778f7bef5 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 14:59:17 +0530 Subject: [PATCH 14/16] ci: drop the temporary scan triggers Both workflows have had a successful run, so leave CodeQL on push, pull request, and the weekly schedule, and leave the image scan on the daily schedule. Signed-off-by: Raman Tehlan --- .github/workflows/codeql.yml | 2 -- .github/workflows/image-scan.yml | 3 --- 2 files changed, 5 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 90d224e62..97a17cfb2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,8 +12,6 @@ name: "CodeQL Advanced" on: - # Temporary: remove after first successful run - workflow_dispatch: push: branches: [ "main" ] pull_request: diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 7f623ec5c..3668b0851 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -1,9 +1,6 @@ name: Scan and Generate Grype Report on: - # Temporary: remove after first successful run - workflow_dispatch: - pull_request: schedule: - cron: '0 9 * * *' From 086de232307da505eaf82eacdc2d6f995dc56305 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 16:50:03 +0530 Subject: [PATCH 15/16] ci: scan the image once and run CodeQL on Monday Drop the shared Grype workflow now that the SARIF job builds and scans the same image. Move the CodeQL schedule to Monday 09:00 and delete the unused manual build step. Signed-off-by: Raman Tehlan --- .github/workflows/codeql.yml | 19 +------------------ .github/workflows/image-scan.yml | 18 ------------------ 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 97a17cfb2..1ae50e086 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,7 +17,7 @@ on: pull_request: branches: [ "main" ] schedule: - - cron: '23 18 * * 2' + - cron: '0 9 * * 1' jobs: analyze: @@ -80,23 +80,6 @@ jobs: # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - name: Run manual build steps - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 - - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 with: diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 3668b0851..bd3803abf 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -21,24 +21,6 @@ jobs: APP_VERSION=$(yq -r '.appVersion' charts/trueforge/Chart.yaml) echo "app_version=$APP_VERSION" >> "$GITHUB_OUTPUT" - image-scan: - name: Image Vulnerability Scan - needs: [resolve] - # The shared workflow declares contents write, so the caller must grant at least that. - # No pull-requests scope on purpose: the ignore-list PR is not wanted here. - permissions: - contents: write - uses: truefoundry/github-workflows-public/.github/workflows/update-grype-report.yml@main - with: - dockerfile_path: 'Dockerfile' - image_artifact_name: 'trueforge' - artifactory_repository_url: ${{ vars.TRUEFOUNDRY_ARTIFACTORY_PUBLIC_REPOSITORY }} - # Single-line on purpose: the called workflow passes this through toJSON, - # so a block scalar's trailing newline would leak into the build arg. - image_build_args: APP_VERSION=${{ needs.resolve.outputs.app_version }} - - # The shared workflow writes JSON for the ignore-list PR and does not publish it. - # This job scans the same image to SARIF so findings land in Security > Code scanning. upload-grype: name: Upload Grype results needs: [resolve] From 7859453091b79107fed0c21a000297a7dd3da9b0 Mon Sep 17 00:00:00 2001 From: Raman Tehlan Date: Mon, 28 Sep 2026 16:50:48 +0530 Subject: [PATCH 16/16] ci: drop APP_VERSION from the image scan The production Dockerfile now builds from source and does not take that build arg. Signed-off-by: Raman Tehlan --- .github/workflows/image-scan.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index bd3803abf..c98614cde 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -7,23 +7,8 @@ on: permissions: {} jobs: - resolve: - name: Resolve APP_VERSION - runs-on: ubuntu-latest - permissions: - contents: read - outputs: - app_version: ${{ steps.app.outputs.app_version }} - steps: - - uses: actions/checkout@v7 - - id: app - run: | - APP_VERSION=$(yq -r '.appVersion' charts/trueforge/Chart.yaml) - echo "app_version=$APP_VERSION" >> "$GITHUB_OUTPUT" - upload-grype: name: Upload Grype results - needs: [resolve] runs-on: ubuntu-latest permissions: actions: read @@ -43,7 +28,6 @@ jobs: platforms: linux/amd64 provenance: false tags: trueforge:grype-report - build-args: APP_VERSION=${{ needs.resolve.outputs.app_version }} - name: Scan image id: scan