From 62ee9543f8ca13aa72f4a1bca5f034e8fbf5de0b Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Sun, 16 Aug 2026 16:07:53 +0100 Subject: [PATCH 01/13] chore: setup pre-commit and initial lint fixes --- .pre-commit-config.yaml | 5 +++++ config/disabledAlgorithms.json | 8 ++++---- src/main/java/hbp/mip/configurations/OpenApiConfig.java | 2 +- src/main/java/hbp/mip/experiment/ExperimentAPI.java | 2 +- src/main/java/hbp/mip/user/UserDTO.java | 2 +- .../java/hbp/mip/utils/ControllerExceptionHandler.java | 2 +- src/main/java/hbp/mip/utils/CustomResourceLoader.java | 2 +- .../hbp/mip/utils/Exceptions/BadRequestException.java | 2 +- .../mip/utils/Exceptions/ExperimentNotFoundException.java | 2 +- .../hbp/mip/utils/Exceptions/InternalServerError.java | 2 +- src/main/java/hbp/mip/utils/Exceptions/NoContent.java | 2 +- .../hbp/mip/utils/Exceptions/UnauthorizedException.java | 2 +- 12 files changed, 19 insertions(+), 14 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e0d92dfdd..60dc5bee0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,3 +13,8 @@ repos: - id: pretty-format-json args: ["--autofix"] exclude: slack.json + +- repo: https://github.com/gitleaks/gitleaks + rev: v8.21.2 + hooks: + - id: gitleaks diff --git a/config/disabledAlgorithms.json b/config/disabledAlgorithms.json index 6fc4a5d46..01cb167b7 100644 --- a/config/disabledAlgorithms.json +++ b/config/disabledAlgorithms.json @@ -1,4 +1,4 @@ -[ - "THREE_C", - "KAPLAN_MEIER" -] \ No newline at end of file +[ + "THREE_C", + "KAPLAN_MEIER" +] diff --git a/src/main/java/hbp/mip/configurations/OpenApiConfig.java b/src/main/java/hbp/mip/configurations/OpenApiConfig.java index 0ee5264d3..9ecc8e290 100644 --- a/src/main/java/hbp/mip/configurations/OpenApiConfig.java +++ b/src/main/java/hbp/mip/configurations/OpenApiConfig.java @@ -15,4 +15,4 @@ public OpenAPI usersMicroserviceOpenAPI() { .info(new Info().title("Platform-backend API") .version("1.0")); } -} \ No newline at end of file +} diff --git a/src/main/java/hbp/mip/experiment/ExperimentAPI.java b/src/main/java/hbp/mip/experiment/ExperimentAPI.java index faca46b36..a34561cd8 100644 --- a/src/main/java/hbp/mip/experiment/ExperimentAPI.java +++ b/src/main/java/hbp/mip/experiment/ExperimentAPI.java @@ -132,4 +132,4 @@ public ResponseEntity createTransientExperiment(Authentication au return new ResponseEntity<>(experimentResponse, HttpStatus.OK); } -} \ No newline at end of file +} diff --git a/src/main/java/hbp/mip/user/UserDTO.java b/src/main/java/hbp/mip/user/UserDTO.java index 3b68be5cf..48a62b4ac 100644 --- a/src/main/java/hbp/mip/user/UserDTO.java +++ b/src/main/java/hbp/mip/user/UserDTO.java @@ -10,4 +10,4 @@ public UserDTO(UserDAO userDAO){ userDAO.getAgreeNDA() ); } -} \ No newline at end of file +} diff --git a/src/main/java/hbp/mip/utils/ControllerExceptionHandler.java b/src/main/java/hbp/mip/utils/ControllerExceptionHandler.java index a86cfb492..1f284f6b8 100644 --- a/src/main/java/hbp/mip/utils/ControllerExceptionHandler.java +++ b/src/main/java/hbp/mip/utils/ControllerExceptionHandler.java @@ -27,7 +27,7 @@ public ResponseEntity handleExperimentNotFoundException(ExperimentNotFou return new ResponseEntity<>(message, HttpStatus.NOT_FOUND); } - + @ExceptionHandler(BadRequestException.class) public ResponseEntity handleBadRequestException(BadRequestException ex, WebRequest request) { ErrorMessage message = new ErrorMessage( diff --git a/src/main/java/hbp/mip/utils/CustomResourceLoader.java b/src/main/java/hbp/mip/utils/CustomResourceLoader.java index 89552146c..4fd0f5dd7 100644 --- a/src/main/java/hbp/mip/utils/CustomResourceLoader.java +++ b/src/main/java/hbp/mip/utils/CustomResourceLoader.java @@ -18,4 +18,4 @@ public void setResourceLoader(@NonNull ResourceLoader resourceLoader) { public Resource getResource(String resourceLocation) { return resourceLoader.getResource(resourceLocation); } -} \ No newline at end of file +} diff --git a/src/main/java/hbp/mip/utils/Exceptions/BadRequestException.java b/src/main/java/hbp/mip/utils/Exceptions/BadRequestException.java index a83830665..cd3bfb4d1 100644 --- a/src/main/java/hbp/mip/utils/Exceptions/BadRequestException.java +++ b/src/main/java/hbp/mip/utils/Exceptions/BadRequestException.java @@ -5,4 +5,4 @@ public class BadRequestException extends RuntimeException { public BadRequestException(String msg) { super(msg); } -} \ No newline at end of file +} diff --git a/src/main/java/hbp/mip/utils/Exceptions/ExperimentNotFoundException.java b/src/main/java/hbp/mip/utils/Exceptions/ExperimentNotFoundException.java index 303735509..cfec9a6ed 100644 --- a/src/main/java/hbp/mip/utils/Exceptions/ExperimentNotFoundException.java +++ b/src/main/java/hbp/mip/utils/Exceptions/ExperimentNotFoundException.java @@ -5,4 +5,4 @@ public class ExperimentNotFoundException extends RuntimeException { public ExperimentNotFoundException(String msg) { super(msg); } -} \ No newline at end of file +} diff --git a/src/main/java/hbp/mip/utils/Exceptions/InternalServerError.java b/src/main/java/hbp/mip/utils/Exceptions/InternalServerError.java index 31357164f..2439779b2 100644 --- a/src/main/java/hbp/mip/utils/Exceptions/InternalServerError.java +++ b/src/main/java/hbp/mip/utils/Exceptions/InternalServerError.java @@ -5,4 +5,4 @@ public class InternalServerError extends RuntimeException { public InternalServerError(String msg) { super(msg); } -} \ No newline at end of file +} diff --git a/src/main/java/hbp/mip/utils/Exceptions/NoContent.java b/src/main/java/hbp/mip/utils/Exceptions/NoContent.java index 6ac31b899..66e2ba167 100644 --- a/src/main/java/hbp/mip/utils/Exceptions/NoContent.java +++ b/src/main/java/hbp/mip/utils/Exceptions/NoContent.java @@ -5,4 +5,4 @@ public class NoContent extends RuntimeException { public NoContent(String msg) { super(msg); } -} \ No newline at end of file +} diff --git a/src/main/java/hbp/mip/utils/Exceptions/UnauthorizedException.java b/src/main/java/hbp/mip/utils/Exceptions/UnauthorizedException.java index 1cbe3cf20..bb07f6f57 100644 --- a/src/main/java/hbp/mip/utils/Exceptions/UnauthorizedException.java +++ b/src/main/java/hbp/mip/utils/Exceptions/UnauthorizedException.java @@ -5,4 +5,4 @@ public class UnauthorizedException extends RuntimeException { public UnauthorizedException(String msg) { super(msg); } -} \ No newline at end of file +} From 570d0389ec708aa2ca8598d84dca6e9c155a4142 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Sun, 16 Aug 2026 16:18:05 +0100 Subject: [PATCH 02/13] pre-commit-config negative testing --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 60dc5bee0..3e4d5f7c9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,6 +10,7 @@ repos: - id: check-added-large-files - id: check-yaml - id: check-json + - id: check-xml - id: pretty-format-json args: ["--autofix"] exclude: slack.json From eb2b2e8cf1ac701004bb5ee2d1988c4d8a5eb719 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Sun, 16 Aug 2026 17:20:43 +0100 Subject: [PATCH 03/13] pin pre-commit hook revisions to commit SHAs --- .pre-commit-config.yaml | 8 ++++++-- src/main/java/hbp/mip/utils/CustomResourceLoader.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3e4d5f7c9..7d7ffe017 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c #v6.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -14,8 +14,12 @@ repos: - id: pretty-format-json args: ["--autofix"] exclude: slack.json + - id: check-xml + - id: detect-private-key + - id: check-case-conflict + - id: mixed-line-ending - repo: https://github.com/gitleaks/gitleaks - rev: v8.21.2 + rev: afc89f91c0795f9763920d40848d770e44341b06 #v8.21.2 hooks: - id: gitleaks diff --git a/src/main/java/hbp/mip/utils/CustomResourceLoader.java b/src/main/java/hbp/mip/utils/CustomResourceLoader.java index 4fd0f5dd7..6f6e536bc 100644 --- a/src/main/java/hbp/mip/utils/CustomResourceLoader.java +++ b/src/main/java/hbp/mip/utils/CustomResourceLoader.java @@ -18,4 +18,4 @@ public void setResourceLoader(@NonNull ResourceLoader resourceLoader) { public Resource getResource(String resourceLocation) { return resourceLoader.getResource(resourceLocation); } -} +} From 367d307b8b4b443e00c7e14c1f053fcd62964bc1 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Tue, 18 Aug 2026 22:56:27 +0100 Subject: [PATCH 04/13] fix(docker): pin base images to digests and use JSON notation for HEALTHCHECK --- Dockerfile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index b08839aff..aa9181a31 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ ####################################################### # Build the spring boot maven project ####################################################### -FROM maven:3.9.11-amazoncorretto-21 AS mvn-build-env +FROM maven:3.9.11-amazoncorretto-21@sha256:82d98fbed447e3f7dfbf1089840a51bfaeb5651cb47a9c5820139d054db3dde1 AS mvn-build-env LABEL maintainer="Thanasis Karampatsis " ENV CODE_PATH="/opt/code" @@ -19,7 +19,7 @@ RUN mvn -B -ntp clean package ####################################################### # Setup the running container ####################################################### -FROM amazoncorretto:21-alpine3.21 +FROM amazoncorretto:21-alpine3.21@sha256:392b286e53c7f4cd366bd2f752f509b7e24de9f414564bccd7d152a58214a8b6 ####################################################### # Setting up timezone @@ -51,14 +51,12 @@ RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSI && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz - ####################################################### # Prepare the spring boot application files ####################################################### COPY config/application.tmpl $APP_CONFIG_TEMPLATE COPY --from=mvn-build-env /opt/code/target/platform-backend.jar /usr/share/jars/ - ####################################################### # Configuration for the backend config files ####################################################### @@ -73,4 +71,4 @@ RUN addgroup -S appgroup && adduser -S appuser -G appgroup \ USER appuser ENTRYPOINT ["sh", "-ec", "exec dockerize -template ${APP_CONFIG_TEMPLATE}:${APP_CONFIG_LOCATION} java --add-opens java.base/java.io=ALL-UNNAMED -Daeron.term.buffer.length -jar /usr/share/jars/platform-backend.jar"] EXPOSE 8080 -HEALTHCHECK --start-period=60s CMD curl --fail --silent --show-error http://localhost:8080/services/actuator/health | grep -q '"status":"UP"' +HEALTHCHECK --start-period=60s CMD ["sh", "-c", "curl --fail --silent --show-error http://localhost:8080/services/actuator/health | grep -q '\"status\":\"UP\"'"] From 1a428d9d8ce98053134f7332b31431a90368a378 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Sun, 16 Aug 2026 17:28:48 +0100 Subject: [PATCH 05/13] fix(docker): pin base images to digests and use JSON notation for HEALTHCHECK --- .github/workflows/sast.yml | 2 +- .github/workflows/secrets-scan.yml | 40 ++++++++++++++++++++++++++++++ .pre-commit-config.yaml | 5 ++-- Dockerfile | 24 +++--------------- ci/sast_scan.py | 2 +- ci/setup-tools.sh | 17 +++++++++++++ ci/suppress_gitleaks.toml | 4 +++ pom.xml | 4 +-- 8 files changed, 70 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/secrets-scan.yml create mode 100644 ci/suppress_gitleaks.toml diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 786dbc816..6bedefeb3 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -16,7 +16,7 @@ jobs: env: SEMGREP_CONFIG_RULESETS: >- semgrep-rules/generic semgrep-rules/problem-based-packs semgrep-rules/bash semgrep-rules/java auto - semgrep-rules/yaml semgrep-rules/package_managers p/default + semgrep-rules/yaml semgrep-rules/package_managers p/default p/gitleaks OPENGREP_EXCLUDE: >- *.sarif ci/ Dockerfile* .pre-commit-config.yaml docs/** README.md AGENTS.md OPENGREP_SARIF_OUTPUT: sast-semgrep-app.sarif diff --git a/.github/workflows/secrets-scan.yml b/.github/workflows/secrets-scan.yml new file mode 100644 index 000000000..cd8bb5848 --- /dev/null +++ b/.github/workflows/secrets-scan.yml @@ -0,0 +1,40 @@ +name: Secret Scanning (gitleaks) + +on: + pull_request: + push: + branches: + - master + workflow_dispatch: + +permissions: + contents: read + security-events: write + +jobs: + gitleaks: + runs-on: ubuntu-latest + env: + GITLEAKS_SARIF_OUTPUT: gitleaks.sarif + + steps: + - name: Check out repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Install gitleaks + run: bash ci/setup-tools.sh --install-tool gitleaks + + - name: Install and run gitleaks + run: > + gitleaks dir . + --config ci/suppress_gitleaks.toml + --redact + --report-format sarif + --report-path "$GITLEAKS_SARIF_OUTPUT" + + - name: Upload SARIF to code scanning + if: always() + uses: github/codeql-action/upload-sarif@c35d1b164463ee62a100735382aaaa525c5d3496 #v2.25.6 + with: + sarif_file: ${{ env.GITLEAKS_SARIF_OUTPUT }} + category: gitleaks diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7d7ffe017..3fd08481c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c #v6.0.0 + rev: v6.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -10,7 +10,6 @@ repos: - id: check-added-large-files - id: check-yaml - id: check-json - - id: check-xml - id: pretty-format-json args: ["--autofix"] exclude: slack.json @@ -20,6 +19,6 @@ repos: - id: mixed-line-ending - repo: https://github.com/gitleaks/gitleaks - rev: afc89f91c0795f9763920d40848d770e44341b06 #v8.21.2 + rev: v8.30.0 hooks: - id: gitleaks diff --git a/Dockerfile b/Dockerfile index b08839aff..2cd21516f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ ####################################################### # Build the spring boot maven project ####################################################### -FROM maven:3.9.11-amazoncorretto-21 AS mvn-build-env +FROM maven:3.9.11-amazoncorretto-21@sha256:82d98fbed447e3f7dfbf1089840a51bfaeb5651cb47a9c5820139d054db3dde1 AS mvn-build-env LABEL maintainer="Thanasis Karampatsis " ENV CODE_PATH="/opt/code" @@ -9,7 +9,6 @@ WORKDIR $CODE_PATH COPY pom.xml $CODE_PATH/ -# Pre-fetch dependencies first to improve build cache efficiency. RUN mvn -B -ntp dependency:go-offline COPY src/ $CODE_PATH/src @@ -19,17 +18,11 @@ RUN mvn -B -ntp clean package ####################################################### # Setup the running container ####################################################### -FROM amazoncorretto:21-alpine3.21 +FROM amazoncorretto:21-alpine3.21@sha256:392b286e53c7f4cd366bd2f752f509b7e24de9f414564bccd7d152a58214a8b6 -####################################################### -# Setting up timezone -####################################################### ENV TZ=Etc/GMT RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone -####################################################### -# Setting up environment -####################################################### ENV APP_CONFIG_TEMPLATE="/opt/config/application.tmpl" ENV APP_CONFIG_LOCATION="/opt/config/application.yml" ENV SPRING_CONFIG_LOCATION="file:/opt/config/application.yml" @@ -43,25 +36,14 @@ WORKDIR /opt RUN apk add --no-cache curl -####################################################### -# Install dockerize -####################################################### ENV DOCKERIZE_VERSION=v0.14.0 RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz - -####################################################### -# Prepare the spring boot application files -####################################################### COPY config/application.tmpl $APP_CONFIG_TEMPLATE COPY --from=mvn-build-env /opt/code/target/platform-backend.jar /usr/share/jars/ - -####################################################### -# Configuration for the backend config files -####################################################### ENV DISABLED_ALGORITHMS_CONFIG_PATH="/opt/platform/algorithms/disabledAlgorithms.json" COPY config/disabledAlgorithms.json $DISABLED_ALGORITHMS_CONFIG_PATH VOLUME /opt/platform/api @@ -73,4 +55,4 @@ RUN addgroup -S appgroup && adduser -S appuser -G appgroup \ USER appuser ENTRYPOINT ["sh", "-ec", "exec dockerize -template ${APP_CONFIG_TEMPLATE}:${APP_CONFIG_LOCATION} java --add-opens java.base/java.io=ALL-UNNAMED -Daeron.term.buffer.length -jar /usr/share/jars/platform-backend.jar"] EXPOSE 8080 -HEALTHCHECK --start-period=60s CMD curl --fail --silent --show-error http://localhost:8080/services/actuator/health | grep -q '"status":"UP"' +HEALTHCHECK --start-period=60s CMD ["sh", "-c", "curl --fail --silent --show-error http://localhost:8080/services/actuator/health | grep -q '\"status\":\"UP\"'"] diff --git a/ci/sast_scan.py b/ci/sast_scan.py index 5c40496d9..f127ae0db 100644 --- a/ci/sast_scan.py +++ b/ci/sast_scan.py @@ -19,7 +19,7 @@ SEMGREP_CONFIG_RULESETS = os.getenv( "SEMGREP_CONFIG_RULESETS", " semgrep-rules/generic semgrep-rules/problem-based-packs semgrep-rules/bash " - " semgrep-rules/java auto semgrep-rules/yaml semgrep-rules/package_managers p/default " + " semgrep-rules/java auto semgrep-rules/yaml semgrep-rules/package_managers p/default p/gitleaks " ).split() OPENGREP_EXCLUDE = os.getenv( "OPENGREP_EXCLUDE", diff --git a/ci/setup-tools.sh b/ci/setup-tools.sh index c24ca8de7..510453ee5 100644 --- a/ci/setup-tools.sh +++ b/ci/setup-tools.sh @@ -30,6 +30,10 @@ SEMGREP_RULES_DIR="semgrep-rules" HADOLINT_VERSION="${HADOLINT_VERSION:-v2.14.0}" HADOLINT_SHA256="${HADOLINT_SHA256:-6bf226944684f56c84dd014e8b979d27425c0148f61b3bd99bcc6f39e9dc5a47}" +# renovate: datasource=github-release-attachments depName=gitleaks/gitleaks +GITLEAKS_VERSION="${GITLEAKS_VERSION:-v8.30.1}" +GITLEAKS_SHA256="${GITLEAKS_SHA256:-551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb}" + # renovate: datasource=npm depName=@cyclonedx/cyclonedx-npm CYCLONEDX_NPM_VERSION="${CYCLONEDX_NPM_VERSION:-6.0.0}" @@ -128,6 +132,19 @@ if should_install "hadolint"; then echo "Hadolint installed OK" fi +# --- Gitleaks ----------------------------------------------------------- +if should_install "gitleaks"; then + echo "[setup-tools] Installing Gitleaks ${GITLEAKS_VERSION}" + GITLEAKS_TARBALL="gitleaks_${GITLEAKS_VERSION#v}_linux_x64.tar.gz" + download_and_verify \ + "https://github.com/gitleaks/gitleaks/releases/download/${GITLEAKS_VERSION}/${GITLEAKS_TARBALL}" \ + "${TMP_DIR}/${GITLEAKS_TARBALL}" \ + "${GITLEAKS_SHA256}" + sudo tar -xzf "${TMP_DIR}/${GITLEAKS_TARBALL}" -C /usr/local/bin gitleaks + gitleaks version + echo "Gitleaks installed OK" +fi + # --- SBOM generation ---------------------------------------------------- case "$SBOM_ECOSYSTEM" in maven) diff --git a/ci/suppress_gitleaks.toml b/ci/suppress_gitleaks.toml new file mode 100644 index 000000000..5673600f3 --- /dev/null +++ b/ci/suppress_gitleaks.toml @@ -0,0 +1,4 @@ +[allowlist] +paths = [ + '''AGENTS\.md''', +] diff --git a/pom.xml b/pom.xml index 69cfbf0a8..38c9bf80c 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 4.0.6 + 4.0.7 @@ -31,7 +31,7 @@ 2.6 10.9.1 2.21.5 - 3.1.4 + 3.1.5 From e25a3ba5eb1f53fe0640baa3942bda2695f20633 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Wed, 19 Aug 2026 11:39:52 +0100 Subject: [PATCH 06/13] chore(renovate): track DOCKERIZE_VERSION --- Dockerfile | 1 + renovate.json | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/Dockerfile b/Dockerfile index 2cd21516f..8a87ddc6d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,6 +36,7 @@ WORKDIR /opt RUN apk add --no-cache curl +# renovate: datasource=github-releases depName=jwilder/dockerize ENV DOCKERIZE_VERSION=v0.14.0 RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ diff --git a/renovate.json b/renovate.json index 7094f757a..6a7b3e477 100644 --- a/renovate.json +++ b/renovate.json @@ -21,6 +21,16 @@ "matchStrings": [ "# renovate: datasource=(?[a-z-]+) depName=(?[^\\s]+)\\n\\s*python-version:\\s*'(?[0-9][0-9.]*)'" ] + }, + { + "customType": "regex", + "description": "Bump DOCKERIZE_VERSION pinned in Dockerfile", + "managerFilePatterns": [ + "/(^|/)Dockerfile[^/]*$/" + ], + "matchStrings": [ + "# renovate: datasource=(?[a-z-]+) depName=(?[^\\s]+)\\s*\\nENV DOCKERIZE_VERSION=(?v[0-9][0-9.]*)" + ] } ], "enabledManagers": [ @@ -48,6 +58,7 @@ "matchDatasources": [ "github-release-attachments", "github-tags", + "github-releases", "npm", "python-version" ], From dfaed46deae080973fe4a214e178c8e19f89227a Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Sat, 29 Aug 2026 10:52:44 +0100 Subject: [PATCH 07/13] docs: fix outdated repo layout in README --- ci/README.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ci/README.md b/ci/README.md index ca91b851e..eb8eb4aeb 100644 --- a/ci/README.md +++ b/ci/README.md @@ -25,20 +25,22 @@ Following the OWASP DevSecOps model, scanning is split into three independent pi ``` .github/ -├── workflows/ -│ ├── container-scan.yml # builds the image, scans the Dockerfile (SAST) and image (SCA) -│ ├── sca.yml # resolves deps, generates SBOM, scans it (SCA) -│ └── sast.yml # scans source code (SAST) -└── scripts/ - ├── setup-tools.sh # installs trivy, osv-scanner, opengrep, hadolint, semgrep-rules - ├── container_scan.py # orchestrator for container-scan.yml - ├── sca_scan.py # orchestrator for sca.yml - ├── sast_scan.py # orchestrator for sast.yml - ├── parse_sarif.py # shared: reads SARIF security-severity scores - ├── suppress_trivy.yaml # shared Trivy ignore file - └── suppress_osv_scanner.toml # shared OSV-Scanner ignore file +└── workflows/ + ├── container-scan.yml # builds the image, scans the Dockerfile (SAST) and image (SCA) + ├── sca.yml # resolves deps, generates SBOM, scans it (SCA) + ├── sast.yml # scans source code (SAST) + ├── publish_images.yml # publishes built images + └── ebrains.yml # EBRAINS-specific pipeline + +ci/ +├── setup-tools.sh # installs trivy, osv-scanner, opengrep, hadolint, semgrep-rules +├── container_scan.py # orchestrator for container-scan.yml +├── sca_scan.py # orchestrator for sca.yml +├── sast_scan.py # orchestrator for sast.yml +├── parse_sarif.py # shared: reads SARIF security-severity scores +├── suppress_trivy.yaml # shared Trivy ignore file +└── suppress_osv_scanner.toml # shared OSV-Scanner ignore file ``` - > **Note:** all three workflows trigger on `pull_request`, `workflow_dispatch`, and a weekly Monday 02:00 UTC schedule, and run independently in parallel. Each has its own gate and its own category in the GitHub Security tab. ## 2. Architecture From a159937fa5f64c85e3ab491364f7dd676a5b32b8 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Sun, 30 Aug 2026 11:48:44 +0100 Subject: [PATCH 08/13] Bump Dockerize --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8a87ddc6d..f5fafe761 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ WORKDIR /opt RUN apk add --no-cache curl # renovate: datasource=github-releases depName=jwilder/dockerize -ENV DOCKERIZE_VERSION=v0.14.0 +ENV DOCKERIZE_VERSION=v0.15.0 RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz From f4eb91df8ebf72da36789ee2b18e0b6e5c95c065 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Sun, 30 Aug 2026 14:12:00 +0100 Subject: [PATCH 09/13] chore(ci): align pipeline with blueprint (gate thresholds, maven resolve, codeql-action v4) --- .github/workflows/container-scan.yml | 8 ++++---- .github/workflows/sast.yml | 2 +- .github/workflows/sca.yml | 12 ++++++------ ci/container_scan.py | 13 ++++++------- ci/parse_sarif.py | 8 ++++++-- ci/sca_scan.py | 7 +++---- ci/setup-tools.sh | 4 +++- 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/.github/workflows/container-scan.yml b/.github/workflows/container-scan.yml index c1341c184..9f9560872 100644 --- a/.github/workflows/container-scan.yml +++ b/.github/workflows/container-scan.yml @@ -57,7 +57,7 @@ jobs: - name: Upload Trivy SARIF to GitHub Security tab id: upload_trivy if: always() - uses: github/codeql-action/upload-sarif@c35d1b164463ee62a100735382aaaa525c5d3496 #v2.25.6 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: sarif_file: ${{ env.TRIVY_SCA_SARIF_OUTPUT }} category: trivy-container-scanning @@ -65,7 +65,7 @@ jobs: - name: Upload OSV Scanner SARIF to GitHub Security tab id: upload_osv if: always() - uses: github/codeql-action/upload-sarif@c35d1b164463ee62a100735382aaaa525c5d3496 #v2.25.6 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: sarif_file: ${{ env.OSV_SCA_SARIF_OUTPUT }} category: osv-scanner-container-scanning @@ -73,7 +73,7 @@ jobs: - name: Upload OpenGrep SARIF to GitHub Security tab id: upload_opengrep if: always() - uses: github/codeql-action/upload-sarif@c35d1b164463ee62a100735382aaaa525c5d3496 #v2.25.6 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: sarif_file: ${{ env.OPENGREP_SAST_SARIF_OUTPUT }} category: opengrep-sast @@ -81,7 +81,7 @@ jobs: - name: Upload Hadolint SARIF to GitHub Security tab id: upload_hadolint if: always() - uses: github/codeql-action/upload-sarif@c35d1b164463ee62a100735382aaaa525c5d3496 #v2.25.6 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: sarif_file: ${{ env.HADOLINT_SAST_SARIF_OUTPUT }} category: hadolint-sast diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 6bedefeb3..68553e30e 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -40,7 +40,7 @@ jobs: - name: Upload Semgrep SARIF to GitHub Security tab id: upload_semgrep if: always() - uses: github/codeql-action/upload-sarif@c35d1b164463ee62a100735382aaaa525c5d3496 #v2.25.6 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: sarif_file: ${{ env.OPENGREP_SARIF_OUTPUT }} category: semgrep-app diff --git a/.github/workflows/sca.yml b/.github/workflows/sca.yml index c57bf84a5..c10ec33c5 100644 --- a/.github/workflows/sca.yml +++ b/.github/workflows/sca.yml @@ -20,6 +20,9 @@ jobs: TRIVY_SARIF_OUTPUT: trivy-platform-backend.sarif OSV_SARIF_OUTPUT: osv-scanner-platform-backend.sarif SCA_MERGED_SARIF_OUTPUT: SCA-platform-backend-merged.sarif + # CVSS gate: fail at >= FAIL, warn between WARN and FAIL. + GATE_FAIL_THRESHOLD: "8.0" + GATE_WARN_THRESHOLD: "5.0" steps: - name: Check out repository @@ -38,10 +41,7 @@ jobs: key: ${{ runner.os }}-m2-v1-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2-v1- - - name: Resolve Maven dependencies - run: mvn dependency:resolve -q - - - name: Setup tools + - name: Setup tools and generate SBOM run: bash ci/setup-tools.sh --install-tool trivy,osv-scanner --sbom-ecosystem maven - name: Run SCA tools @@ -50,7 +50,7 @@ jobs: - name: Upload Trivy SARIF to GitHub Security tab id: upload_trivy if: always() - uses: github/codeql-action/upload-sarif@c35d1b164463ee62a100735382aaaa525c5d3496 #v2.25.6 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: sarif_file: ${{ env.TRIVY_SARIF_OUTPUT }} category: trivy-app @@ -58,7 +58,7 @@ jobs: - name: Upload OSV Scanner SARIF to GitHub Security tab id: upload_osv if: always() - uses: github/codeql-action/upload-sarif@c35d1b164463ee62a100735382aaaa525c5d3496 #v2.25.6 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: sarif_file: ${{ env.OSV_SARIF_OUTPUT }} category: osv-scanner-app diff --git a/ci/container_scan.py b/ci/container_scan.py index e909dc013..d0cbf8b13 100644 --- a/ci/container_scan.py +++ b/ci/container_scan.py @@ -4,7 +4,7 @@ import logging import json import argparse -from parse_sarif import evaluate +from parse_sarif import evaluate, GATE_FAIL_THRESHOLD, GATE_WARN_THRESHOLD GREEN = '\033[92m' @@ -92,12 +92,12 @@ def handle_sca(): eval_result = evaluate(path) if eval_result.gate_failed: - tool_status[name] = "FAILED" # this tool found CVSS >= 8.0 + tool_status[name] = "FAILED" gate_failed = True elif eval_result.gate_warn: - tool_status[name] = "WARNING" # this tool found 5.0 <= CVSS < 8.0 + tool_status[name] = "WARNING" else: - tool_status[name] = "PASSED" # this tool found nothing >= 5.0 + tool_status[name] = "PASSED" # Print summary of results logger.info(f"\n{BOLD}========== SCA PIPELINE SUMMARY =========={RESET}") @@ -105,12 +105,11 @@ def handle_sca(): if status == "PASSED": logger.info(f"[{name}]: {GREEN}PASSED{RESET}") elif status == "WARNING": - logger.warning(f"[{name}]: {YELLOW}WARNING (findings between 5.0 and 8.0){RESET}") + logger.warning(f"[{name}]: {YELLOW}WARNING (findings between {GATE_WARN_THRESHOLD} and {GATE_FAIL_THRESHOLD}){RESET}") elif status == "ERROR": logger.error(f"[{name}]: {RED}ERROR (tool did not run correctly){RESET}") else: - logger.error(f"[{name}]: {RED}FAILED (CVSS >= 8.0 found){RESET}") - logger.info(f"{BOLD}=========================================={RESET}\n") + logger.error(f"[{name}]: {RED}FAILED (CVSS >= {GATE_FAIL_THRESHOLD} found){RESET}") # Exit with non-zero code if any tool failed the gate if gate_failed: diff --git a/ci/parse_sarif.py b/ci/parse_sarif.py index 5d35c9707..793a2e6ed 100644 --- a/ci/parse_sarif.py +++ b/ci/parse_sarif.py @@ -1,6 +1,10 @@ import json +import os from dataclasses import dataclass +GATE_FAIL_THRESHOLD = float(os.getenv("GATE_FAIL_THRESHOLD", "8.0")) +GATE_WARN_THRESHOLD = float(os.getenv("GATE_WARN_THRESHOLD", "5.0")) + @dataclass class EvaluationResult: gate_failed: bool @@ -34,6 +38,6 @@ def evaluate(sarif_paths): max_score = max(max_score, float(score)) return EvaluationResult( - gate_failed=max_score >= 8, - gate_warn=5 <= max_score < 8, + gate_failed=max_score >= GATE_FAIL_THRESHOLD, + gate_warn=GATE_WARN_THRESHOLD <= max_score < GATE_FAIL_THRESHOLD, ) diff --git a/ci/sca_scan.py b/ci/sca_scan.py index b3297d949..2c651ec74 100644 --- a/ci/sca_scan.py +++ b/ci/sca_scan.py @@ -3,7 +3,7 @@ import sys import logging import json -from parse_sarif import evaluate +from parse_sarif import evaluate, GATE_FAIL_THRESHOLD, GATE_WARN_THRESHOLD GREEN = '\033[92m' RED = '\033[91m' @@ -114,12 +114,11 @@ def main(): if status == "PASSED": logger.info(f"[{name}]: {GREEN}PASSED{RESET}") elif status == "WARNING": - logger.warning(f"[{name}]: {YELLOW}WARNING (findings between 5.0 and 8.0){RESET}") + logger.warning(f"[{name}]: {YELLOW}WARNING (findings between {GATE_WARN_THRESHOLD} and {GATE_FAIL_THRESHOLD}){RESET}") elif status == "ERROR": logger.error(f"[{name}]: {RED}ERROR (tool did not run correctly){RESET}") else: - logger.error(f"[{name}]: {RED}FAILED (CVSS >= 8.0 found){RESET}") - logger.info(f"{BOLD}=========================================={RESET}\n") + logger.error(f"[{name}]: {RED}FAILED (CVSS >= {GATE_FAIL_THRESHOLD} found){RESET}") # Exit with non-zero code if any tool failed the gate if gate_failed: diff --git a/ci/setup-tools.sh b/ci/setup-tools.sh index 510453ee5..e65fcf000 100644 --- a/ci/setup-tools.sh +++ b/ci/setup-tools.sh @@ -149,10 +149,12 @@ fi case "$SBOM_ECOSYSTEM" in maven) echo "Generating SBOM for Maven project" - mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom -q + mvn -B -ntp dependency:resolve -q + mvn -B -ntp org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom -q ;; npm) echo "Generating SBOM for NPM project" + npm ci npx --yes "@cyclonedx/cyclonedx-npm@${CYCLONEDX_NPM_VERSION}" --output-file target/bom.json ;; none) From 6ebbb54f87874dd76ffc528685f50cda7ef392c6 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Tue, 1 Sep 2026 13:15:17 +0100 Subject: [PATCH 10/13] chore(renovate): auto-bump pre-commit hooks and semgrep-rules ref - enable the pre-commit manager and switch hook revs to the - add a git-refs custom manager to track semgrep-rules develop head branch - add git-refs to the minimumReleaseAge cooldown list --- .github/workflows/sast.yml | 2 +- .pre-commit-config.yaml | 4 ++-- ci/sast_scan.py | 2 +- ci/setup-tools.sh | 2 +- renovate.json | 17 +++++++++++++++-- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 68553e30e..40940c4a0 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -16,7 +16,7 @@ jobs: env: SEMGREP_CONFIG_RULESETS: >- semgrep-rules/generic semgrep-rules/problem-based-packs semgrep-rules/bash semgrep-rules/java auto - semgrep-rules/yaml semgrep-rules/package_managers p/default p/gitleaks + semgrep-rules/yaml semgrep-rules/package_managers p/default OPENGREP_EXCLUDE: >- *.sarif ci/ Dockerfile* .pre-commit-config.yaml docs/** README.md AGENTS.md OPENGREP_SARIF_OUTPUT: sast-semgrep-app.sarif diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3fd08481c..c2a0f044d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -19,6 +19,6 @@ repos: - id: mixed-line-ending - repo: https://github.com/gitleaks/gitleaks - rev: v8.30.0 + rev: 83d9cd684c87d95d656c1458ef04895a7f1cbd8e # frozen: v8.30.1 hooks: - id: gitleaks diff --git a/ci/sast_scan.py b/ci/sast_scan.py index f127ae0db..98e9d3586 100644 --- a/ci/sast_scan.py +++ b/ci/sast_scan.py @@ -19,7 +19,7 @@ SEMGREP_CONFIG_RULESETS = os.getenv( "SEMGREP_CONFIG_RULESETS", " semgrep-rules/generic semgrep-rules/problem-based-packs semgrep-rules/bash " - " semgrep-rules/java auto semgrep-rules/yaml semgrep-rules/package_managers p/default p/gitleaks " + " semgrep-rules/java auto semgrep-rules/yaml semgrep-rules/package_managers p/default" ).split() OPENGREP_EXCLUDE = os.getenv( "OPENGREP_EXCLUDE", diff --git a/ci/setup-tools.sh b/ci/setup-tools.sh index e65fcf000..bc3222978 100644 --- a/ci/setup-tools.sh +++ b/ci/setup-tools.sh @@ -22,7 +22,7 @@ OSV_SCANNER_SHA256="${OSV_SCANNER_SHA256:-15314940c10d26af9c6649f150b8a47c1262e8 OPENGREP_VERSION="${OPENGREP_VERSION:-v1.25.0}" OPENGREP_SHA256="${OPENGREP_SHA256:-9ac4aebb47ba3f7b0d8fc641ac8749cb6c2f253f616131a67d9631e00d4bea33}" -# renovate: datasource=github-tags depName=semgrep/semgrep-rules +# renovate: datasource=git-refs depName=https://github.com/semgrep/semgrep-rules SEMGREP_RULES_REF="${SEMGREP_RULES_REF:-40b8c63f75dc7c22c8a77482d73bfb864b146f7e}" SEMGREP_RULES_DIR="semgrep-rules" diff --git a/renovate.json b/renovate.json index 6a7b3e477..1af49b6fd 100644 --- a/renovate.json +++ b/renovate.json @@ -31,10 +31,22 @@ "matchStrings": [ "# renovate: datasource=(?[a-z-]+) depName=(?[^\\s]+)\\s*\\nENV DOCKERIZE_VERSION=(?v[0-9][0-9.]*)" ] + }, + { + "currentValueTemplate": "develop", + "customType": "regex", + "description": "Track a git branch head pinned as a commit SHA in CI setup scripts", + "managerFilePatterns": [ + "/(^|/)setup-tools\\.sh$/" + ], + "matchStrings": [ + "# renovate: datasource=(?git-refs) depName=(?[^\\s]+)\\n[A-Z_]+_REF=\"\\$\\{[A-Z_]+_REF:-(?[a-f0-9]{40})\\}\"" + ] } ], "enabledManagers": [ - "custom.regex" + "custom.regex", + "pre-commit" ], "extends": [ "config:recommended" @@ -60,7 +72,8 @@ "github-tags", "github-releases", "npm", - "python-version" + "python-version", + "git-refs" ], "minimumReleaseAge": "7 days" } From d01c01b79049d54ea553f257c575dbe3a87e2a52 Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Wed, 9 Sep 2026 14:28:37 +0100 Subject: [PATCH 11/13] fix(ci): encrypt SARIF artifacts --- .github/workflows/container-scan.yml | 77 +++++++++++++--------------- .github/workflows/sast.yml | 36 ++++++++++--- .github/workflows/sca.yml | 49 +++++++++++------- pom.xml | 2 +- 4 files changed, 98 insertions(+), 66 deletions(-) diff --git a/.github/workflows/container-scan.yml b/.github/workflows/container-scan.yml index 9f9560872..0135baaa2 100644 --- a/.github/workflows/container-scan.yml +++ b/.github/workflows/container-scan.yml @@ -23,7 +23,7 @@ jobs: TRIVY_SCA_SARIF_OUTPUT: sca-trivy-container.sarif OSV_SCA_SARIF_OUTPUT: sca-osv-container.sarif - # SAST /Linting + # SAST / Linting SEMGREP_CONFIG_RULESETS: >- semgrep-rules/dockerfile auto OPENGREP_SAST_SARIF_OUTPUT: sast-opengrep-dockerfile.sarif @@ -34,7 +34,7 @@ jobs: uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 #v6.2.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: # renovate: datasource=python-version depName=python python-version: '3.14.4' @@ -51,52 +51,49 @@ jobs: run: python ci/container_scan.py --scan-type sast - name: Run SCA scanning - if: always() + if: ${{ !cancelled() }} run: python ci/container_scan.py --scan-type sca --image ${{ env.IMAGE_NAME }} - - name: Upload Trivy SARIF to GitHub Security tab - id: upload_trivy - if: always() - uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 - with: - sarif_file: ${{ env.TRIVY_SCA_SARIF_OUTPUT }} - category: trivy-container-scanning - - - name: Upload OSV Scanner SARIF to GitHub Security tab - id: upload_osv - if: always() - uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 - with: - sarif_file: ${{ env.OSV_SCA_SARIF_OUTPUT }} - category: osv-scanner-container-scanning - - - name: Upload OpenGrep SARIF to GitHub Security tab - id: upload_opengrep - if: always() - uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 - with: - sarif_file: ${{ env.OPENGREP_SAST_SARIF_OUTPUT }} - category: opengrep-sast - - - name: Upload Hadolint SARIF to GitHub Security tab - id: upload_hadolint - if: always() - uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 - with: - sarif_file: ${{ env.HADOLINT_SAST_SARIF_OUTPUT }} - category: hadolint-sast - - name: Merge all SARIF reports - if: always() + if: ${{ !cancelled() }} run: | python ci/container_scan.py \ --merge-sarif "${{ env.TRIVY_SCA_SARIF_OUTPUT }}" "${{ env.OSV_SCA_SARIF_OUTPUT }}" "${{ env.OPENGREP_SAST_SARIF_OUTPUT }}" "${{ env.HADOLINT_SAST_SARIF_OUTPUT }}" \ --merge-output "${{ env.CONTAINER_SCAN_MERGED_SARIF_OUTPUT }}" - - name: Upload SARIF artifacts - if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 + - name: Upload merged SARIF to GitHub Security tab + if: ${{ !cancelled() && hashFiles(env.CONTAINER_SCAN_MERGED_SARIF_OUTPUT) != '' }} + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 + with: + sarif_file: ${{ env.CONTAINER_SCAN_MERGED_SARIF_OUTPUT }} + category: container-scan + + - name: Encrypt SARIF report + id: encrypt + if: ${{ !cancelled() && hashFiles(env.CONTAINER_SCAN_MERGED_SARIF_OUTPUT) != '' }} + env: + PW: ${{ secrets.ARTIFACT_PASSWORD }} + OUT: ${{ env.CONTAINER_SCAN_MERGED_SARIF_OUTPUT }}.gpg + run: | + if [ -z "$PW" ]; then + echo "::warning title=SARIF report not uploaded::ARTIFACT_PASSWORD is not available in this run (Dependabot, Renovate or fork PR). Skipping encryption and upload." + rm -f -- "$CONTAINER_SCAN_MERGED_SARIF_OUTPUT" + exit 0 + fi + printf '%s' "$PW" | gpg --symmetric --batch --yes --quiet \ + --pinentry-mode loopback --passphrase-fd 0 \ + --no-symkey-cache \ + --cipher-algo AES256 \ + --s2k-mode 3 --s2k-digest-algo SHA512 --s2k-count 65011712 \ + --output "$OUT" -- "$CONTAINER_SCAN_MERGED_SARIF_OUTPUT" + rm -f -- "$CONTAINER_SCAN_MERGED_SARIF_OUTPUT" + echo "encrypted=$OUT" >> "$GITHUB_OUTPUT" + + - name: Upload encrypted SARIF artifact + if: ${{ !cancelled() && steps.encrypt.outputs.encrypted != '' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: container-scan-sarif-report - path: ${{ env.CONTAINER_SCAN_MERGED_SARIF_OUTPUT }} + path: ${{ steps.encrypt.outputs.encrypted }} retention-days: 30 + if-no-files-found: error diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 40940c4a0..14ec2c11d 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 #v6.2.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: # renovate: datasource=python-version depName=python python-version: '3.14.4' @@ -37,17 +37,39 @@ jobs: - name: Run SAST scanning run: python ci/sast_scan.py - - name: Upload Semgrep SARIF to GitHub Security tab - id: upload_semgrep - if: always() + - name: Upload SARIF to GitHub Security tab + if: ${{ !cancelled() && hashFiles(env.OPENGREP_SARIF_OUTPUT) != '' }} uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: sarif_file: ${{ env.OPENGREP_SARIF_OUTPUT }} category: semgrep-app - - name: Upload SARIF artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 + - name: Encrypt SARIF report + id: encrypt + if: ${{ !cancelled() && hashFiles(env.OPENGREP_SARIF_OUTPUT) != '' }} + env: + PW: ${{ secrets.ARTIFACT_PASSWORD }} + OUT: ${{ env.OPENGREP_SARIF_OUTPUT }}.gpg + run: | + if [ -z "$PW" ]; then + echo "::warning title=SARIF report not uploaded::ARTIFACT_PASSWORD is not available in this run (Dependabot, Renovate or fork PR). Skipping encryption and upload." + rm -f -- "$OPENGREP_SARIF_OUTPUT" + exit 0 + fi + printf '%s' "$PW" | gpg --symmetric --batch --yes --quiet \ + --pinentry-mode loopback --passphrase-fd 0 \ + --no-symkey-cache \ + --cipher-algo AES256 \ + --s2k-mode 3 --s2k-digest-algo SHA512 --s2k-count 65011712 \ + --output "$OUT" -- "$OPENGREP_SARIF_OUTPUT" + rm -f -- "$OPENGREP_SARIF_OUTPUT" + echo "encrypted=$OUT" >> "$GITHUB_OUTPUT" + + - name: Upload encrypted SARIF artifact + if: ${{ !cancelled() && steps.encrypt.outputs.encrypted != '' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: sast-scan-sarif-report - path: ${{ env.OPENGREP_SARIF_OUTPUT }} + path: ${{ steps.encrypt.outputs.encrypted }} retention-days: 30 + if-no-files-found: error diff --git a/.github/workflows/sca.yml b/.github/workflows/sca.yml index c10ec33c5..a53c4f33b 100644 --- a/.github/workflows/sca.yml +++ b/.github/workflows/sca.yml @@ -29,13 +29,13 @@ jobs: uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 #v6.2.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: # renovate: datasource=python-version depName=python python-version: '3.14.4' - name: Cache Maven packages - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ~/.m2/repository # /.m2 only is too broad and can cause cache corruption issues key: ${{ runner.os }}-m2-v1-${{ hashFiles('**/pom.xml') }} @@ -47,26 +47,39 @@ jobs: - name: Run SCA tools run: python ci/sca_scan.py - - name: Upload Trivy SARIF to GitHub Security tab - id: upload_trivy - if: always() + - name: Upload merged SARIF to GitHub Security tab + if: ${{ !cancelled() && hashFiles(env.SCA_MERGED_SARIF_OUTPUT) != '' }} uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 with: - sarif_file: ${{ env.TRIVY_SARIF_OUTPUT }} - category: trivy-app + sarif_file: ${{ env.SCA_MERGED_SARIF_OUTPUT }} + category: sca-app - - name: Upload OSV Scanner SARIF to GitHub Security tab - id: upload_osv - if: always() - uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.2 - with: - sarif_file: ${{ env.OSV_SARIF_OUTPUT }} - category: osv-scanner-app + - name: Encrypt SARIF report + id: encrypt + if: ${{ !cancelled() && hashFiles(env.SCA_MERGED_SARIF_OUTPUT) != '' }} + env: + PW: ${{ secrets.ARTIFACT_PASSWORD }} + OUT: ${{ env.SCA_MERGED_SARIF_OUTPUT }}.gpg + run: | + if [ -z "$PW" ]; then + echo "::warning title=SARIF report not uploaded::ARTIFACT_PASSWORD is not available in this run (Dependabot, Renovate or fork PR). Skipping encryption and upload." + rm -f -- "$SCA_MERGED_SARIF_OUTPUT" + exit 0 + fi + printf '%s' "$PW" | gpg --symmetric --batch --yes --quiet \ + --pinentry-mode loopback --passphrase-fd 0 \ + --no-symkey-cache \ + --cipher-algo AES256 \ + --s2k-mode 3 --s2k-digest-algo SHA512 --s2k-count 65011712 \ + --output "$OUT" -- "$SCA_MERGED_SARIF_OUTPUT" + rm -f -- "$SCA_MERGED_SARIF_OUTPUT" + echo "encrypted=$OUT" >> "$GITHUB_OUTPUT" - - name: Upload SARIF artifacts - if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 + - name: Upload encrypted SARIF artifact + if: ${{ !cancelled() && steps.encrypt.outputs.encrypted != '' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: sca-scan-sarif-report - path: ${{ env.SCA_MERGED_SARIF_OUTPUT }} + path: ${{ steps.encrypt.outputs.encrypted }} retention-days: 30 + if-no-files-found: error diff --git a/pom.xml b/pom.xml index 38c9bf80c..03df7912e 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ 2.14.0 3.0.3 1.18.46 - 11.0.22 + 11.0.25 2.6 10.9.1 2.21.5 From 0c099422722461c4ed65c427a2752717be59cc7c Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Tue, 29 Sep 2026 20:53:01 +0000 Subject: [PATCH 12/13] fix: merge conflict in pre-commit hook configuration From 646a279da6c98488576c4c0954eb30c58c5cb6dc Mon Sep 17 00:00:00 2001 From: moghit-eou Date: Tue, 29 Sep 2026 21:43:14 +0000 Subject: [PATCH 13/13] chore(ci): align action pins with master --- .github/workflows/container-scan.yml | 6 +++--- .github/workflows/sast.yml | 6 +++--- .github/workflows/sca.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/container-scan.yml b/.github/workflows/container-scan.yml index 0135baaa2..c5c4cc2d4 100644 --- a/.github/workflows/container-scan.yml +++ b/.github/workflows/container-scan.yml @@ -31,13 +31,13 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 #v7.0.0 with: # renovate: datasource=python-version depName=python - python-version: '3.14.4' + python-version: '3.14.7' - name: Build Docker image run: docker build -t ${{ env.IMAGE_NAME }} . diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 14ec2c11d..5390f608c 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -23,13 +23,13 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 #v7.0.0 with: # renovate: datasource=python-version depName=python - python-version: '3.14.4' + python-version: '3.14.7' - name: Setup tools run: bash ci/setup-tools.sh --install-tool opengrep,semgrep-rules diff --git a/.github/workflows/sca.yml b/.github/workflows/sca.yml index a53c4f33b..4ef4cc0f5 100644 --- a/.github/workflows/sca.yml +++ b/.github/workflows/sca.yml @@ -26,13 +26,13 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 #v7.0.0 with: # renovate: datasource=python-version depName=python - python-version: '3.14.4' + python-version: '3.14.7' - name: Cache Maven packages uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0