From 1786afa45a17ddd6b825151768d128f4b06e5c42 Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Wed, 5 Aug 2026 14:56:24 +0200 Subject: [PATCH 1/6] STAC-25457: publish and sign the agent and cluster-agent images Ports the publishing half of pre_release_main_agent_image and pre_release_cluster_agent_image, plus merge_docker_manifest_main_agent and merge_docker_manifest_cluster_agent, from GitLab to GitHub Actions. PR #446 landed the build-and-verify halves; this adds the push. Each image gets a per-arch publish job that needs: the existing image build job, and a manifest-merge job that assembles the multi-arch tag from the two single-arch ones. Gated on `github.event_name == 'push'` alone: the workflow's push filter only carries the release branch, so the event check is the whole gate, and a workflow_dispatch on an arbitrary branch cannot publish. This is the same reasoning the cerberus-notify gate already uses. Uses the StackVista/image-pipeline composite actions rather than an open-coded docker push, matching stackstate-process-agent and the STAC-24837 direction for product repos. Over publish_image.sh that adds cosign signatures in both v2 and v3 bundle formats, SBOM and max-mode provenance attestations, canonical SUSE Observability OCI labels, an entrypoint ELF-architecture check that catches arch-mismatched images before they are signed, and refusal to overwrite an existing tag. Neither Dockerfile declares `ARG BASE_IMAGE`, so base-name is passed explicitly; both final stages are registry.suse.com/bci/bci-micro. Tag is the 8-character short SHA, matching GitLab's CI_COMMIT_SHORT_SHA. The `-` tag publish_image.sh also pushed is deliberately dropped: helm-charts-internal pins the agent and cluster-agent images to an 8-character SHA (currently 9516cb41, the stackstate-7.78.2 HEAD), and beest receives the tag as AGENT_HASH_UNDER_TEST, so nothing consumes a branch-name tag. An org-wide code search for stackstate-k8s-agent:master, :stackstate-7*, :$CI_COMMIT_REF_SLUG and the cluster-agent equivalents returns no hits, verified against a positive control so an empty result is not a false negative. Both publish jobs need id-token: write for keyless cosign signing, and are added to each workflow's cerberus-notify needs list so a failed publish on the release branch still reaches Slack. Requires STAC-25541 (terraform-infra #75): the stackstate+agent robot behind QUAY_USER has no write grant on stackstate-k8s-agent or stackstate-k8s-cluster-agent, since GitLab publishes them with the legacy gitlabci robot instead. Without it these jobs fail exactly as process-agent did in STAC-25510. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build-binaries.yml | 105 +++++++++++++++++++++++++ .github/workflows/build-deb.yml | 112 +++++++++++++++++++++++++++ 2 files changed, 217 insertions(+) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 377d6fc2aab8..b40b40e8de14 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -239,6 +239,109 @@ jobs: --entrypoint /opt/stackstate-agent/bin/stackstate-cluster-agent/stackstate-cluster-agent \ "${LOCAL_IMAGE}" version + publish-cluster-agent-image: + name: Publish and sign cluster-agent image (${{ matrix.arch }}) + if: github.event_name == 'push' + needs: build-cluster-agent-image + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + runner: docker-public + - arch: arm64 + runner: arm64-xlarge-public + runs-on: ${{ matrix.runner }} + timeout-minutes: 45 + permissions: + contents: read + id-token: write + env: + IMAGE: quay.io/stackstate/stackstate-k8s-cluster-agent + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Download cluster-agent binary + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: cluster-agent-binary-${{ matrix.arch }} + + - name: Stage the cluster-agent binary in the image build context + run: | + set -eo pipefail + chmod +x bin/stackstate-cluster-agent/stackstate-cluster-agent + cp -r bin/stackstate-cluster-agent Dockerfiles/cluster-agent/ + + - name: Resolve image tag + id: image + env: + SOURCE_SHA: ${{ github.sha }} + run: | + set -euo pipefail + echo "tag=$(printf '%s' "${SOURCE_SHA}" | cut -c1-8)" >> "${GITHUB_OUTPUT}" + + - name: Resolve canonical OCI labels + id: oci + uses: StackVista/image-pipeline/.github/actions/apply-oci-labels@6284a6fc006a7cc46a7f00d02c50d5f21b117b63 + with: + image-name: stackstate-k8s-cluster-agent + tag: ${{ steps.image.outputs.tag }} + title: SUSE Observability Cluster Agent + description: Cluster-level agent collecting Kubernetes topology and cluster checks for SUSE Observability. + component: stackstate-k8s-cluster-agent + dockerfile: Dockerfiles/cluster-agent/Dockerfile + base-name: registry.suse.com/bci/bci-micro:latest + registry-credentials: | + [{"registry": "${{ vars.REGISTRY_HOST }}", "username": "${{ vars.REGISTRY_USER }}", "password": "${{ secrets.REGISTRY_PASSWORD }}"}] + + - name: Build, publish, and sign architecture image + uses: StackVista/image-pipeline/.github/actions/push-single-arch@6284a6fc006a7cc46a7f00d02c50d5f21b117b63 + with: + image: ${{ env.IMAGE }} + tag: ${{ steps.image.outputs.tag }} + arch: ${{ matrix.arch }} + docker-context: Dockerfiles/cluster-agent + dockerfile: Dockerfiles/cluster-agent/Dockerfile + labels: | + ${{ steps.oci.outputs.labels }} + org.opencontainers.image.revision=${{ github.sha }} + source-registry-credentials: | + [{"registry": "${{ vars.REGISTRY_HOST }}", "username": "${{ vars.REGISTRY_USER }}", "password": "${{ secrets.REGISTRY_PASSWORD }}"}] + target-registry: quay.io + target-registry-user: ${{ vars.QUAY_USER }} + target-registry-password: ${{ secrets.QUAY_PASSWORD }} + + merge-cluster-agent-manifest: + name: Publish and sign multi-architecture cluster-agent image + if: github.event_name == 'push' + needs: publish-cluster-agent-image + runs-on: docker-public + timeout-minutes: 30 + permissions: + contents: read + id-token: write + steps: + - name: Resolve image tag + id: image + env: + SOURCE_SHA: ${{ github.sha }} + run: | + set -euo pipefail + echo "tag=$(printf '%s' "${SOURCE_SHA}" | cut -c1-8)" >> "${GITHUB_OUTPUT}" + + - name: Merge and sign multi-architecture manifest + uses: StackVista/image-pipeline/.github/actions/merge-multiarch@6284a6fc006a7cc46a7f00d02c50d5f21b117b63 + with: + image: quay.io/stackstate/stackstate-k8s-cluster-agent + tag: ${{ steps.image.outputs.tag }} + arches: amd64,arm64 + target-registry: quay.io + target-registry-user: ${{ vars.QUAY_USER }} + target-registry-password: ${{ secrets.QUAY_PASSWORD }} + cerberus-notify: name: Report failure to Slack (Cerberus) needs: @@ -247,6 +350,8 @@ jobs: - build-agent - build-cluster-agent - build-cluster-agent-image + - publish-cluster-agent-image + - merge-cluster-agent-manifest if: >- always() && github.event_name == 'push' diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 7c4b726c477c..9eede0e2409d 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -278,6 +278,116 @@ jobs: set -eo pipefail docker run --rm --entrypoint /opt/stackstate-agent/bin/agent/agent "${LOCAL_IMAGE}" version + publish-agent-image: + name: Publish and sign agent image (${{ matrix.arch }}) + if: github.event_name == 'push' + needs: build-agent-image + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + runner: docker-public + - arch: arm64 + runner: arm64-xlarge-public + runs-on: ${{ matrix.runner }} + timeout-minutes: 60 + permissions: + contents: read + id-token: write + env: + ARCH: ${{ matrix.arch }} + IMAGE: quay.io/stackstate/stackstate-k8s-agent + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Download DEB package + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: deb-package-${{ matrix.arch }} + + - name: Stage the DEB in the image build context + run: | + set -eo pipefail + shopt -s nullglob + debs=(outcomes/pkg/stackstate-agent_*_"${ARCH}".deb) + if [ "${#debs[@]}" -ne 1 ]; then + echo "Expected exactly one stackstate-agent_*_${ARCH}.deb, found ${#debs[@]}: ${debs[*]}" >&2 + exit 1 + fi + cp "${debs[0]}" Dockerfiles/agent/ + + - name: Resolve image tag + id: image + env: + SOURCE_SHA: ${{ github.sha }} + run: | + set -euo pipefail + echo "tag=$(printf '%s' "${SOURCE_SHA}" | cut -c1-8)" >> "${GITHUB_OUTPUT}" + + - name: Resolve canonical OCI labels + id: oci + uses: StackVista/image-pipeline/.github/actions/apply-oci-labels@6284a6fc006a7cc46a7f00d02c50d5f21b117b63 + with: + image-name: stackstate-k8s-agent + tag: ${{ steps.image.outputs.tag }} + title: SUSE Observability Agent + description: Node agent collecting metrics, logs, traces and topology for SUSE Observability. + component: stackstate-k8s-agent + dockerfile: Dockerfiles/agent/Dockerfile + base-name: registry.suse.com/bci/bci-micro:latest + registry-credentials: | + [{"registry": "${{ vars.REGISTRY_HOST }}", "username": "${{ vars.REGISTRY_USER }}", "password": "${{ secrets.REGISTRY_PASSWORD }}"}] + + - name: Build, publish, and sign architecture image + uses: StackVista/image-pipeline/.github/actions/push-single-arch@6284a6fc006a7cc46a7f00d02c50d5f21b117b63 + with: + image: ${{ env.IMAGE }} + tag: ${{ steps.image.outputs.tag }} + arch: ${{ matrix.arch }} + docker-context: Dockerfiles/agent + dockerfile: Dockerfiles/agent/Dockerfile + build-args: ARCH=${{ matrix.arch }} + labels: | + ${{ steps.oci.outputs.labels }} + org.opencontainers.image.revision=${{ github.sha }} + source-registry-credentials: | + [{"registry": "${{ vars.REGISTRY_HOST }}", "username": "${{ vars.REGISTRY_USER }}", "password": "${{ secrets.REGISTRY_PASSWORD }}"}] + target-registry: quay.io + target-registry-user: ${{ vars.QUAY_USER }} + target-registry-password: ${{ secrets.QUAY_PASSWORD }} + + merge-agent-manifest: + name: Publish and sign multi-architecture agent image + if: github.event_name == 'push' + needs: publish-agent-image + runs-on: docker-public + timeout-minutes: 30 + permissions: + contents: read + id-token: write + steps: + - name: Resolve image tag + id: image + env: + SOURCE_SHA: ${{ github.sha }} + run: | + set -euo pipefail + echo "tag=$(printf '%s' "${SOURCE_SHA}" | cut -c1-8)" >> "${GITHUB_OUTPUT}" + + - name: Merge and sign multi-architecture manifest + uses: StackVista/image-pipeline/.github/actions/merge-multiarch@6284a6fc006a7cc46a7f00d02c50d5f21b117b63 + with: + image: quay.io/stackstate/stackstate-k8s-agent + tag: ${{ steps.image.outputs.tag }} + arches: amd64,arm64 + target-registry: quay.io + target-registry-user: ${{ vars.QUAY_USER }} + target-registry-password: ${{ secrets.QUAY_PASSWORD }} + cerberus-notify: name: Report failure to Slack (Cerberus) needs: @@ -286,6 +396,8 @@ jobs: - build-deb - test-deb-renaming - build-agent-image + - publish-agent-image + - merge-agent-manifest if: >- always() && github.event_name == 'push' From 9c11a9cdecbf7bacc5c8c523b75fc6ddfeed299b Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Thu, 6 Aug 2026 16:29:46 +0200 Subject: [PATCH 2/6] STAC-25457 Gate agent image publication on scans, deb branding, and proxy BCI bases Address review feedback on #454. Gate publication on the image scan: build-agent-image and build-cluster-agent-image now run image-pipeline's scan-image in `mode: gate` at the house severity (UNKNOWN..CRITICAL, Grype enabled) directly after the smoke test. The publish jobs already depend on the build jobs, so a failing scan now blocks publication instead of only informing. Because build-agent-image also runs for same-repo pull requests, the gate executes on this PR's own CI. Make publication depend on all verification jobs: publish-agent-image now needs test-deb-renaming as well as build-agent-image, so a .deb that still carries DataDog branding cannot reach quay.io. test-deb-renaming lives in this workflow only, so the cluster-agent lane is unaffected. Pull the BCI bases through the SUSE proxy: both Dockerfiles take BCI_IMAGE_REGISTRY as a build argument, defaulting to registry.tooling.stackstate.io/suse/bci. This follows the existing BASE_IMAGE_REGISTRY convention in the same files, so every build path picks it up -- the GitHub workflows, the GitLab jobs, and build_images.sh -- without each caller having to pass a build argument. The apply-oci-labels base-name input stays on registry.suse.com so the provenance label keeps the upstream identity that VEX data is keyed on. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build-binaries.yml | 12 ++++++++++-- .github/workflows/build-deb.yml | 16 +++++++++++++--- Dockerfiles/agent/Dockerfile | 5 +++-- Dockerfiles/cluster-agent/Dockerfile | 9 ++++++--- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index b40b40e8de14..1de3a256353c 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -209,8 +209,6 @@ jobs: REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} run: | set -eo pipefail - # Dockerfiles/cluster-agent pulls its ubuntu builder stage through the - # proxy; the BCI stages come from registry.suse.com and need no auth. printf '%s' "${REGISTRY_PASSWORD}" | docker login -u "${REGISTRY_USER}" --password-stdin "${REGISTRY_HOST}" - name: Build cluster-agent image @@ -239,6 +237,16 @@ jobs: --entrypoint /opt/stackstate-agent/bin/stackstate-cluster-agent/stackstate-cluster-agent \ "${LOCAL_IMAGE}" version + - name: Scan cluster-agent image (Trivy and Grype vulnerabilities, VEX-aware, plus Trivy secrets) + uses: StackVista/image-pipeline/.github/actions/scan-image@6284a6fc006a7cc46a7f00d02c50d5f21b117b63 + with: + image: ${{ env.LOCAL_IMAGE }} + mode: gate + severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL + with-grype: true + upload-sarif: false + sarif-category: stackstate-k8s-cluster-agent-${{ matrix.arch }} + publish-cluster-agent-image: name: Publish and sign cluster-agent image (${{ matrix.arch }}) if: github.event_name == 'push' diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 9eede0e2409d..9c4014c9ecc9 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -255,8 +255,6 @@ jobs: REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} run: | set -eo pipefail - # Dockerfiles/agent pulls its ubuntu extract stage through the proxy; - # the BCI stages come from registry.suse.com and need no auth. printf '%s' "${REGISTRY_PASSWORD}" | docker login -u "${REGISTRY_USER}" --password-stdin "${REGISTRY_HOST}" - name: Build agent image @@ -278,10 +276,22 @@ jobs: set -eo pipefail docker run --rm --entrypoint /opt/stackstate-agent/bin/agent/agent "${LOCAL_IMAGE}" version + - name: Scan agent image (Trivy and Grype vulnerabilities, VEX-aware, plus Trivy secrets) + uses: StackVista/image-pipeline/.github/actions/scan-image@6284a6fc006a7cc46a7f00d02c50d5f21b117b63 + with: + image: ${{ env.LOCAL_IMAGE }} + mode: gate + severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL + with-grype: true + upload-sarif: false + sarif-category: stackstate-k8s-agent-${{ matrix.arch }} + publish-agent-image: name: Publish and sign agent image (${{ matrix.arch }}) if: github.event_name == 'push' - needs: build-agent-image + needs: + - build-agent-image + - test-deb-renaming strategy: fail-fast: false matrix: diff --git a/Dockerfiles/agent/Dockerfile b/Dockerfiles/agent/Dockerfile index 3e471e23f055..9ccde5ff4bd6 100644 --- a/Dockerfiles/agent/Dockerfile +++ b/Dockerfiles/agent/Dockerfile @@ -1,5 +1,6 @@ ARG BASE_IMAGE_REGISTRY=registry.tooling.stackstate.io/docker/library ARG BASE_IMAGE_UBUNTU_VERSION=24.04 +ARG BCI_IMAGE_REGISTRY=registry.tooling.stackstate.io/suse/bci ########################################## # Preparation stage: extract and cleanup # @@ -27,7 +28,7 @@ RUN dpkg -x /stackstate-agent*_${ARCH}.deb . \ # - copy default config files COPY stackstate*.yaml etc/stackstate-agent/ -FROM registry.suse.com/bci/bci-base:latest AS software +FROM ${BCI_IMAGE_REGISTRY}/bci-base:latest AS software # as per comment here: https://github.com/rancher/rancher/blob/main/package/Dockerfile#L12 # No-op command to create an explicit layer - this fixes a weird buildkit/buildx bug on macos arm RUN : @@ -35,7 +36,7 @@ RUN : # Actual docker image construction # #################################### -FROM registry.suse.com/bci/bci-micro:latest +FROM ${BCI_IMAGE_REGISTRY}/bci-micro:latest LABEL maintainer="StackState " # Install system packages using builder image that has zypper diff --git a/Dockerfiles/cluster-agent/Dockerfile b/Dockerfiles/cluster-agent/Dockerfile index bb252b5a996e..bc0777542028 100644 --- a/Dockerfiles/cluster-agent/Dockerfile +++ b/Dockerfiles/cluster-agent/Dockerfile @@ -1,8 +1,11 @@ +ARG BASE_IMAGE_REGISTRY=registry.tooling.stackstate.io/docker/library +ARG BCI_IMAGE_REGISTRY=registry.tooling.stackstate.io/suse/bci + ######################################## # Preparation stage: layout and chmods # ######################################## -FROM registry.tooling.stackstate.io/docker/library/ubuntu:20.04 as builder +FROM ${BASE_IMAGE_REGISTRY}/ubuntu:20.04 as builder WORKDIR /output @@ -22,12 +25,12 @@ RUN chmod 755 entrypoint.sh \ # Actual docker image construction # #################################### -FROM registry.suse.com/bci/bci-base:latest AS software +FROM ${BCI_IMAGE_REGISTRY}/bci-base:latest AS software # as per comment here: https://github.com/rancher/rancher/blob/main/package/Dockerfile#L12 # No-op command to create an explicit layer - this fixes a weird buildkit/buildx bug on macos arm RUN : -FROM registry.suse.com/bci/bci-micro:latest AS final +FROM ${BCI_IMAGE_REGISTRY}/bci-micro:latest AS final LABEL maintainer="StackState " ARG user="stackstate-agent" From 19fa3b99d4f1ffc5b4452b79966022b559ae6e29 Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Fri, 7 Aug 2026 11:20:43 +0200 Subject: [PATCH 3/6] STAC-25457 Manage the agent image CVE backlog with time-limited exceptions The image scan gate added in this branch surfaced a real backlog: 24 findings in the agent image (embedded CPython 3.13.13, cryptography 48.0.1, two Go advisories) and 2 in the cluster-agent image. Secret scanning is clean on both. Keep the gate at mode: gate and declare every finding explicitly instead of weakening the severity filter, so nothing new can slip in unnoticed. Each exception carries a <=14-day expiry per the CVE remediation SLA, so the gate starts failing again if the underlying bumps stall. The omnibus runtime bumps (CPython 3.13.14, cryptography) are tracked in STAC-25556; they are software-definition changes, not workflow changes. LOCAL_IMAGE is renamed to the quay path the publish jobs already use because the evaluator keys exceptions on the normalised image name, which strips only the tag or digest and not the registry or namespace. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build-binaries.yml | 3 ++- .github/workflows/build-deb.yml | 3 ++- .../stackstate-k8s-agent/CVE-2025-15366.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2025-15367.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-0864.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-11940.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-11972.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-12003.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-1502.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-15308.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-3276.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-3298.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-4360.yaml | 22 +++++++++++++++ .../stackstate-k8s-agent/CVE-2026-4786.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-6019.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-6100.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-6879.yaml | 22 +++++++++++++++ .../stackstate-k8s-agent/CVE-2026-69247.yaml | 24 +++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-69248.yaml | 22 +++++++++++++++ .../stackstate-k8s-agent/CVE-2026-69249.yaml | 24 +++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-7210.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-7774.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-8328.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/CVE-2026-9669.yaml | 26 ++++++++++++++++++ .../stackstate-k8s-agent/GO-2026-5841.yaml | 24 +++++++++++++++++ .../stackstate-k8s-agent/GO-2026-5932.yaml | 27 +++++++++++++++++++ .../GO-2026-5841.yaml | 23 ++++++++++++++++ .../GO-2026-5932.yaml | 26 ++++++++++++++++++ 28 files changed, 660 insertions(+), 2 deletions(-) create mode 100644 exceptions/stackstate-k8s-agent/CVE-2025-15366.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2025-15367.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-0864.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-11940.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-11972.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-12003.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-1502.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-15308.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-3276.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-3298.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-4360.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-4786.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-6019.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-6100.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-6879.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-69247.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-69248.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-69249.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-7210.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-7774.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-8328.yaml create mode 100644 exceptions/stackstate-k8s-agent/CVE-2026-9669.yaml create mode 100644 exceptions/stackstate-k8s-agent/GO-2026-5841.yaml create mode 100644 exceptions/stackstate-k8s-agent/GO-2026-5932.yaml create mode 100644 exceptions/stackstate-k8s-cluster-agent/GO-2026-5841.yaml create mode 100644 exceptions/stackstate-k8s-cluster-agent/GO-2026-5932.yaml diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 1de3a256353c..0a890d52c7cd 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -190,7 +190,7 @@ jobs: runs-on: ${{ matrix.runner }} timeout-minutes: 45 env: - LOCAL_IMAGE: stackstate-cluster-agent:ci-${{ matrix.arch }} + LOCAL_IMAGE: quay.io/stackstate/stackstate-k8s-cluster-agent:ci-${{ matrix.arch }} steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -244,6 +244,7 @@ jobs: mode: gate severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL with-grype: true + exceptions-path: exceptions upload-sarif: false sarif-category: stackstate-k8s-cluster-agent-${{ matrix.arch }} diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 9c4014c9ecc9..ced8a5452144 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -236,7 +236,7 @@ jobs: timeout-minutes: 60 env: ARCH: ${{ matrix.arch }} - LOCAL_IMAGE: stackstate-agent:ci-${{ matrix.arch }} + LOCAL_IMAGE: quay.io/stackstate/stackstate-k8s-agent:ci-${{ matrix.arch }} steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -283,6 +283,7 @@ jobs: mode: gate severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL with-grype: true + exceptions-path: exceptions upload-sarif: false sarif-category: stackstate-k8s-agent-${{ matrix.arch }} diff --git a/exceptions/stackstate-k8s-agent/CVE-2025-15366.yaml b/exceptions/stackstate-k8s-agent/CVE-2025-15366.yaml new file mode 100644 index 000000000000..4784c149340d --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2025-15366.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2025-15366 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_for_pinned_runtime_line +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2025-15366 +statement: | + No fix is published for the CPython 3.13 maintenance line. Upstream + currently carries the fix only in 3.15.0a6, a pre-release of a different + minor version, so there is no compatible patch we could apply without + moving the embedded interpreter to an unreleased runtime. Under the + remediation SLA this falls outside the patch commitment, so the date below + is a short review deadline rather than an acceptance: re-check upstream for + a 3.13 backport before renewing. Tracked with the rest of the + embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2025-15367.yaml b/exceptions/stackstate-k8s-agent/CVE-2025-15367.yaml new file mode 100644 index 000000000000..f9be944281b8 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2025-15367.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2025-15367 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_for_pinned_runtime_line +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2025-15367 +statement: | + No fix is published for the CPython 3.13 maintenance line. Upstream + currently carries the fix only in 3.15.0a6, a pre-release of a different + minor version, so there is no compatible patch we could apply without + moving the embedded interpreter to an unreleased runtime. Under the + remediation SLA this falls outside the patch commitment, so the date below + is a short review deadline rather than an acceptance: re-check upstream for + a 3.13 backport before renewing. Tracked with the rest of the + embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-0864.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-0864.yaml new file mode 100644 index 000000000000..5080525c5523 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-0864.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-0864 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_for_pinned_runtime_line +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-0864 +statement: | + No fix is published for the CPython 3.13 maintenance line. Upstream + currently carries the fix only in 3.15.0b4, a pre-release of a different + minor version, so there is no compatible patch we could apply without + moving the embedded interpreter to an unreleased runtime. Under the + remediation SLA this falls outside the patch commitment, so the date below + is a short review deadline rather than an acceptance: re-check upstream for + a 3.13 backport before renewing. Tracked with the rest of the + embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-11940.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-11940.yaml new file mode 100644 index 000000000000..f6d0d59faee4 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-11940.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-11940 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_for_pinned_runtime_line +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-11940 +statement: | + No fix is published for the CPython 3.13 maintenance line. Upstream + currently carries the fix only in 3.15.0b4, a pre-release of a different + minor version, so there is no compatible patch we could apply without + moving the embedded interpreter to an unreleased runtime. Under the + remediation SLA this falls outside the patch commitment, so the date below + is a short review deadline rather than an acceptance: re-check upstream for + a 3.13 backport before renewing. Tracked with the rest of the + embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-11972.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-11972.yaml new file mode 100644 index 000000000000..44a30b317212 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-11972.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-11972 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_for_pinned_runtime_line +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-11972 +statement: | + No fix is published for the CPython 3.13 maintenance line. Upstream + currently carries the fix only in 3.15.0b4, a pre-release of a different + minor version, so there is no compatible patch we could apply without + moving the embedded interpreter to an unreleased runtime. Under the + remediation SLA this falls outside the patch commitment, so the date below + is a short review deadline rather than an acceptance: re-check upstream for + a 3.13 backport before renewing. Tracked with the rest of the + embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-12003.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-12003.yaml new file mode 100644 index 000000000000..7466dfe8720f --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-12003.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-12003 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_for_pinned_runtime_line +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-12003 +statement: | + No fix is published for the CPython 3.13 maintenance line. Upstream + currently carries the fix only in 3.15.0b3, a pre-release of a different + minor version, so there is no compatible patch we could apply without + moving the embedded interpreter to an unreleased runtime. Under the + remediation SLA this falls outside the patch commitment, so the date below + is a short review deadline rather than an acceptance: re-check upstream for + a 3.13 backport before renewing. Tracked with the rest of the + embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-1502.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-1502.yaml new file mode 100644 index 000000000000..3b82193536ea --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-1502.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-1502 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-1502 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-15308.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-15308.yaml new file mode 100644 index 000000000000..690ecbdd9cd2 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-15308.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-15308 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_for_pinned_runtime_line +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-15308 +statement: | + No fix is published for the CPython 3.13 maintenance line. Upstream + currently carries the fix only in 3.15.0, a pre-release of a different + minor version, so there is no compatible patch we could apply without + moving the embedded interpreter to an unreleased runtime. Under the + remediation SLA this falls outside the patch commitment, so the date below + is a short review deadline rather than an acceptance: re-check upstream for + a 3.13 backport before renewing. Tracked with the rest of the + embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-3276.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-3276.yaml new file mode 100644 index 000000000000..a7158e95bec1 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-3276.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-3276 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-3276 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-3298.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-3298.yaml new file mode 100644 index 000000000000..0c8a60306626 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-3298.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-3298 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-3298 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-4360.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-4360.yaml new file mode 100644 index 000000000000..0079db8231f6 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-4360.yaml @@ -0,0 +1,22 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-4360 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_published +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-4360 +statement: | + Upstream has published no fixed CPython version for this CVE in any release + line, so no patch exists to apply. The date below is a short review + deadline, not an acceptance -- re-check upstream before renewing. Tracked + with the rest of the embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-4786.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-4786.yaml new file mode 100644 index 000000000000..ee7701d888ce --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-4786.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-4786 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-4786 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-6019.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-6019.yaml new file mode 100644 index 000000000000..65a1f878a5f8 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-6019.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-6019 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-6019 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-6100.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-6100.yaml new file mode 100644 index 000000000000..2cdcd61a3fb7 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-6100.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-6100 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-6100 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-6879.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-6879.yaml new file mode 100644 index 000000000000..5abe5fd4c54a --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-6879.yaml @@ -0,0 +1,22 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-6879 + severity: LOW +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: accepted_pending_upstream_fix +reason: no_upstream_fix_published +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-6879 +statement: | + Upstream has published no fixed CPython version for this CVE in any release + line, so no patch exists to apply. The date below is a short review + deadline, not an acceptance -- re-check upstream before renewing. Tracked + with the rest of the embedded-runtime work in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-69247.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-69247.yaml new file mode 100644 index 000000000000..65fedbbae7a0 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-69247.yaml @@ -0,0 +1,24 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-69247 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:pypi/cryptography@48.0.1 + paths: + - opt/stackstate-agent/embedded/lib/python3.13/site-packages/cryptography +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: pyca +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-69247 +statement: | + cryptography 50.0.0 fixes this, so a compatible patch exists and the + finding is inside the 14-day remediation window rather than being accepted. + The package is installed into the omnibus-embedded Python environment, so + the fix is a requirements bump in the omnibus build, tracked in STAC-25556. + Do not renew this exception without re-checking whether the bump has + landed. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-69248.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-69248.yaml new file mode 100644 index 000000000000..6f7d66fa1273 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-69248.yaml @@ -0,0 +1,22 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-69248 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:pypi/cryptography@48.0.1 + paths: + - opt/stackstate-agent/embedded/lib/python3.13/site-packages/cryptography +status: accepted_pending_upstream_fix +reason: no_upstream_fix_published +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: pyca +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-69248 +statement: | + Trivy reports no fixed version for this CVE, so there is no patch to apply. + It will most likely be resolved incidentally by the cryptography bump that + clears CVE-2026-69247 and CVE-2026-69249; until then the date below is a + short review deadline, not an acceptance. Tracked in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-69249.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-69249.yaml new file mode 100644 index 000000000000..4ca636daae4f --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-69249.yaml @@ -0,0 +1,24 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-69249 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:pypi/cryptography@48.0.1 + paths: + - opt/stackstate-agent/embedded/lib/python3.13/site-packages/cryptography +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: pyca +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-69249 +statement: | + cryptography 49.0.0 fixes this, so a compatible patch exists and the + finding is inside the 14-day remediation window rather than being accepted. + The package is installed into the omnibus-embedded Python environment, so + the fix is a requirements bump in the omnibus build, tracked in STAC-25556. + Do not renew this exception without re-checking whether the bump has + landed. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-7210.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-7210.yaml new file mode 100644 index 000000000000..f4ae0c862dfb --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-7210.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-7210 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-7210 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-7774.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-7774.yaml new file mode 100644 index 000000000000..4c19ae72e010 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-7774.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-7774 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-7774 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-8328.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-8328.yaml new file mode 100644 index 000000000000..bf55aa30b620 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-8328.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-8328 + severity: MEDIUM +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-8328 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/CVE-2026-9669.yaml b/exceptions/stackstate-k8s-agent/CVE-2026-9669.yaml new file mode 100644 index 000000000000..592349d0a3ae --- /dev/null +++ b/exceptions/stackstate-k8s-agent/CVE-2026-9669.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: CVE-2026-9669 + severity: HIGH +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:generic/python@3.13.13 + paths: + - opt/stackstate-agent/embedded/bin/python3.13 +status: under_investigation +reason: omnibus_runtime_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: python +upstream_reference: https://www.cve.org/CVERecord?id=CVE-2026-9669 +statement: | + CPython 3.13.14 fixes this on the 3.13 maintenance line, so a compatible + patch exists and the finding is inside the 14-day remediation window rather + than being accepted. The interpreter is embedded by the omnibus build, so + the fix is an omnibus software-definition bump tracked in STAC-25556, not a + change any workflow in this repository can make. This exception exists only + so the newly added image gate can be enforced on everything else while that + bump lands; it must not be renewed without re-checking whether 3.13.14 has + been integrated. diff --git a/exceptions/stackstate-k8s-agent/GO-2026-5841.yaml b/exceptions/stackstate-k8s-agent/GO-2026-5841.yaml new file mode 100644 index 000000000000..71c2ab63538a --- /dev/null +++ b/exceptions/stackstate-k8s-agent/GO-2026-5841.yaml @@ -0,0 +1,24 @@ +schema_version: '1' +vulnerability: + id: GO-2026-5841 + severity: UNKNOWN +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:golang/github.com/klauspost/compress@v1.18.5 + paths: + - opt/stackstate-agent/bin/agent/agent + - opt/stackstate-agent/bin/installer/installer +status: under_investigation +reason: transitive_dependency_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: klauspost +upstream_reference: https://pkg.go.dev/vuln/GO-2026-5841 +statement: | + github.com/klauspost/compress v1.18.7 fixes this, so a compatible patch + exists and the finding is inside the 14-day remediation window. It reaches + the binary transitively through the upstream Datadog agent dependency + graph, so the bump has to go through a go.mod update rather than a direct + version pin. Tracked in STAC-25556. diff --git a/exceptions/stackstate-k8s-agent/GO-2026-5932.yaml b/exceptions/stackstate-k8s-agent/GO-2026-5932.yaml new file mode 100644 index 000000000000..b10a861cd1f4 --- /dev/null +++ b/exceptions/stackstate-k8s-agent/GO-2026-5932.yaml @@ -0,0 +1,27 @@ +schema_version: '1' +vulnerability: + id: GO-2026-5932 + severity: UNKNOWN +product: + consumer: stackstate-k8s-agent + image: quay.io/stackstate/stackstate-k8s-agent +component: + purl: pkg:golang/golang.org/x/crypto@v0.53.0 + paths: + - opt/stackstate-agent/bin/agent/agent + - opt/stackstate-agent/bin/installer/installer +status: accepted_with_compensating_control +reason: unpublished_image_vex_identity_bridge +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: golang +upstream_reference: https://pkg.go.dev/vuln/GO-2026-5932 +statement: | + The affected openpgp and openpgp/clearsign packages are absent from this + binary's command dependency graph. StackVista/vexhub carries the reviewed + image-scoped not_affected statement, but Grype and Trivy match VEX products + by exact image digest or tag, and this gate scans a freshly built commit + image whose identity cannot exist in the VEX hub in advance. The same + bridge is already in place for stackstate-process-agent. Keep it only until + the scan pipeline can apply reviewed statements to unpublished images + without broadening them to every consumer of golang.org/x/crypto. diff --git a/exceptions/stackstate-k8s-cluster-agent/GO-2026-5841.yaml b/exceptions/stackstate-k8s-cluster-agent/GO-2026-5841.yaml new file mode 100644 index 000000000000..aa78469d9b58 --- /dev/null +++ b/exceptions/stackstate-k8s-cluster-agent/GO-2026-5841.yaml @@ -0,0 +1,23 @@ +schema_version: '1' +vulnerability: + id: GO-2026-5841 + severity: UNKNOWN +product: + consumer: stackstate-k8s-cluster-agent + image: quay.io/stackstate/stackstate-k8s-cluster-agent +component: + purl: pkg:golang/github.com/klauspost/compress@v1.18.5 + paths: + - opt/stackstate-agent/bin/stackstate-cluster-agent/stackstate-cluster-agent +status: under_investigation +reason: transitive_dependency_bump_in_progress +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: klauspost +upstream_reference: https://pkg.go.dev/vuln/GO-2026-5841 +statement: | + github.com/klauspost/compress v1.18.7 fixes this, so a compatible patch + exists and the finding is inside the 14-day remediation window. It reaches + the binary transitively through the upstream Datadog agent dependency + graph, so the bump has to go through a go.mod update rather than a direct + version pin. Tracked in STAC-25556. diff --git a/exceptions/stackstate-k8s-cluster-agent/GO-2026-5932.yaml b/exceptions/stackstate-k8s-cluster-agent/GO-2026-5932.yaml new file mode 100644 index 000000000000..6025ad99e3da --- /dev/null +++ b/exceptions/stackstate-k8s-cluster-agent/GO-2026-5932.yaml @@ -0,0 +1,26 @@ +schema_version: '1' +vulnerability: + id: GO-2026-5932 + severity: UNKNOWN +product: + consumer: stackstate-k8s-cluster-agent + image: quay.io/stackstate/stackstate-k8s-cluster-agent +component: + purl: pkg:golang/golang.org/x/crypto@v0.53.0 + paths: + - opt/stackstate-agent/bin/stackstate-cluster-agent/stackstate-cluster-agent +status: accepted_with_compensating_control +reason: unpublished_image_vex_identity_bridge +expires: '2026-08-20' +owner: "@StackVista/observability-team" +upstream_owner: golang +upstream_reference: https://pkg.go.dev/vuln/GO-2026-5932 +statement: | + The affected openpgp and openpgp/clearsign packages are absent from this + binary's command dependency graph. StackVista/vexhub carries the reviewed + image-scoped not_affected statement, but Grype and Trivy match VEX products + by exact image digest or tag, and this gate scans a freshly built commit + image whose identity cannot exist in the VEX hub in advance. The same + bridge is already in place for stackstate-process-agent. Keep it only until + the scan pipeline can apply reviewed statements to unpublished images + without broadening them to every consumer of golang.org/x/crypto. From b656b1f46238e41814b409186f41ecabc9eb3a5e Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Wed, 5 Aug 2026 16:57:39 +0200 Subject: [PATCH 4/6] STAC-25500: port the DEB signing and pre-release publishing lane to GitHub Closes the last two GitLab jobs with no GitHub counterpart: sign_deb and pre_release_deb (.gitlab-ci-agent.yml lines 604 and 635). Security prerequisite, not cleanup ---------------------------------- sign_debian_package.sh called printenv unconditionally. On GitLab that dumped the GPG private key and its passphrase into the job log; stackstate-agent is a PUBLIC repo, so on GitHub that log is world-readable. It also left the exported private key in the checkout as gpg_private.key, where any later artifact upload would collect it. Both are removed before any signing secret is wired in. Key setup now happens in an ephemeral GNUPGHOME created with mktemp and mode 700, removed by an EXIT trap that also kills the gpg-agent so a preset passphrase cannot outlive the job on a reused runner. The passphrase reaches gpg through a mode-600 file inside that directory rather than argv. Fixes a latent signing bug -------------------------- The old preset step interpolated an unquoted command substitution into a single gpg-preset-passphrase call. A key exposes one keygrip per primary and subkey, so with a signing subkey the second keygrip was passed as a stray argument and never presetted, leaving signing able to block on a pinentry prompt no CI runner can answer. Each keygrip is now presetted individually. Verified against a throwaway key: two keygrips, both presetted. Shared setup ------------ sign_debian_package.sh and publish_package.sh need the same key in the same state but are separate processes, and on GitHub may be separate steps, so neither can rely on a keyring the other left behind. The setup moves into gpg_signing_setup.sh, sourced by both. gpg-preset-passphrase is auto-detected across /usr/lib/gnupg2, /usr/lib/gnupg, /usr/libexec and PATH, and the script fails loudly rather than silently skipping the preset when it is absent. Both scripts now fall back from CI_PROJECT_DIR to GITHUB_WORKSPACE, and publish_package.sh falls back from CI_COMMIT_REF_NAME to GITHUB_REF_NAME, so the apt codename stays the release branch exactly as it was on GitLab. Workflow -------- sign-and-publish-deb downloads both architecture artifacts and runs a single deb-s3 upload. GitLab fanned this out per architecture, so two jobs rewrote the same apt index concurrently; collecting both first removes that race. The install script is split in two. generate-install-script runs inv release.generate-install -t inside the build container, because the task collection imports python-gitlab and the GitHub and Datadog API helpers and only loads in the conda environment, and asserts the rendered script contains no None.s3.amazonaws.com from an unset bucket variable. publish-install-script then uploads it, so the container job never holds a credential. Both publishing jobs are gated on push and bound to the agent-pre-release environment, which carries the deployment branch rule, the signing secrets and the AWS role from STAC-25545. Pull requests cannot reach them. Validated: shellcheck -x clean on all three scripts; gpg_signing_setup exercised against a generated throwaway key covering explicit override, PATH auto-detection and the missing-binary failure path; actionlint clean apart from the pre-existing self-hosted runner-label notices; zizmor reports no findings. Blocked until the agent-pre-release environment, its four SIGNING_* secrets and AGENT_PRERELEASE_ROLE_ARN exist. Refs STAC-25546, STAC-25545 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build-deb.yml | 135 +++++++++++++++++- omnibus/package-scripts/gpg_signing_setup.sh | 67 +++++++++ omnibus/package-scripts/publish_package.sh | 40 +++--- .../package-scripts/sign_debian_package.sh | 36 ++--- 4 files changed, 236 insertions(+), 42 deletions(-) create mode 100755 omnibus/package-scripts/gpg_signing_setup.sh diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index ced8a5452144..11d0ea6e5341 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -236,7 +236,7 @@ jobs: timeout-minutes: 60 env: ARCH: ${{ matrix.arch }} - LOCAL_IMAGE: quay.io/stackstate/stackstate-k8s-agent:ci-${{ matrix.arch }} + LOCAL_IMAGE: stackstate-agent:ci-${{ matrix.arch }} steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -283,7 +283,6 @@ jobs: mode: gate severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL with-grype: true - exceptions-path: exceptions upload-sarif: false sarif-category: stackstate-k8s-agent-${{ matrix.arch }} @@ -399,6 +398,135 @@ jobs: target-registry-user: ${{ vars.QUAY_USER }} target-registry-password: ${{ secrets.QUAY_PASSWORD }} + sign-and-publish-deb: + name: Sign DEB packages (GPG) and publish to the pre-release apt repository + needs: + - build-deb + - test-deb-renaming + if: github.event_name == 'push' + runs-on: ubuntu-24.04 + environment: agent-pre-release + timeout-minutes: 30 + permissions: + contents: read + id-token: write + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Download amd64 DEB package + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: deb-package-amd64 + + - name: Download arm64 DEB package + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: deb-package-arm64 + + - name: Install debsigs, GnuPG and deb-s3 + run: | + set -euo pipefail + sudo apt-get update + sudo apt-get install -y --no-install-recommends debsigs gnupg gpg-agent + sudo gem install --no-document deb-s3 + + - name: Assume the pre-release publishing role + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 + with: + role-to-assume: ${{ vars.AGENT_PRERELEASE_ROLE_ARN }} + aws-region: eu-west-1 + + - name: Sign the DEB packages with debsigs + env: + SIGNING_PUBLIC_KEY: ${{ secrets.SIGNING_PUBLIC_KEY }} + SIGNING_PRIVATE_KEY: ${{ secrets.SIGNING_PRIVATE_KEY }} + SIGNING_PRIVATE_PASSPHRASE: ${{ secrets.SIGNING_PRIVATE_PASSPHRASE }} + SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} + run: ./omnibus/package-scripts/sign_debian_package.sh + + - name: Publish the DEB packages to the pre-release apt repository + env: + SIGNING_PUBLIC_KEY: ${{ secrets.SIGNING_PUBLIC_KEY }} + SIGNING_PRIVATE_KEY: ${{ secrets.SIGNING_PRIVATE_KEY }} + SIGNING_PRIVATE_PASSPHRASE: ${{ secrets.SIGNING_PRIVATE_PASSPHRASE }} + SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} + run: ./omnibus/package-scripts/publish_package.sh stackstate-agent-3-test + + generate-install-script: + name: Generate the pre-release agent install script + needs: godeps-cache-amd64 + if: github.event_name == 'push' + runs-on: xlarge-public + timeout-minutes: 30 + permissions: + contents: read + container: + image: ${{ needs.godeps-cache-amd64.outputs.ci_image }} # zizmor: ignore[unpinned-images] + credentials: + username: ${{ vars.REGISTRY_USER }} + password: ${{ secrets.REGISTRY_PASSWORD }} + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Render install.sh against the pre-release repositories + env: + STS_AWS_TEST_BUCKET: stackstate-agent-3-test + STS_AWS_TEST_BUCKET_YUM: stackstate-agent-3-rpm-test + STS_AWS_TEST_BUCKET_WIN: stackstate-agent-3-test + run: | + set -eo pipefail + . /root/miniforge3/etc/profile.d/conda.sh + conda activate "${CONDA_ENV}" + git config --global --add safe.directory '*' + inv release.generate-install -t + grep -q 's3.amazonaws.com' ./cmd/agent/install.sh + if grep -q 'None.s3.amazonaws.com' ./cmd/agent/install.sh; then + echo "install.sh references an unset bucket variable" >&2 + exit 1 + fi + + - name: Upload the rendered install script + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: agent-install-script + path: cmd/agent/install.sh + retention-days: 5 + if-no-files-found: error + + publish-install-script: + name: Publish the pre-release agent install script to S3 + needs: generate-install-script + if: github.event_name == 'push' + runs-on: ubuntu-24.04 + environment: agent-pre-release + timeout-minutes: 15 + permissions: + contents: read + id-token: write + steps: + - name: Download the rendered install script + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: agent-install-script + + - name: Assume the pre-release publishing role + uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 + with: + role-to-assume: ${{ vars.AGENT_PRERELEASE_ROLE_ARN }} + aws-region: eu-west-1 + + - name: Upload install.sh + run: | + set -euo pipefail + aws s3 cp ./install.sh s3://stackstate-agent-3-test/install.sh --acl public-read + aws s3 ls s3://stackstate-agent-3-test/ + cerberus-notify: name: Report failure to Slack (Cerberus) needs: @@ -409,6 +537,9 @@ jobs: - build-agent-image - publish-agent-image - merge-agent-manifest + - sign-and-publish-deb + - generate-install-script + - publish-install-script if: >- always() && github.event_name == 'push' diff --git a/omnibus/package-scripts/gpg_signing_setup.sh b/omnibus/package-scripts/gpg_signing_setup.sh new file mode 100755 index 000000000000..973f7b4160eb --- /dev/null +++ b/omnibus/package-scripts/gpg_signing_setup.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# Sourced by sign_debian_package.sh and publish_package.sh. +# +# Both scripts need the same signing key in the same state, but they are +# separate processes and on GitHub Actions they may run as separate steps, so +# neither can rely on a keyring the other left behind. Sourcing this keeps the +# setup identical in both without duplicating it. + +gpg_signing_setup() { + : "${SIGNING_PUBLIC_KEY:?SIGNING_PUBLIC_KEY is not set}" + : "${SIGNING_PRIVATE_KEY:?SIGNING_PRIVATE_KEY is not set}" + : "${SIGNING_PRIVATE_PASSPHRASE:?SIGNING_PRIVATE_PASSPHRASE is not set}" + : "${SIGNING_KEY_ID:?SIGNING_KEY_ID is not set}" + + # Debian ships this under /usr/lib/gnupg2 on the old signing image and under + # /usr/lib/gnupg on current releases, and it is not on PATH in either. + local preset="${GPG_PRESET_PASSPHRASE:-}" + if [ -z "${preset}" ]; then + for candidate in \ + /usr/lib/gnupg2/gpg-preset-passphrase \ + /usr/lib/gnupg/gpg-preset-passphrase \ + /usr/libexec/gpg-preset-passphrase \ + "$(command -v gpg-preset-passphrase 2>/dev/null || true)"; do + if [ -n "${candidate}" ] && [ -x "${candidate}" ]; then + preset="${candidate}" + break + fi + done + fi + if [ ! -x "${preset:-}" ]; then + echo "gpg-preset-passphrase not found; set GPG_PRESET_PASSPHRASE" >&2 + return 1 + fi + + # Keep the keyring and the private key off the build workspace: this + # repository is public, and anything left in the checkout can be swept up by + # an artifact upload. The trap also stops a gpg-agent holding a preset + # passphrase from outliving the job on a reused runner. + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + chmod 700 "${GNUPGHOME}" + trap 'gpgconf --kill gpg-agent >/dev/null 2>&1 || true; rm -rf "${GNUPGHOME}"' EXIT + + cat <<-CONF >"${GNUPGHOME}/gpg-agent.conf" + default-cache-ttl 46000 + allow-preset-passphrase + CONF + + local passphrase_file="${GNUPGHOME}/passphrase" + (umask 077; printf '%s' "${SIGNING_PRIVATE_PASSPHRASE}" >"${passphrase_file}") + + printf '%s\n' "${SIGNING_PUBLIC_KEY}" | gpg --batch --quiet --import + printf '%s\n' "${SIGNING_PRIVATE_KEY}" \ + | gpg --batch --yes --quiet --pinentry-mode loopback \ + --passphrase-file "${passphrase_file}" --import + + gpg-connect-agent RELOADAGENT /bye + + # A key can expose more than one keygrip (primary plus subkeys); preset each + # so signing never blocks on a pinentry prompt a CI runner cannot answer. + gpg --list-secret-keys --with-fingerprint --with-colons \ + | awk -F: '$1 == "grp" { print $10 }' \ + | while read -r keygrip; do + "${preset}" --preset "${keygrip}" <"${passphrase_file}" + done +} diff --git a/omnibus/package-scripts/publish_package.sh b/omnibus/package-scripts/publish_package.sh index 828fabf40c71..3af581dbf98f 100755 --- a/omnibus/package-scripts/publish_package.sh +++ b/omnibus/package-scripts/publish_package.sh @@ -1,29 +1,31 @@ #!/bin/bash -TARGET_BUCKET=$1 +set -euo pipefail -CODENAME=${2:-$CI_COMMIT_REF_NAME} -TARGET_CODENAME=${CODENAME:-dirty} +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=omnibus/package-scripts/gpg_signing_setup.sh +source "${script_dir}/gpg_signing_setup.sh" - -if [ -z ${TARGET_BUCKET+x} ]; then - echo "Missing S3 bucket parameter" - exit 1; +TARGET_BUCKET="${1:-}" +if [ -z "${TARGET_BUCKET}" ]; then + echo "Missing S3 bucket parameter" >&2 + exit 1 fi -if [ -z ${STACKSTATE_AGENT_VERSION+x} ]; then - STACKSTATE_AGENT_VERSION=$(cat $CI_PROJECT_DIR/version.txt) -fi -echo $STACKSTATE_AGENT_VERSION +# CI_PROJECT_DIR is GitLab's; GITHUB_WORKSPACE is the GitHub Actions equivalent. +PROJECT_DIR="${CI_PROJECT_DIR:-${GITHUB_WORKSPACE:-$(pwd)}}" +PKG_DIR="${PKG_DIR:-${PROJECT_DIR}/outcomes/pkg}" -ls $CI_PROJECT_DIR/outcomes/pkg/*.* +CODENAME="${2:-${CI_COMMIT_REF_NAME:-${GITHUB_REF_NAME:-}}}" +TARGET_CODENAME="${CODENAME:-dirty}" + +if [ -z "${STACKSTATE_AGENT_VERSION:-}" ]; then + STACKSTATE_AGENT_VERSION=$(cat "${PROJECT_DIR}/version.txt") +fi -cat <~/.gnupg/gpg-agent.conf -default-cache-ttl 46000 -allow-preset-passphrase -EOF +echo "Publishing stackstate-agent ${STACKSTATE_AGENT_VERSION} to ${TARGET_BUCKET} (${TARGET_CODENAME})" +ls "${PKG_DIR}"/*.* -gpg-connect-agent RELOADAGENT /bye -echo $SIGNING_PRIVATE_PASSPHRASE | /usr/lib/gnupg2/gpg-preset-passphrase -v -c $(gpg --list-secret-keys --with-fingerprint --with-colons | awk -F: '$1 == "grp" { print $10 }') +gpg_signing_setup -deb-s3 upload --sign=${SIGNING_KEY_ID} --codename ${TARGET_CODENAME} --bucket ${TARGET_BUCKET} $CI_PROJECT_DIR/outcomes/pkg/*.deb +deb-s3 upload --sign="${SIGNING_KEY_ID}" --codename "${TARGET_CODENAME}" --bucket "${TARGET_BUCKET}" "${PKG_DIR}"/*.deb diff --git a/omnibus/package-scripts/sign_debian_package.sh b/omnibus/package-scripts/sign_debian_package.sh index 7ed0f3c8aa94..a1915bdec7ad 100755 --- a/omnibus/package-scripts/sign_debian_package.sh +++ b/omnibus/package-scripts/sign_debian_package.sh @@ -1,30 +1,24 @@ #!/bin/bash -set -e +set -euo pipefail -if [ -z ${STACKSTATE_AGENT_VERSION+x} ]; then +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=omnibus/package-scripts/gpg_signing_setup.sh +source "${script_dir}/gpg_signing_setup.sh" + +# CI_PROJECT_DIR is GitLab's; GITHUB_WORKSPACE is the GitHub Actions equivalent. +PROJECT_DIR="${CI_PROJECT_DIR:-${GITHUB_WORKSPACE:-$(pwd)}}" +PKG_DIR="${PKG_DIR:-${PROJECT_DIR}/outcomes/pkg}" + +if [ -z "${STACKSTATE_AGENT_VERSION:-}" ]; then # Pick the latest tag by default for our version. - STACKSTATE_AGENT_VERSION=$(cat $CI_PROJECT_DIR/version.txt) + STACKSTATE_AGENT_VERSION=$(cat "${PROJECT_DIR}/version.txt") # But we will be building from the master branch in this case. fi -echo $STACKSTATE_AGENT_VERSION - -printenv - -echo "$SIGNING_PUBLIC_KEY" | gpg --import -echo "$SIGNING_PRIVATE_KEY" > gpg_private.key -echo "$SIGNING_PRIVATE_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 --import gpg_private.key -echo "$SIGNING_KEY_ID" - -ls $CI_PROJECT_DIR/outcomes/pkg/*.* - -cat <~/.gnupg/gpg-agent.conf -default-cache-ttl 46000 -allow-preset-passphrase -EOF +echo "Signing stackstate-agent ${STACKSTATE_AGENT_VERSION}" +ls "${PKG_DIR}"/*.* -gpg-connect-agent RELOADAGENT /bye -echo $SIGNING_PRIVATE_PASSPHRASE | /usr/lib/gnupg2/gpg-preset-passphrase -v -c $(gpg --list-secret-keys --with-fingerprint --with-colons | awk -F: '$1 == "grp" { print $10 }') +gpg_signing_setup -debsigs --sign=origin -k ${SIGNING_KEY_ID} $CI_PROJECT_DIR/outcomes/pkg/*.deb +debsigs --sign=origin -k "${SIGNING_KEY_ID}" "${PKG_DIR}"/*.deb From e2977c09a97b754726b7132051b256038e0a0b89 Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Thu, 6 Aug 2026 15:52:16 +0200 Subject: [PATCH 5/6] STAC-25500: pin deb-s3 and gate install.sh publication on DEB publication Addresses review feedback on PR #455. [P1] The signing job installed the publisher with `gem install deb-s3`, resolving the latest code at run time into a job that then executes it with the package signing key and the pre-release AWS credentials in scope. GitLab never did this: `sign_deb` ran in a pinned image with deb-s3 already baked in, so the runtime resolve was a regression introduced by the port. deb-s3 and its full runtime dependency tree are now pinned in `.github/deb-s3-gems.sha256` and installed by `.github/scripts/install-deb-s3.sh`, which fetches each gem at its exact version and verifies it against the SHA256 RubyGems publishes for that release before anything is installed or executed. The manifest covers nine gems. base64, bigdecimal and logger are deliberately excluded: aws-sdk-core requires them at ">= 0" and they are Ruby default gems supplied by the distribution's own ruby package, so pinning them would force a native build for no supply-chain gain. The script also links the canonical executable when RubyGems installs a versioned binstub, since publish_package.sh invokes deb-s3 by bare name, and ends with a `deb-s3 help` smoke check that activates the whole pinned set so a missing or incompatible gem fails at install time rather than midway through publishing. [P2] publish-install-script depended only on generate-install-script, so it could overwrite the public install.sh even when the build, signing or apt upload had failed. GitLab's pre_release_deb required sign_deb. It now requires both generate-install-script and sign-and-publish-deb, restoring that release boundary. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/deb-s3-gems.sha256 | 9 +++++ .github/scripts/install-deb-s3.sh | 65 +++++++++++++++++++++++++++++++ .github/workflows/build-deb.yml | 12 ++++-- 3 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 .github/deb-s3-gems.sha256 create mode 100755 .github/scripts/install-deb-s3.sh diff --git a/.github/deb-s3-gems.sha256 b/.github/deb-s3-gems.sha256 new file mode 100644 index 000000000000..75afacad61c1 --- /dev/null +++ b/.github/deb-s3-gems.sha256 @@ -0,0 +1,9 @@ +116bf85c436200d1060811e6f5d2d40c88f65448f2125bc77ffce5121e6e183b aws-eventstream-1.4.0.gem +40bda996876a45a60c43fbf489b04b46216e98c1814c1ac6453b942e0df6501e aws-partitions-1.1277.0.gem +ee3e3220b8468a3c9e59daba18e6ec897bf5c7ce8adcc0670cfa2f1f092112fe aws-sdk-core-3.254.0.gem +a2e83662ca31b77a2a19c9aa2f40a98165a67270c18c718fe1c70d0cbd7cd749 aws-sdk-kms-1.130.0.gem +1217b878b554b45f2152115c5d2623e3497222f46a738e5a96e9767cbf41468b aws-sdk-s3-1.228.2.gem +6973ff95cb0fd0dc58ba26e90e9510a2219525d07620c8babeb70ef831826c00 aws-sigv4-1.12.1.gem +8beb36bd7d5f524644f2e4b947e9212bcb47cab0b50cd8ad459ce527f938b956 deb-s3-26.1.0.gem +238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1 jmespath-1.6.2.gem +e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73 thor-1.5.0.gem diff --git a/.github/scripts/install-deb-s3.sh b/.github/scripts/install-deb-s3.sh new file mode 100755 index 000000000000..9f975b9e82a2 --- /dev/null +++ b/.github/scripts/install-deb-s3.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# +# Install deb-s3 and its full runtime dependency tree from a pinned, checksum +# verified manifest. +# +# deb-s3 runs with the package signing key and the pre-release AWS credentials +# in scope, so it must not be resolved at run time. Every gem is fetched at the +# exact version recorded in the manifest and verified against the SHA256 that +# RubyGems publishes for that release before anything is installed or executed. +# +# Usage: install-deb-s3.sh [manifest] +# +# Regenerating the manifest: fetch each gem and record +# " -.gem", matching the checksum published at +# https://rubygems.org/api/v1/versions/.json for that version. + +set -euo pipefail + +MANIFEST="${1:-.github/deb-s3-gems.sha256}" + +if [[ ! -f "${MANIFEST}" ]]; then + echo "gem manifest not found: ${MANIFEST}" >&2 + exit 1 +fi + +MANIFEST_ABS="$(cd "$(dirname "${MANIFEST}")" && pwd)/$(basename "${MANIFEST}")" + +WORKDIR="$(mktemp -d)" +trap 'rm -rf "${WORKDIR}"' EXIT + +cp "${MANIFEST_ABS}" "${WORKDIR}/gems.sha256" +cd "${WORKDIR}" + +while read -r _sha file; do + [[ -n "${file:-}" ]] || continue + name="${file%-*}" + version="${file##*-}" + version="${version%.gem}" + echo "fetching ${name} ${version}" + gem fetch "${name}" --version "${version}" --platform ruby +done < gems.sha256 + +echo "verifying checksums" +sha256sum --check --strict gems.sha256 + +echo "installing" +${GEM_INSTALL_SUDO-sudo} gem install --local --no-document --ignore-dependencies ./*.gem + +# RubyGems installs versioned binstubs on some distributions (deb-s3.ruby3.2, +# deb-s33.2), so a plain "deb-s3" on PATH is not guaranteed. publish_package.sh +# invokes it by bare name, so link the canonical executable when it is missing. +if ! command -v deb-s3 >/dev/null 2>&1; then + canonical="$(gem contents deb-s3 | grep -E '/bin/deb-s3$' | head -n 1)" + if [[ -z "${canonical}" ]]; then + echo "deb-s3 was installed but its executable could not be located" >&2 + exit 1 + fi + ${GEM_INSTALL_SUDO-sudo} ln -sf "${canonical}" "${LINK_DIR:-/usr/local/bin}/deb-s3" +fi + +# Smoke check: this activates the whole pinned dependency set, so a missing or +# incompatible gem fails here rather than midway through publishing. +echo "verifying deb-s3" +deb-s3 help >/dev/null +echo "deb-s3 ready: $(command -v deb-s3)" diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 11d0ea6e5341..591e6e548230 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -426,12 +426,14 @@ jobs: with: name: deb-package-arm64 - - name: Install debsigs, GnuPG and deb-s3 + - name: Install debsigs and GnuPG run: | set -euo pipefail sudo apt-get update - sudo apt-get install -y --no-install-recommends debsigs gnupg gpg-agent - sudo gem install --no-document deb-s3 + sudo apt-get install -y --no-install-recommends debsigs gnupg gpg-agent ruby + + - name: Install deb-s3 from the pinned, checksum-verified manifest + run: ./.github/scripts/install-deb-s3.sh .github/deb-s3-gems.sha256 - name: Assume the pre-release publishing role uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 @@ -501,7 +503,9 @@ jobs: publish-install-script: name: Publish the pre-release agent install script to S3 - needs: generate-install-script + needs: + - generate-install-script + - sign-and-publish-deb if: github.event_name == 'push' runs-on: ubuntu-24.04 environment: agent-pre-release From 185e7630d48aa1b639be5fde0976714db7f72a74 Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Fri, 7 Aug 2026 13:53:37 +0200 Subject: [PATCH 6/6] STAC-25500 Restore the image scan exception wiring lost in the rebase Resolving the rebase conflict against the rewritten base took this branch's whole copy of build-deb.yml, which predated the exception work on STAC-25457. That silently reverted two lines, so the gate ran here with no exceptions loaded and reported all 24 findings as unmanaged. Restores the quay LOCAL_IMAGE name the evaluator matches exceptions on, and the exceptions-path input. The workflow diff against the base branch is now additions only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build-deb.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 591e6e548230..4b5503ce2f36 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -236,7 +236,7 @@ jobs: timeout-minutes: 60 env: ARCH: ${{ matrix.arch }} - LOCAL_IMAGE: stackstate-agent:ci-${{ matrix.arch }} + LOCAL_IMAGE: quay.io/stackstate/stackstate-k8s-agent:ci-${{ matrix.arch }} steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -283,6 +283,7 @@ jobs: mode: gate severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL with-grype: true + exceptions-path: exceptions upload-sarif: false sarif-category: stackstate-k8s-agent-${{ matrix.arch }}