From cb90d637e17ac5068ea49059fd1e1d82e0acd812 Mon Sep 17 00:00:00 2001 From: Rahul Pidde <206018639+cx-rahul-pidde@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:46:57 +0530 Subject: [PATCH] Squashed signed staging changes (AST-181538) Single signed commit equivalent to the 12 commits of PR #1587 (staging): - Add provenance tag and confidence-gated suppression to guardrail prompts (AST-180794) (#1578) - Merge branch 'main' into staging - Block agent file edits that introduce hardcoded secrets (AST-181538) (#1583) - Honour scanner switches and severity threshold from cx-onboarding.properties (#1586) - Fix golangci-lint issues in agent hooks / remaining revive comment lint issues - Updated misleading message on wrong scan-report format (AST-182790) (#1588) - Fix pillow and sqlparse SCA findings (AST-188320) (#1590) - Bump/revert bash base image, ignore CVE-2026-111943 in Trivy, restore lodash 4.17.21 test fixture (AST-000) Co-Authored-By: Claude Sonnet 5.5 --- .trivyignore | 7 + Dockerfile | 2 +- go.mod | 148 ++++++-- go.sum | 358 +++++++++++++----- internal/commands/agenthooks/cx/hooks.go | 103 ++++- internal/commands/agenthooks/cx/hooks_test.go | 75 +++- .../agenthooks/cx/scanner_switch_test.go | 243 ++++++++++++ .../agenthooks/guardrails/asca/asca.go | 35 +- .../agenthooks/guardrails/kics/kics.go | 25 +- .../agenthooks/guardrails/secrets/content.go | 40 ++ .../guardrails/secrets/content_test.go | 77 ++++ .../agenthooks/guardrails/secrets/delta.go | 203 ++++++++++ .../agenthooks/guardrails/secrets/prompts.go | 136 +++++++ .../agenthooks/guardrails/secrets/scanner.go | 32 ++ .../agenthooks/guardrails/secrets/secrets.go | 148 ++++++++ .../guardrails/secrets/secrets_test.go | 330 ++++++++++++++++ internal/commands/agenthooks/sca/sca.go | 29 ++ .../commands/agenthooks/sca/threshold_test.go | 42 ++ .../agenthooks/scannerconfig/scannerconfig.go | 121 ++++++ .../scannerconfig/scannerconfig_test.go | 138 +++++++ .../commands/data/manifests/requirements.txt | 12 +- internal/commands/scan.go | 7 +- .../secretsrealtime/secrets-realtime.go | 46 ++- .../secretsrealtime/secrets-realtime_test.go | 24 ++ .../data/manifests/requirements.txt | 12 +- 25 files changed, 2196 insertions(+), 197 deletions(-) create mode 100644 internal/commands/agenthooks/cx/scanner_switch_test.go create mode 100644 internal/commands/agenthooks/guardrails/secrets/content.go create mode 100644 internal/commands/agenthooks/guardrails/secrets/content_test.go create mode 100644 internal/commands/agenthooks/guardrails/secrets/delta.go create mode 100644 internal/commands/agenthooks/guardrails/secrets/prompts.go create mode 100644 internal/commands/agenthooks/guardrails/secrets/scanner.go create mode 100644 internal/commands/agenthooks/guardrails/secrets/secrets.go create mode 100644 internal/commands/agenthooks/guardrails/secrets/secrets_test.go create mode 100644 internal/commands/agenthooks/sca/threshold_test.go create mode 100644 internal/commands/agenthooks/scannerconfig/scannerconfig.go create mode 100644 internal/commands/agenthooks/scannerconfig/scannerconfig_test.go diff --git a/.trivyignore b/.trivyignore index 58ab2c148..2b2557636 100644 --- a/.trivyignore +++ b/.trivyignore @@ -40,6 +40,13 @@ CVE-2026-95818 # Reason: Base image vulnerability - awaiting Wolfi update to 1.3.2.1_rc20260601-r0 CVE-2026-85091 +# CVE-2026-111943: ca-certificates-bundle crypto/x509 certificate handling +# Severity: HIGH +# Component: ca-certificates-bundle 20260909-r2 (in checkmarx/bash base image) +# Reason: Base image vulnerability - fix is ca-certificates-bundle 20260909-r3, but the latest +# checkmarx/bash tag (5.3-r14) on Docker Hub still ships -r2. Remove once a rebuilt image is published. +CVE-2026-111943 + # ============================================================================ # BINARY VULNERABILITIES - Compatibility Issues (Not Updated) # ============================================================================ diff --git a/Dockerfile b/Dockerfile index 33068cae9..c8e06901f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM checkmarx/bash:5.3-r13-f99a9136837d1b@sha256:63716ceab566d449b6c1de5032f0ca1e6da5ffa8627b419941f07b35451e3626 +FROM checkmarx/bash:5.3-r14-ca00804d797fe8@sha256:ca00804d797fe8c0846a2f1ec4fc159bd08fdf66a6c8621031c954d1bee61193 USER nonroot COPY cx /app/bin/cx diff --git a/go.mod b/go.mod index feee8cdd0..12e754d86 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/checkmarx/ast-cli -go 1.26.9 +go 1.26.10 require ( github.com/Checkmarx/ast-cx-hooks v1.0.10 @@ -16,7 +16,7 @@ require ( github.com/checkmarx/2ms/v3 v3.21.0 github.com/gofrs/flock v0.13.0 github.com/golang-jwt/jwt/v5 v5.3.1 - github.com/gomarkdown/markdown v0.0.0-20260417124207-7d523f7318df + github.com/gomarkdown/markdown v0.0.0-20260724235538-61af6e1e6971 github.com/google/uuid v1.6.0 github.com/gookit/color v1.6.0 github.com/jcmturner/gokrb5/v8 v8.4.4 @@ -30,9 +30,9 @@ require ( github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 github.com/xeipuuv/gojsonschema v1.2.0 github.com/zalando/go-keyring v0.2.8 - golang.org/x/crypto v0.57.0 - golang.org/x/sync v0.23.0 - golang.org/x/text v0.42.0 + golang.org/x/crypto v0.58.0 + golang.org/x/sync v0.24.0 + golang.org/x/text v0.43.0 google.golang.org/grpc v1.83.2 google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af gopkg.in/yaml.v3 v3.0.1 @@ -40,35 +40,104 @@ require ( ) require ( - cyphar.com/go-pathrs v0.2.5 // indirect - github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect - github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 // indirect - github.com/Masterminds/semver v1.5.0 // indirect + cel.dev/expr v0.25.2 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.18.2 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + cloud.google.com/go/iam v1.5.3 // indirect + cloud.google.com/go/monitoring v1.24.3 // indirect + cloud.google.com/go/storage v1.61.3 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect + github.com/OneOfOne/xxhash v1.2.8 // indirect + github.com/STARRY-S/zip v0.2.3 // indirect + github.com/anchore/go-lzo v0.1.0 // indirect + github.com/anchore/go-rpmdb v0.0.0-20250516171929-f77691e1faec // indirect + github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.12 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.12 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect + github.com/aws/smithy-go v1.24.2 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect + github.com/bodgit/plumbing v1.3.0 // indirect + github.com/bodgit/sevenzip v1.6.1 // indirect + github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect + github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect + github.com/containerd/containerd/v2 v2.3.6 // indirect + github.com/containerd/plugin v1.1.0 // indirect github.com/danieljoos/wincred v1.2.3 // indirect + github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.1.1 // indirect github.com/docker/docker v28.0.3+incompatible // indirect - github.com/docker/go-events v0.0.0-20250808211157-605354379745 // indirect - github.com/edsrzf/mmap-go v1.2.0 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect + github.com/goccy/go-yaml v1.19.2 // indirect github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/snappy v1.0.0 // indirect + github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/jsonschema-go v0.4.3 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect + github.com/googleapis/gax-go/v2 v2.17.0 // indirect + github.com/gpustack/gguf-parser-go v0.24.0 // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.8.6 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/henvic/httpretty v0.1.4 // indirect github.com/klauspost/cpuid/v2 v2.4.0 // indirect - github.com/knqyf263/go-rpmdb v0.1.1 // indirect - github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423092549-19e70c243037 // indirect + github.com/mholt/archives v0.1.5 // indirect + github.com/mikelolasagasti/xz v1.0.1 // indirect + github.com/minio/minlz v1.0.1 // indirect + github.com/moby/moby/api v1.54.2 // indirect + github.com/moby/moby/client v0.4.1 // indirect github.com/morikuni/aec v1.1.0 // indirect - github.com/nwaples/rardecode v1.1.3 // indirect - github.com/opencontainers/selinux v1.13.1 // indirect + github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect + github.com/nwaples/rardecode/v2 v2.2.0 // indirect + github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect + github.com/olekukonko/errors v1.2.0 // indirect + github.com/olekukonko/ll v0.1.6 // indirect + github.com/pkg/xattr v0.4.9 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/prometheus/procfs v0.20.1 // indirect - github.com/saferwall/pe v1.5.6 // indirect - github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect github.com/segmentio/asm v1.1.3 // indirect github.com/segmentio/encoding v0.5.4 // indirect + github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect + github.com/sorairolake/lzip-go v0.3.8 // indirect + github.com/spiffe/go-spiffe/v2 v2.7.0 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 // indirect + go.opentelemetry.io/otel/sdk v1.45.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.45.0 // indirect + go4.org v0.0.0-20230225012048-214862532bf5 // indirect + gonum.org/v1/gonum v0.17.0 // indirect + google.golang.org/api v0.271.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.3 // indirect ) require ( @@ -90,18 +159,17 @@ require ( github.com/acobaugh/osrelease v0.1.0 // indirect github.com/adrg/xdg v0.5.3 // indirect github.com/agext/levenshtein v1.2.3 // indirect - github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51 // indirect github.com/anchore/clio v0.0.0-20250320142751-cc31d7f3f651 // indirect github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2 // indirect - github.com/anchore/go-collections v0.0.0-20241211140901-567f400e9a46 // indirect + github.com/anchore/go-collections v0.0.0-20251016125210-a3c352120e8c // indirect github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d // indirect github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722 // indirect github.com/anchore/go-macholibre v0.0.0-20250320151634-807da7ad2331 // indirect github.com/anchore/go-struct-converter v0.1.0 // indirect github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b // indirect github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115 // indirect - github.com/anchore/stereoscope v0.1.0 // indirect - github.com/anchore/syft v1.21.0 // indirect + github.com/anchore/stereoscope v0.1.22 // indirect + github.com/anchore/syft v1.42.3 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/aquasecurity/go-pep440-version v0.0.1 // indirect @@ -122,13 +190,13 @@ require ( github.com/cloudflare/circl v1.6.5 // indirect github.com/containerd/cgroups/v3 v3.1.3 // indirect github.com/containerd/containerd v1.7.36 // indirect - github.com/containerd/containerd/api v1.10.0 // indirect + github.com/containerd/containerd/api v1.11.1 // indirect github.com/containerd/continuity v0.5.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/containerd/platforms v1.0.0-rc.4 // indirect + github.com/containerd/platforms v1.0.0-rc.5 // indirect github.com/containerd/ttrpc v1.2.8 // indirect github.com/containerd/typeurl/v2 v2.3.0 // indirect github.com/cyphar/filepath-securejoin v0.7.0 // indirect @@ -161,7 +229,7 @@ require ( github.com/go-git/go-billy/v5 v5.9.1 // indirect github.com/go-git/go-git/v5 v5.19.2 github.com/go-gorp/gorp/v3 v3.1.0 // indirect - github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.21.1 // indirect @@ -200,7 +268,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953 // indirect github.com/kevinburke/ssh_config v1.6.0 // indirect - github.com/klauspost/compress v1.18.6 // indirect + github.com/klauspost/compress v1.18.7 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -231,7 +299,7 @@ require ( github.com/muesli/termenv v0.16.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/olekukonko/tablewriter v1.1.4 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opencontainers/runtime-spec v1.3.0 // indirect @@ -288,9 +356,9 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect - go.opentelemetry.io/otel v1.44.0 // indirect - go.opentelemetry.io/otel/metric v1.44.0 // indirect - go.opentelemetry.io/otel/trace v1.44.0 // indirect + go.opentelemetry.io/otel v1.45.0 // indirect + go.opentelemetry.io/otel/metric v1.45.0 // indirect + go.opentelemetry.io/otel/trace v1.45.0 // indirect go.uber.org/mock v0.6.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect @@ -298,10 +366,10 @@ require ( golang.org/x/mod v0.41.0 // indirect golang.org/x/net v0.60.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sys v0.48.0 // indirect - golang.org/x/term v0.46.0 // indirect + golang.org/x/sys v0.49.0 // indirect + golang.org/x/term v0.47.0 // indirect golang.org/x/time v0.15.0 // indirect - golang.org/x/tools v0.49.0 // indirect + golang.org/x/tools v0.51.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect @@ -310,13 +378,13 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect helm.sh/helm/v3 v3.20.2 // indirect - k8s.io/api v0.36.0 // indirect + k8s.io/api v0.36.3 // indirect k8s.io/apiextensions-apiserver v0.35.1 // indirect - k8s.io/apimachinery v0.36.0 // indirect + k8s.io/apimachinery v0.36.3 // indirect k8s.io/apiserver v0.35.1 // indirect k8s.io/cli-runtime v0.36.0 // indirect - k8s.io/client-go v0.36.0 // indirect - k8s.io/component-base v0.36.0 // indirect + k8s.io/client-go v0.36.3 // indirect + k8s.io/component-base v0.36.3 // indirect k8s.io/klog/v2 v2.140.0 // indirect k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 // indirect k8s.io/kubectl v0.36.0 // indirect @@ -337,6 +405,4 @@ replace github.com/docker/go-connections => github.com/docker/go-connections v0. replace github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.13.0 -replace github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.2.0 - replace github.com/zalando/go-keyring => github.com/checkmarx/go-keyring v0.0.0-20260812105354-1168609d33ac diff --git a/go.sum b/go.sum index 169ae6e0d..563432fd6 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs= +cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -27,15 +29,31 @@ cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM= +cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc= +cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= +cloud.google.com/go/logging v1.13.1 h1:O7LvmO0kGLaHY/gq8cV7T0dyp6zJhYAOtZPX4TF3QtY= +cloud.google.com/go/logging v1.13.1/go.mod h1:XAQkfkMBxQRjQek96WLPNze7vsOmay9H5PqfsNYDqvw= +cloud.google.com/go/longrunning v0.8.0 h1:LiKK77J3bx5gDLi4SMViHixjD2ohlkwBi+mKA7EhfW8= +cloud.google.com/go/longrunning v0.8.0/go.mod h1:UmErU2Onzi+fKDg2gR7dusz11Pe26aknR4kHmJJqIfk= +cloud.google.com/go/monitoring v1.24.3 h1:dde+gMNc0UhPZD1Azu6at2e79bfdztVDS5lvhOdsgaE= +cloud.google.com/go/monitoring v1.24.3/go.mod h1:nYP6W0tm3N9H/bOw8am7t62YTzZY+zUeQ+Bi6+2eonI= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -45,8 +63,10 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cyphar.com/go-pathrs v0.2.5 h1:SnX9FBvnoyn3lUs1dkMgZ52bAETpirNu3FTRh5HlRik= -cyphar.com/go-pathrs v0.2.5/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= +cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KMOg= +cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= +cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= +cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -54,8 +74,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 h1:t9mXVk8SurivauUmW28nWggC/aOm5NBZ+U2ddBfbyP8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434/go.mod h1:n+tj8pffsLO7fLdcrnbfl444A2OwGv8a6ISsac75Wow= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8a+4nPE9g= @@ -90,12 +108,18 @@ github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0 h1:l7+6kwRMJNwdCvYdDl7Eax+wzEYHSnNY7zrrfbhDdTA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0/go.mod h1:IA1C1U7jO/ENqm/vhi7V9YYpBsp+IMyqNrEN94N7tVc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0 h1:7t/qx5Ost0s0wbA/VDrByOooURhp+ikYwv20i9Y07TQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0/go.mod h1:vB2GH9GAYYJTO3mEn8oYwzEdhlayZIdQz6zdzgUIRvA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 h1:0s6TxfCu2KHkkZPnBfsQ2y5qia0jl3MMrmBhu3nCOYk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= @@ -112,6 +136,8 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM= github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo= +github.com/STARRY-S/zip v0.2.3 h1:luE4dMvRPDOWQdeDdUxUoZkzUIpTccdKdhHHsQJ1fm4= +github.com/STARRY-S/zip v0.2.3/go.mod h1:lqJ9JdeRipyOQJrYSOtpNAiaesFO6zVDsE8GIGFaoSk= github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE= github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY= github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= @@ -124,32 +150,34 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= -github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51 h1:yhk+P8lF3ZiROjmaVRao9WGTRo4b/wYjoKEiAHWrKwc= -github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51/go.mod h1:nwuGSd7aZp0rtYt79YggCGafz1RYsclE7pi3fhLwvuw= github.com/anchore/clio v0.0.0-20250320142751-cc31d7f3f651 h1:GufQ55tLEC5gzm2BTfi3G1B/XjCEIHjPsL37vP2ywf0= github.com/anchore/clio v0.0.0-20250320142751-cc31d7f3f651/go.mod h1:Utb9i4kwiCWvqAIxZaJeMIXFO9uOgQXlvH2BfbfO/zI= github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2 h1:GC2QaO0YsmjpsZ4rtVKv9DnproIxqqn+qkskpc+i8MA= github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2/go.mod h1:XUbUECwVKuD3qYRUj+QZIOHjyyXua2gFmVjKA40iHXA= -github.com/anchore/go-collections v0.0.0-20241211140901-567f400e9a46 h1:huvprHsfzhrIIkk7kja1Fm5Wn3mnwPv4CeHrGlGD3ds= -github.com/anchore/go-collections v0.0.0-20241211140901-567f400e9a46/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8= +github.com/anchore/go-collections v0.0.0-20251016125210-a3c352120e8c h1:eoJXyC0n7DZ4YvySG/ETdYkTar2Due7eH+UmLK6FbrA= +github.com/anchore/go-collections v0.0.0-20251016125210-a3c352120e8c/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8= github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d h1:gT69osH9AsdpOfqxbRwtxcNnSZ1zg4aKy2BevO3ZBdc= github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d/go.mod h1:PhSnuFYknwPZkOWKB1jXBNToChBA+l0FjwOxtViIc50= github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722 h1:2SqmFgE7h+Ql4VyBzhjLkRF/3gDrcpUBj8LjvvO6OOM= github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722/go.mod h1:oFuE8YuTCM+spgMXhePGzk3asS94yO9biUfDzVTFqNw= +github.com/anchore/go-lzo v0.1.0 h1:NgAacnzqPeGH49Ky19QKLBZEuFRqtTG9cdaucc3Vncs= +github.com/anchore/go-lzo v0.1.0/go.mod h1:3kLx0bve2oN1iDwgM1U5zGku1Tfbdb0No5qp1eL1fIk= github.com/anchore/go-macholibre v0.0.0-20250320151634-807da7ad2331 h1:fWPHXkH3FQGVCyPkFMqNvMjQvdNMfkylBTsDqZC4lE4= github.com/anchore/go-macholibre v0.0.0-20250320151634-807da7ad2331/go.mod h1:DYvTRnWrlJ//6YOR83SiewmJiNFDEMRaOTnrzgco9FA= +github.com/anchore/go-rpmdb v0.0.0-20250516171929-f77691e1faec h1:SjjPMOXTzpuU1ZME4XeoHyek+dry3/C7I8gzaCo02eg= +github.com/anchore/go-rpmdb v0.0.0-20250516171929-f77691e1faec/go.mod h1:eQVa6QFGzKy0qMcnW2pez0XBczvgwSjw9vA23qifEyU= github.com/anchore/go-struct-converter v0.1.0 h1:2rDRssAl6mgKBSLNiVCMADgZRhoqtw9dedlWa0OhD30= github.com/anchore/go-struct-converter v0.1.0/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= -github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0vW0nnNKJfJieyH/TZ9UYAnTZs5/gHTdAe8= -github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ= +github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6 h1:Ha+LSCVuXYSYGi7wIkJK6G8g6jI3LH7y6LbyEVyp4Io= +github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6/go.mod h1:+9oM3XUy8iea/vWj9FhZ9bQGUBN8JpPxxJm5Wbcx9XM= github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods= github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115 h1:ZyRCmiEjnoGJZ1+Ah0ZZ/mKKqNhGcUZBl0s7PTTDzvY= github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI= -github.com/anchore/stereoscope v0.1.0 h1:waF2C5b/XRAyShKup3VoJz8Pdv7AiDxUbABTizmJdJ0= -github.com/anchore/stereoscope v0.1.0/go.mod h1:3vasimie0IJOXvMbMpjwvwIHBDA1+192QZDWNhJRqFQ= -github.com/anchore/syft v1.21.0 h1:JHmYOnEbCJsElROCCfg+3oIODw1LQLfXGkIrmXNZYsI= -github.com/anchore/syft v1.21.0/go.mod h1:8i8Yp/MiSOdqID0+6eiwE9bOJWM7fEBYitINZyr2G6s= +github.com/anchore/stereoscope v0.1.22 h1:L807G/kk0WZzOCGuRGF7knxMKzwW2PGdbPVRystryd8= +github.com/anchore/stereoscope v0.1.22/go.mod h1:FikPtAb/WnbqwgLHAvQA9O+fWez0K4pbjxzghz++iy4= +github.com/anchore/syft v1.42.3 h1:eIeeGyqfXm/C8wpBWU50xFbOjdL37VbLatMj9nEJ6n4= +github.com/anchore/syft v1.42.3/go.mod h1:i2PZ+276IdPcnd/n32aeIv849iO/QqdjRknbIc39yL0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= @@ -173,6 +201,44 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= +github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= +github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0= +github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g= +github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8= +github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 h1:HwxWTbTrIHm5qY+CAEur0s/figc3qwvLWsNkF4RPToo= +github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 h1:kiIDLZ005EcKomYYITtfsjn7dtOwHDOFy7IbPXKek2o= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 h1:jzKAXIlhZhJbnYwHbvUQZEB8KfgAEuG0dc08Bkda7NU= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8MSU6Ch5i9PgBkcU= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk= +github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= +github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/becheran/wildmatch-go v1.0.0 h1:mE3dGGkTmpKtT4Z+88t8RStG40yN9T+kFEGj2PZFSzA= @@ -181,13 +247,23 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitnami/go-version v0.0.0-20250324202741-04b9d491e744 h1:GpZTDKC8M59iKhOsTJb088Uz/h/EHU2ZL+XKwoLhv+U= github.com/bitnami/go-version v0.0.0-20250324202741-04b9d491e744/go.mod h1:9iglf1GG4oNRJ39bZ5AZrjgAFD2RwQbXw6Qf7Cs47wo= +github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= +github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs= github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU= +github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs= +github.com/bodgit/sevenzip v1.6.1 h1:kikg2pUMYC9ljU7W9SaqHXhym5HyKm8/M/jd31fYan4= +github.com/bodgit/sevenzip v1.6.1/go.mod h1:GVoYQbEVbOGT8n2pfqCIMRUaRjQ8F9oSqoBEqZh5fQ8= +github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= +github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= github.com/bouk/monkey v1.0.0 h1:k6z8fLlPhETfn5l9rlWVE7Q6B23DoaqosTdArvNQRdc= github.com/bouk/monkey v1.0.0/go.mod h1:PG/63f4XEUlVyW1ttIeOJmJhhe1+t9EC/je3eTjvFhE= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= @@ -207,10 +283,10 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80= github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= -github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= -github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI= -github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo= +github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= +github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= +github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= +github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= @@ -253,12 +329,16 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= github.com/containerd/containerd v1.7.36 h1:HyMsOG5kmp1LQsGzqwI6Ts06T4VpYZbszfDZYB0bW5w= github.com/containerd/containerd v1.7.36/go.mod h1:ozI//0TomTCLPhQREnx0IXDIQMg+Fk7yTtg9fNvU8EQ= -github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= -github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM= +github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= +github.com/containerd/containerd/api v1.11.1/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= +github.com/containerd/containerd/v2 v2.3.6 h1:huoqZXaDW1x1kgPvFC4rMwxv92vUJnqgq7I5b1rSddM= +github.com/containerd/containerd/v2 v2.3.6/go.mod h1:qaUSWKk9EchqbudSbhv1MxI8dXKGYHLpZtMQdkEkVZ4= github.com/containerd/continuity v0.5.0 h1:7a85HZpCSs+1Zps0Ee3DPSuAWY+0SJM1JNM51nlEVDg= github.com/containerd/continuity v0.5.0/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -269,8 +349,10 @@ github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v1.0.0-rc.4 h1:M42JrUT4zfZTqtkUwkr0GzmUWbfyO5VO0Q5b3op97T4= -github.com/containerd/platforms v1.0.0-rc.4/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A= +github.com/containerd/platforms v1.0.0-rc.5 h1:vXd569rDrz8LeMXzAnBsy6LADV5YtsD8oyaRarxdmSU= +github.com/containerd/platforms v1.0.0-rc.5/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A= +github.com/containerd/plugin v1.1.0 h1:O+7lczNJVMy8rz0YNx3xGB8tTf5qY4i5abF041Ew19U= +github.com/containerd/plugin v1.1.0/go.mod h1:qBTum+A8lJ6lO44A19Eo7y1OlcLj4OWFH1DA/vnHmcc= github.com/containerd/ttrpc v1.2.8 h1:xbVu6D4qF2jihdh9rDVOKqUMiFBQk6YctTdo1zk087Y= github.com/containerd/ttrpc v1.2.8/go.mod h1:wyZW2K79t4Hfcxl+GUvkZqRBzJlqFFvgEeeWXa42tyE= github.com/containerd/typeurl/v2 v2.3.0 h1:HZHPhRWo5XMy3QGQoPrUzbW/2ckwjfweHmOwlkIrPAQ= @@ -281,8 +363,8 @@ github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.7.0 h1:s0Y3ITPy6sQn5xt54DuYvTF8hu134ooYLUb58DX/HjE= github.com/cyphar/filepath-securejoin v0.7.0/go.mod h1:ymLGms/u3BYaviIiuKFnUx8EkQEZeK6cInNoAPJA3o4= github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= @@ -296,10 +378,14 @@ github.com/deitch/magic v0.0.0-20240306090643-c67ab88f10cb/go.mod h1:B3tI9iGHi4i github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/diskfs/go-diskfs v1.7.0 h1:vonWmt5CMowXwUc79jWyGrf2DIMeoOjkLlMnQYGVOs8= +github.com/diskfs/go-diskfs v1.7.0/go.mod h1:LhQyXqOugWFRahYUSw47NyZJPezFzB9UELwhpszLP/k= github.com/distribution/distribution/v3 v3.1.1 h1:KUbk7C8CfaLXy8kbf/hGq9cad/wCoLB6dbWH6DMbmX0= github.com/distribution/distribution/v3 v3.1.1/go.mod h1:d7lXwZpph0bVcOj4Aqn0nMrWHIwRQGdiV5TLeI+/w6Y= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= +github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU= @@ -321,13 +407,12 @@ github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj6 github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84= -github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/elliotchance/phpserialize v1.4.0 h1:cAp/9+KSnEbUC8oYCE32n2n84BeW8HOY3HMDI8hG2OY= github.com/elliotchance/phpserialize v1.4.0/go.mod h1:gt7XX9+ETUcLXbtTKEuyrqW3lcLUAeS/AnGZ2e49TZs= +github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY= +github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw= github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -341,10 +426,20 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= +github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/erofs/go-erofs v0.3.0 h1:o/W5ABAA3sHYl97WL93dacKEfeDpJhdFf3c2snAti7I= +github.com/erofs/go-erofs v0.3.0/go.mod h1:XkSeN9MHszGd4+3gcEjadJLYHCQpWzJ7/8yznzMuzJs= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= @@ -382,6 +477,10 @@ github.com/github/go-spdx/v2 v2.4.0 h1:+4IwVwJJbm3rzvrQ6P1nI9BDMcy3la4RchRy5uehV github.com/github/go-spdx/v2 v2.4.0/go.mod h1:/5rwgS0txhGtRdUZwc02bTglzg6HK3FfuEbECKlK2Sg= github.com/gitleaks/go-gitdiff v0.9.1 h1:ni6z6/3i9ODT685OLCTf+s/ERlWUNWQF4x1pvoNICw0= github.com/gitleaks/go-gitdiff v0.9.1/go.mod h1:pKz0X4YzCKZs30BL+weqBIG7mx0jl4tF1uXV9ZyNvrA= +github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= +github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= +github.com/gkampitakis/go-snaps v0.5.20 h1:FGKonEeQPJ12t7RQj6cTPa881fl5c8HYarMLv5vP7sg= +github.com/gkampitakis/go-snaps v0.5.20/go.mod h1:gC3YqxQTPyIXvQrw/Vpt3a8VqR1MO8sVpZFWN4DGwNs= github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4= github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= @@ -401,13 +500,15 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -435,6 +536,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= @@ -443,6 +546,8 @@ github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxUW+NltUg= +github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -481,10 +586,8 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= -github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomarkdown/markdown v0.0.0-20260417124207-7d523f7318df h1:Mwihr/o+v4L5h56rwHLOE20+hh7Okhwno5BHz3zDuao= -github.com/gomarkdown/markdown v0.0.0-20260417124207-7d523f7318df/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/gomarkdown/markdown v0.0.0-20260724235538-61af6e1e6971 h1:Qoqh9ZuBuqoeWZSyTfv+n1lezKuAyMFMQzOewVvFFTo= +github.com/gomarkdown/markdown v0.0.0-20260724235538-61af6e1e6971/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= @@ -512,10 +615,13 @@ github.com/google/jsonschema-go v0.4.3 h1:/DBOLZTfDow7pe2GmaJNhltueGTtDKICi8V8p+ github.com/google/jsonschema-go v0.4.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs= github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -535,13 +641,19 @@ github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0Z github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= +github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= +github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0= github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= @@ -560,12 +672,16 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/gpustack/gguf-parser-go v0.24.0 h1:tdJceXYp9e5RhE9RwVYIuUpir72Jz2D68NEtDXkKCKc= +github.com/gpustack/gguf-parser-go v0.24.0/go.mod h1:y4TwTtDqFWTK+xvprOjRUh+dowgU2TKCX37vRKvGiZ0= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -573,7 +689,10 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.8.6 h1:9sQboWULaydVphxc4S64oAI4YqpuCk7nPmvbk131ebY= +github.com/hashicorp/go-getter v1.8.6/go.mod h1:nVH12eOV2P58dIiL3rsU6Fh3wLeJEKBOJzhMmzlSWoo= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -592,6 +711,8 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= @@ -610,6 +731,8 @@ github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/henvic/httpretty v0.1.4 h1:Jo7uwIRWVFxkqOnErcoYfH90o3ddQyVrSANeS4cxYmU= +github.com/henvic/httpretty v0.1.4/go.mod h1:Dn60sQTZfbt2dYsdUSNsCljyF4AfdqnuJFDLJA1I4AM= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -659,15 +782,13 @@ github.com/kevinburke/ssh_config v1.6.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7Dmvb github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= -github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= +github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/knqyf263/go-rpmdb v0.1.1 h1:oh68mTCvp1XzxdU7EfafcWzzfstUZAEa3MW0IJye584= -github.com/knqyf263/go-rpmdb v0.1.1/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -688,19 +809,19 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= -github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasjones/reggen v0.0.0-20200904144131-37ba4fa293bb h1:w1g9wNDIE/pHSTmAaUhv4TZQuPBS6GV3mMz5hkgziIU= github.com/lucasjones/reggen v0.0.0-20200904144131-37ba4fa293bb/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= -github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= +github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -718,19 +839,25 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 h1:P8UmIzZMYDR+NGImiFvErt6VWfIRPuGM+vyjiEdkmIw= github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0= +github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mholt/archives v0.1.5 h1:Fh2hl1j7VEhc6DZs2DLMgiBNChUux154a1G+2esNvzQ= +github.com/mholt/archives v0.1.5/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0= +github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc= +github.com/minio/minlz v1.0.1 h1:OUZUzXcib8diiX+JYxyRLIdomyZYzHct6EShOKtQY2A= +github.com/minio/minlz v1.0.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -739,19 +866,19 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= -github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.5.1-0.20220423092549-19e70c243037 h1:HFfFxOGn95p7f1McxDK/LbYRMTjNKiDEOMgUIzMSXdU= -github.com/mitchellh/mapstructure v1.5.1-0.20220423092549-19e70c243037/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg= +github.com/moby/moby/api v1.54.2/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= +github.com/moby/moby/client v0.4.1 h1:DMQgisVoMkmMs7fp3ROSdiBnoAu8+vo3GggFl06M/wY= +github.com/moby/moby/client v0.4.1/go.mod h1:z52C9O2POPOsnxZAy//WtKcQ32P+jT/NGeXu/7nfjGQ= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -791,10 +918,20 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= -github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 h1:kpt9ZfKcm+EDG4s40hMwE//d5SBgDjUOrITReV2u4aA= +github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1/go.mod h1:qgCw4bBKZX8qMgGeEZzGFVT3notl42dBjNqO2jut0M0= +github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= +github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= +github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A= +github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= +github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= +github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= +github.com/olekukonko/errors v1.2.0 h1:10Zcn4GeV59t/EGqJc8fUjtFT/FuUh5bTMzZ1XwmCRo= +github.com/olekukonko/errors v1.2.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.1.6 h1:lGVTHO+Qc4Qm+fce/2h2m5y9LvqaW+DCN7xW9hsU3uA= +github.com/olekukonko/ll v0.1.6/go.mod h1:NVUmjBb/aCtUpjKk75BhWrOlARz3dqsM+OtszpY4o88= +github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVWj1drm6I= +github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY= github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= @@ -803,10 +940,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= -github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= -github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s= +github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= +github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -832,6 +967,10 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE= +github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -883,9 +1022,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c h1:8gOLsYwaY2JwlTMT4brS5/9XJdrdIbmk2obvQ748CC0= github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c/go.mod h1:kwM/7r/rVluTE8qJbHAffduuqmSv4knVQT2IajGvSiA= +github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/saferwall/pe v1.5.6 h1:DrRLnoQFxHWJ5lJUmrH7X2L0xeUu6SUS95Dc61eW2Yc= -github.com/saferwall/pe v1.5.6/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= @@ -904,8 +1042,6 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= -github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d h1:RQqyEogx5J6wPdoxqL132b100j8KjcVHO1c0KLRoIhc= -github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d/go.mod h1:PegD7EVqlN88z7TpCqH92hHP+GBpfomGCCnw1PFtNOA= github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc= github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg= github.com/segmentio/encoding v0.5.4 h1:OW1VRern8Nw6ITAtwSZ7Idrl3MXCFwXHPgqESYfvNt0= @@ -927,6 +1063,10 @@ github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28Jjd github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= github.com/slack-go/slack v0.23.1 h1:ZS5B96wxxYQRwvJ3/vJFtqtUZi3tXhsZCyT44Nv7M80= github.com/slack-go/slack v0.23.1/go.mod h1:H0yR/YBuRJ39RkE+JpV/d/oEsbanzTRowR82bCN0cEs= +github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d h1:3VwvTjiRPA7cqtgOWddEL+JrcijMlXUmj99c/6YyZoY= +github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d/go.mod h1:tAG61zBM1DYRaGIPloumExGvScf08oHuo0kFoOqdbT0= +github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik= +github.com/sorairolake/lzip-go v0.3.8/go.mod h1:JcBqGMV0frlxwrsE9sMWXDjqn3EeVf0/54YPsw66qkU= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -952,6 +1092,8 @@ github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3A github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/spiffe/go-spiffe/v2 v2.7.0 h1:uXe1MflJoHw58wAUvxVlcM7WpKtijWG7I1UidcGh6g4= +github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -980,6 +1122,14 @@ github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slH github.com/terminalstatic/go-xsd-validate v0.1.6/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -1045,12 +1195,16 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 h1:dkBzNEAIKADEaFnuESzcXvpd09vxvDZsOjx11gjUqLk= go.opentelemetry.io/contrib/bridges/prometheus v0.67.0/go.mod h1:Z5RIwRkZgauOIfnG5IpidvLpERjhTninpP1dTG2jTl4= +go.opentelemetry.io/contrib/detectors/gcp v1.44.0 h1:NmLfL734pJhM0JKaYd2Y28+nY9dPRWYAAbxhRCrKXPw= +go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s= go.opentelemetry.io/contrib/exporters/autoexport v0.67.0 h1:4fnRcNpc6YFtG3zsFw9achKn3XgmxPxuMuqIL5rE8e8= go.opentelemetry.io/contrib/exporters/autoexport v0.67.0/go.mod h1:qTvIHMFKoxW7HXg02gm6/Wofhq5p3Ib/A/NNt1EoBSQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0 h1:deI9UQMoGFgrg5iLPgzueqFPHevDl+28YKfSpPTI6rY= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0/go.mod h1:PFx9NgpNUKXdf7J4Q3agRxMs3Y07QhTCVipKmLsMKnU= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= @@ -1061,8 +1215,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0 h1:zWWrB1U6nqhS/k6zYB74CjRpuiitRtLLi68VcgmOEto= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0/go.mod h1:2qXPNBX1OVRC0IwOnfo1ljoid+RD0QK3443EaqVlsOU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= go.opentelemetry.io/otel/exporters/prometheus v0.64.0 h1:g0LRDXMX/G1SEZtK8zl8Chm4K6GBwRkjPKE36LxiTYs= @@ -1075,16 +1229,18 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0 h1:s/1iRkCKDfhlh1J go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0/go.mod h1:UI3wi0FXg1Pofb8ZBiBLhtMzgoTm1TYkMvn71fAqDzs= go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/metric/x v0.67.0 h1:PcicCNZFkZ4bXfSooXdo3WN7RBOVOtjVdo1wD358Uns= +go.opentelemetry.io/otel/metric/x v0.67.0/go.mod h1:FBjCWZe6wgcqxcMtjdGiClDKXb2YxxXii0CXftE4QtI= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= @@ -1099,6 +1255,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= +go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -1113,8 +1271,8 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= -golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= +golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54= +golang.org/x/crypto v0.58.0/go.mod h1:Xh+kl5A+M0gMiWDytH2Hhr5Z7WbNCpv/eB/EFgfSk+w= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1234,8 +1392,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= -golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= +golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA= +golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1303,20 +1461,20 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= -golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= +golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= +golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE= -golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc= +golang.org/x/term v0.47.0 h1:cpyOwQkr2Nzxe2p6KnrTG7Ei2wtzjsuSjhpXXepZ/BM= +golang.org/x/term v0.47.0/go.mod h1:efAfAuG6RKABvg1ArGebRkvX6LXul14SM67o2e4mUCY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1327,8 +1485,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= -golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= +golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc= +golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1389,8 +1547,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= -golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= +golang.org/x/tools v0.51.0 h1:k4Xc/1Om9jwkBJBo4NVLMSARBoWtK10mx+W5BnXCeAI= +golang.org/x/tools v0.51.0/go.mod h1:9eEncMayCV6zRMGhR5eZEC2iBx98qWcF1HZ9Z7wJOoA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1431,6 +1589,8 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= +google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= +google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1580,8 +1740,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= helm.sh/helm/v3 v3.20.2 h1:binM4rvPx5DcNsa1sIt7UZi55lRbu3pZUFmQkSoRh48= helm.sh/helm/v3 v3.20.2/go.mod h1:Fl1kBaWCpkUrM6IYXPjQ3bdZQfFrogKArqptvueZ6Ww= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1591,20 +1751,20 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80= -k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34= +k8s.io/api v0.36.3 h1:NxB+05W2UGqXWFXcLO0RB5cnqnUPP5v5sVlaOH0Iz4w= +k8s.io/api v0.36.3/go.mod h1:JzLQKqRHC5+I8RVj/lS3lCg0mg6nWI9Fo/Sk3ElxHzg= k8s.io/apiextensions-apiserver v0.35.1 h1:p5vvALkknlOcAqARwjS20kJffgzHqwyQRM8vHLwgU7w= k8s.io/apiextensions-apiserver v0.35.1/go.mod h1:2CN4fe1GZ3HMe4wBr25qXyJnJyZaquy4nNlNmb3R7AQ= -k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ= -k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc= +k8s.io/apimachinery v0.36.3 h1:PkzMRBRG8joFD8EhCuQAtNPvJlxb82FwplP26HIzvAM= +k8s.io/apimachinery v0.36.3/go.mod h1:cTSjBWgPe/6CQyBKzY/hDIRWCQQQeK0mfLbml0UYFHE= k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs= k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4= k8s.io/cli-runtime v0.36.0 h1:HNxciQpQMMOKS0/GiUXcKDyA6J2FDILJj9NmP2BZrTg= k8s.io/cli-runtime v0.36.0/go.mod h1:KObkknK9Ro5LYX+1RdiKc7C8CvGg4aX+V/Zv+E8WPHA= -k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= -k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y= -k8s.io/component-base v0.36.0 h1:hFjEktssxiJhrK1zfybkH4kJOi8iZuF+mIDCqS5+jRo= -k8s.io/component-base v0.36.0/go.mod h1:JZvIfcNHk+uck+8LhJzhSBtydWXaZNQwX2OdL+Mnwsk= +k8s.io/client-go v0.36.3 h1:M4JdVzXxYcZk4fGpfDdYnxSwhLKWCFoQsHW6t+z8Hfg= +k8s.io/client-go v0.36.3/go.mod h1:gcPwr0c87vjjG6HB6pWEqOeuYVoXSsREjzux2j6GF30= +k8s.io/component-base v0.36.3 h1:vc/UFvPCkW0irPz84LAodAL1j3f4xktPM6dDJIEheAY= +k8s.io/component-base v0.36.3/go.mod h1:hZbNFG+gCMl9EbykDGEu73feKP9/Cq6JsV4pTo9GTO8= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 h1:Sztf7ESG9tAXRW/ACJZjrj5jhdOUqS2KFRQT+CTvu78= @@ -1643,6 +1803,8 @@ modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= oras.land/oras-go/v2 v2.6.2 h1:N04RXngAp1LJKTG6ifz3xHPipasEkWr+hFmInja5YKo= oras.land/oras-go/v2 v2.6.2/go.mod h1:PlTtg4JTDJkDe8yVHpM2wz7/YDc00GVas+i4jAW2TZ4= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= @@ -1654,7 +1816,7 @@ sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7 sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= -sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.3 h1:u08YRbVUi59ri4YD6cg0UqNM4Dimn0sIl+wldcx5PYw= +sigs.k8s.io/structured-merge-diff/v6 v6.3.3/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/internal/commands/agenthooks/cx/hooks.go b/internal/commands/agenthooks/cx/hooks.go index 12b043c2e..9fb7e3317 100644 --- a/internal/commands/agenthooks/cx/hooks.go +++ b/internal/commands/agenthooks/cx/hooks.go @@ -11,7 +11,9 @@ import ( "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails" "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails/asca" "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails/kics" + "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails/secrets" "github.com/checkmarx/ast-cli/internal/commands/agenthooks/sca" + "github.com/checkmarx/ast-cli/internal/commands/agenthooks/scannerconfig" "github.com/checkmarx/ast-cli/internal/commands/agenthooks/sessiontally" "github.com/checkmarx/ast-cli/internal/wrappers" ) @@ -19,9 +21,10 @@ import ( // canonical per-engine labels for the session summary (normalizes the legacy SCA/Oss split used by // the per-event remediation telemetry; ASCA already uses "Asca"). const ( - engineAsca = "Asca" - engineSca = "Sca" - engineKics = "Kics" + engineAsca = "Asca" + engineSca = "Sca" + engineKics = "Kics" + engineSecrets = "Secrets" ) // scaScanner is the package-level SCA scanner used by the guardrail handlers. @@ -33,6 +36,21 @@ var scaScanner *sca.Scanner // It is set by RegisterGuardrails and cleared by RegisterPassThrough. var kicsScanner *kics.Scanner +// bindThreshold points each guardrail's finding filter at the severity threshold for this event's +// agent, so findings below cx_severity_threshold are left out of a deny and the agent is not told to +// fix them. Agents the switches do not apply to keep every finding. +func bindThreshold(agent agenthooks.AgentID) { + below := func(severity string) bool { return belowThreshold(agent, severity) } + secrets.BelowThreshold = below + asca.BelowThreshold = below + kics.BelowThreshold = below + sca.BelowThreshold = below +} + +// secretsScanner is the package-level secret-detection scanner used by the file-edit guardrail. +// It is set by RegisterGuardrails and cleared by RegisterPassThrough. +var secretsScanner *secrets.Scanner + var telemetryWrapper wrappers.TelemetryWrapper func cxWhenAgentIdle(_ agenthooks.AgentIdleEvent) agenthooks.IdleVerdict { @@ -53,6 +71,7 @@ func sessionIDFromToolCall(ev *agenthooks.ToolCallEvent) string { // cxBeforeToolCall gates shell execution against the organization's blacklist, // tool rules, and the SCA guardrail (malicious / vulnerable package installs). func cxBeforeToolCall(ev agenthooks.ToolCallEvent) agenthooks.ToolVerdict { + bindThreshold(ev.Agent) if !ev.IsShell() { return agenthooks.Allow() } @@ -63,10 +82,10 @@ func cxBeforeToolCall(ev agenthooks.ToolCallEvent) agenthooks.ToolVerdict { } return agenthooks.Deny(reason) } - if scaScanner != nil { + if scaScanner != nil && scannerOn(ev.Agent, scannerconfig.SCA) { agent := agentToString(ev.Agent) sid := sessionIDFromToolCall(&ev) - if finding, remediation, severity := scaScanner.CheckBashInstall(ev.Command, ev.WorkDir, agent, sid); finding != "" { + if finding, remediation, severity := scaScanner.CheckBashInstall(ev.Command, ev.WorkDir, agent, sid); finding != "" && !belowThreshold(ev.Agent, severity) { sessiontally.Add(sid, engineSca, 1, 1) logRemediationTelemetry(agent, "SCA", severity, sid) return agenthooks.DenyWithContext(finding, remediation) @@ -81,10 +100,11 @@ func cxBeforeToolCall(ev agenthooks.ToolCallEvent) agenthooks.ToolVerdict { // 1. File EDITS (Claude / Windsurf / Droid / Gemini) — ev.Changes is populated. // Enforce blast_radius_limit, files_limits.max_total_file_size_kb, the ASCA // guardrail (AI-introduced code vulnerabilities), the KICS guardrail -// (IaC security vulnerabilities), and the SCA guardrail -// (malicious / vulnerable manifest additions) before any bytes are written -// to disk. MultiEdit and multi-file edits are handled uniformly by iterating -// ev.Changes. +// (IaC security vulnerabilities), the SCA guardrail +// (malicious / vulnerable manifest additions), and the secret-detection +// guardrail (hardcoded credentials introduced by the edit) before any bytes +// are written to disk. MultiEdit and multi-file edits are handled uniformly +// by iterating ev.Changes. // // 2. Cursor file READS (beforeReadFile) — ev.Changes is empty and ev.FilePath // points to a file the agent is about to ingest into the LLM context. @@ -93,6 +113,7 @@ func cxBeforeToolCall(ev agenthooks.ToolCallEvent) agenthooks.ToolVerdict { // or if the file exceeds the policy size cap. Reads do NOT count toward // the blast-radius budget (that limit is about writes). func cxBeforeFileEdit(ev agenthooks.FileEditEvent) agenthooks.FileEditVerdict { + bindThreshold(ev.Agent) if ev.Agent == agenthooks.AgentCursor && len(ev.Changes) == 0 { if reason := guardrails.ScanFileForSecrets(ev.FilePath); reason != "" { return agenthooks.RejectEdit(reason) @@ -111,30 +132,44 @@ func cxBeforeFileEdit(ev agenthooks.FileEditEvent) agenthooks.FileEditVerdict { return agenthooks.RejectEdit(reason) } agent := agentToString(ev.Agent) - if blocked, reason, context, severity := asca.ScanFileEdit(&ev, telemetryWrapper, agent); blocked { - sessiontally.Add(ev.SessionID, engineAsca, 1, 1) - logRemediationTelemetry(agent, "Asca", severity, ev.SessionID) - return agenthooks.RejectEditWithContext(reason, context) + // Each engine below is skipped (not just its verdict ignored) when the developer switched it off in + // ~/.checkmarx/cx-onboarding.properties; an unreadable config leaves every engine on. + // cx_severity_threshold (same file): a deny whose highest severity is below the threshold is let + // through for ASCA, KICS, SCA and secrets. Malicious packages and an unknown severity + // are never relaxed. A blank or invalid threshold means low (nothing filtered). + if scannerOn(ev.Agent, scannerconfig.ASCA) { + if blocked, reason, context, severity := asca.ScanFileEdit(&ev, telemetryWrapper, agent); blocked && !belowThreshold(ev.Agent, severity) { + sessiontally.Add(ev.SessionID, engineAsca, 1, 1) + logRemediationTelemetry(agent, "Asca", severity, ev.SessionID) + return agenthooks.RejectEditWithContext(reason, context) + } } var kicsNote string - if kicsScanner != nil { + if kicsScanner != nil && scannerOn(ev.Agent, scannerconfig.KICS) { blocked, reason, context, note, severity := kics.ScanFileEdit(&ev, kicsScanner, telemetryWrapper, agent) - if blocked { + if blocked && !belowThreshold(ev.Agent, severity) { sessiontally.Add(ev.SessionID, engineKics, 1, 1) logRemediationTelemetry(agent, "IaC", severity, ev.SessionID) return agenthooks.RejectEditWithContext(reason, context) } kicsNote = note } - if scaScanner != nil { + if scaScanner != nil && scannerOn(ev.Agent, scannerconfig.SCA) { for _, diff := range ev.Changes { - if finding, remediation, severity := scaScanner.CheckManifestEdit(ev.FilePath, fullAfterContent(ev.FilePath, diff), ev.WorkDir, agent, ev.SessionID); finding != "" { + if finding, remediation, severity := scaScanner.CheckManifestEdit(ev.FilePath, fullAfterContent(ev.FilePath, diff), ev.WorkDir, agent, ev.SessionID); finding != "" && !belowThreshold(ev.Agent, severity) { sessiontally.Add(ev.SessionID, engineSca, 1, 1) logRemediationTelemetry(agent, "Oss", severity, ev.SessionID) return agenthooks.RejectEditWithContext(finding, remediation) } } } + if secretsScanner != nil && secretsApply(ev.Agent) && scannerOn(ev.Agent, scannerconfig.Secrets) { + if blocked, reason, context, severity := secrets.ScanFileEdit(&ev, secretsScanner, telemetryWrapper, agent); blocked && !belowThreshold(ev.Agent, severity) { + sessiontally.Add(ev.SessionID, engineSecrets, 1, 1) + logRemediationTelemetry(agent, "Secrets", severity, ev.SessionID) + return agenthooks.RejectEditWithContext(reason, context) + } + } // A note on an ALLOW, deliberately: blocking every IaC edit because a // container engine is down would be worse than an unscanned edit. if kicsNote != "" { @@ -223,10 +258,11 @@ func promptWorkspaceRoots(raw any) []string { } // RegisterGuardrails wires the four guardrail handlers and instantiates the -// SCA and KICS scanners used by the Bash and FileEdit handlers. +// SCA, KICS, and secret-detection scanners used by the Bash and FileEdit handlers. func RegisterGuardrails(jwt wrappers.JWTWrapper, ff wrappers.FeatureFlagsWrapper, rt wrappers.RealtimeScannerWrapper, tel wrappers.TelemetryWrapper) { scaScanner = sca.NewScanner(jwt, ff, rt) kicsScanner = kics.NewScanner(jwt, ff) + secretsScanner = secrets.NewScanner(jwt, ff) telemetryWrapper = tel agenthooks.WhenAgentIdle(cxWhenAgentIdle) agenthooks.BeforeToolCall(cxBeforeToolCall) @@ -239,6 +275,7 @@ func RegisterGuardrails(jwt wrappers.JWTWrapper, ff wrappers.FeatureFlagsWrapper func RegisterPassThrough() { scaScanner = nil kicsScanner = nil + secretsScanner = nil agenthooks.WhenAgentIdle(func(_ agenthooks.AgentIdleEvent) agenthooks.IdleVerdict { return agenthooks.Resume() }) agenthooks.BeforeToolCall(func(_ agenthooks.ToolCallEvent) agenthooks.ToolVerdict { return agenthooks.Allow() }) agenthooks.BeforeFileEdit(func(_ agenthooks.FileEditEvent) agenthooks.FileEditVerdict { return agenthooks.AcceptEdit() }) @@ -268,6 +305,36 @@ func logRemediationTelemetry(agent, engine, severity, sessionID string) { } } +// switchesApply reports whether the ~/.checkmarx/cx-onboarding.properties scanner switches and severity +// threshold are honoured for this agent. Claude, Cursor, Gemini and Codex are excluded for now: they keep +// scanning with ASCA / KICS / SCA and blocking at any severity even when the shared file exists on the +// machine. Every other agent (GitHub Copilot, Droid, Windsurf, ...) honours it. Add an agent to +// the case list below to hold it back, or remove one to roll the feature out to it. +func switchesApply(agent agenthooks.AgentID) bool { + switch agent { + case agenthooks.AgentClaude, agenthooks.AgentCursor, agenthooks.AgentGemini, agenthooks.AgentCodex: + return false + } + return true +} + +// secretsApply reports whether the secret-detection guardrail runs for this agent. Claude, Cursor, Gemini +// and Codex skip it entirely and keep the ASCA / KICS / SCA guardrails; every other agent runs it. It +// shares switchesApply's agent list so the two cannot drift apart. +func secretsApply(agent agenthooks.AgentID) bool { + return switchesApply(agent) +} + +// scannerOn is scannerconfig.Enabled, limited to the agents the switches apply to. +func scannerOn(agent agenthooks.AgentID, s scannerconfig.Scanner) bool { + return !switchesApply(agent) || scannerconfig.Enabled(s) +} + +// belowThreshold is scannerconfig.BelowThreshold, limited to the agents the switches apply to. +func belowThreshold(agent agenthooks.AgentID, severity string) bool { + return switchesApply(agent) && scannerconfig.BelowThreshold(severity) +} + // agentToString converts agenthooks.AgentID enum to string representation for telemetry. func agentToString(agent agenthooks.AgentID) string { switch agent { diff --git a/internal/commands/agenthooks/cx/hooks_test.go b/internal/commands/agenthooks/cx/hooks_test.go index 36763db70..a70eeb8c1 100644 --- a/internal/commands/agenthooks/cx/hooks_test.go +++ b/internal/commands/agenthooks/cx/hooks_test.go @@ -19,10 +19,12 @@ import ( "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails" "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails/kics" + "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails/secrets" "github.com/checkmarx/ast-cli/internal/commands/agenthooks/sca" "github.com/checkmarx/ast-cli/internal/services/realtimeengine" "github.com/checkmarx/ast-cli/internal/services/realtimeengine/iacrealtime" "github.com/checkmarx/ast-cli/internal/services/realtimeengine/ossrealtime" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/secretsrealtime" "github.com/checkmarx/ast-cli/internal/wrappers" "github.com/Checkmarx/ast-cx-hooks/cursor" @@ -53,16 +55,18 @@ func (r *recordingTelemetry) SendAIDataToLog(data *wrappers.DataForAITelemetry) func resetHookGlobals(t *testing.T) { t.Helper() - prevSCA, prevKICS, prevTel := scaScanner, kicsScanner, telemetryWrapper + prevSCA, prevKICS, prevSecrets, prevTel := scaScanner, kicsScanner, secretsScanner, telemetryWrapper t.Cleanup(func() { scaScanner = prevSCA kicsScanner = prevKICS + secretsScanner = prevSecrets telemetryWrapper = prevTel guardrails.ResetBlastRadiusCount() guardrails.ResetTotalFileSizeCount() }) scaScanner = nil kicsScanner = nil + secretsScanner = nil telemetryWrapper = nil guardrails.ResetBlastRadiusCount() guardrails.ResetTotalFileSizeCount() @@ -415,6 +419,51 @@ func TestCxBeforeFileEdit_SCAManifest_RejectsWithContext(t *testing.T) { } } +func TestCxBeforeFileEdit_SecretsFinding_RejectsWithContext(t *testing.T) { + resetHookGlobals(t) + const secret = "ghp_hook_test_secret_value" + tel := &recordingTelemetry{} + telemetryWrapper = tel + secretsScanner = secrets.NewScannerWithFunc(func(_, content, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + if strings.Contains(content, secret) { + return []secretsrealtime.SecretsRealtimeResult{{ + Title: "github-pat", + Description: "GitHub personal access token", + SecretValue: secret, + Severity: "Critical", + Locations: []realtimeengine.Location{{Line: 1}}, + }}, nil + } + return nil, nil + }) + + v := cxBeforeFileEdit(agenthooks.FileEditEvent{ + Agent: agenthooks.AgentCopilotCLI, + SessionID: "sec-sess", + FilePath: "config.env", + WorkDir: t.TempDir(), + Changes: []agenthooks.FileDiff{{Before: "", After: "TOKEN=" + secret}}, + }) + if v.Permit { + t.Fatal("secret finding should RejectEdit") + } + if strings.Contains(v.Message, secret) || strings.Contains(v.Context, secret) { + t.Fatal("verdict leaked the secret value") + } + if !strings.Contains(v.Context, "cx-devassist:cx-devassist-secrets") { + t.Errorf("expected Copilot skill in context, got %q", v.Context) + } + if len(tel.calls) != 2 { + t.Fatalf("expected 2 telemetry calls (detect + remediate), got %d", len(tel.calls)) + } + if tel.calls[0].Type != "hooks-detect" || tel.calls[0].Engine != engineSecrets { + t.Errorf("detect telemetry = Type %q Engine %q", tel.calls[0].Type, tel.calls[0].Engine) + } + if tel.calls[1].Type != telemetryTypeHooksRemediate || tel.calls[1].Engine != "Secrets" { + t.Errorf("remediate telemetry = Type %q Engine %q", tel.calls[1].Type, tel.calls[1].Engine) + } +} + func TestCxBeforeFileEdit_CleanEdit_Accepts(t *testing.T) { resetHookGlobals(t) v := cxBeforeFileEdit(agenthooks.FileEditEvent{ @@ -555,6 +604,9 @@ func TestRegisterGuardrails_AndPassThrough(t *testing.T) { if kicsScanner == nil { t.Fatal("RegisterGuardrails should set kicsScanner") } + if secretsScanner == nil { + t.Fatal("RegisterGuardrails should set secretsScanner") + } if telemetryWrapper == nil { t.Fatal("RegisterGuardrails should set telemetryWrapper") } @@ -566,6 +618,9 @@ func TestRegisterGuardrails_AndPassThrough(t *testing.T) { if kicsScanner != nil { t.Fatal("RegisterPassThrough should clear kicsScanner") } + if secretsScanner != nil { + t.Fatal("RegisterPassThrough should clear secretsScanner") + } } func TestLogRemediationTelemetry(t *testing.T) { @@ -746,10 +801,11 @@ func TestCxBeforeFileEdit_CursorRead_NoSecrets_Accepts(t *testing.T) { func TestCxBeforeFileEdit_UnsupportedFileType_Accepts(t *testing.T) { setEmptyHomeDir(t) - prevSca, prevKics := scaScanner, kicsScanner - defer func() { scaScanner, kicsScanner = prevSca, prevKics }() + prevSca, prevKics, prevSecrets := scaScanner, kicsScanner, secretsScanner + defer func() { scaScanner, kicsScanner, secretsScanner = prevSca, prevKics, prevSecrets }() scaScanner = nil kicsScanner = nil + secretsScanner = nil path := filepath.Join(t.TempDir(), "notes.txt") ev := agenthooks.FileEditEvent{ @@ -769,20 +825,23 @@ func TestCxBeforePrompt_Benign_Accepts(t *testing.T) { } func TestRegisterGuardrails_SetsScanners(t *testing.T) { - prevSca, prevKics, prevTelemetry := scaScanner, kicsScanner, telemetryWrapper - defer func() { scaScanner, kicsScanner, telemetryWrapper = prevSca, prevKics, prevTelemetry }() + prevSca, prevKics, prevSecrets, prevTelemetry := scaScanner, kicsScanner, secretsScanner, telemetryWrapper + defer func() { + scaScanner, kicsScanner, secretsScanner, telemetryWrapper = prevSca, prevKics, prevSecrets, prevTelemetry + }() telemetry := mock.TelemetryMockWrapper{} RegisterGuardrails(&mock.JWTMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, &mock.RealtimeScannerMockWrapper{}, telemetry) assert.NotNil(t, scaScanner) assert.NotNil(t, kicsScanner) + assert.NotNil(t, secretsScanner) assert.Equal(t, telemetry, telemetryWrapper) } func TestRegisterPassThrough_ClearsScanners(t *testing.T) { - prevSca, prevKics := scaScanner, kicsScanner - defer func() { scaScanner, kicsScanner = prevSca, prevKics }() + prevSca, prevKics, prevSecrets := scaScanner, kicsScanner, secretsScanner + defer func() { scaScanner, kicsScanner, secretsScanner = prevSca, prevKics, prevSecrets }() RegisterGuardrails(&mock.JWTMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, &mock.RealtimeScannerMockWrapper{}, mock.TelemetryMockWrapper{}) assert.NotNil(t, scaScanner) @@ -790,6 +849,7 @@ func TestRegisterPassThrough_ClearsScanners(t *testing.T) { RegisterPassThrough() assert.Nil(t, scaScanner) assert.Nil(t, kicsScanner) + assert.Nil(t, secretsScanner) } func TestLogRemediationTelemetry_NilWrapper_NoOp(t *testing.T) { @@ -873,6 +933,7 @@ func TestCodexApplyPatch_KICSFinding_DeniesEndToEnd(t *testing.T) { }}, nil }) scaScanner = nil + secretsScanner = nil patch := "*** Begin Patch\n" + "*** Add File: main.tf\n" + diff --git a/internal/commands/agenthooks/cx/scanner_switch_test.go b/internal/commands/agenthooks/cx/scanner_switch_test.go new file mode 100644 index 000000000..81d105028 --- /dev/null +++ b/internal/commands/agenthooks/cx/scanner_switch_test.go @@ -0,0 +1,243 @@ +//go:build !integration + +package cx + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" + + agenthooks "github.com/Checkmarx/ast-cx-hooks" + + "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails/kics" + "github.com/checkmarx/ast-cli/internal/commands/agenthooks/guardrails/secrets" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/iacrealtime" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/secretsrealtime" +) + +// useScannerConfig points the user's home at a temp dir holding ~/.checkmarx/cx-onboarding.properties +// with the given body (no file at all when body is empty). +func useScannerConfig(t *testing.T, body string) { + t.Helper() + dir := t.TempDir() + restore := setHomeDir(dir) + t.Cleanup(restore) + if body == "" { + return + } + cxDir := filepath.Join(dir, ".checkmarx") + if err := os.MkdirAll(cxDir, 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(cxDir, "cx-onboarding.properties"), []byte(body), 0o600); err != nil { + t.Fatal(err) + } +} + +func secretsEdit(secret string, agent agenthooks.AgentID) agenthooks.FileEditEvent { + return agenthooks.FileEditEvent{ + Agent: agent, + SessionID: "switch-sess", + FilePath: "config.env", + WorkDir: "", + Changes: []agenthooks.FileDiff{{Before: "", After: "TOKEN=" + secret}}, + } +} + +func stubSecretsScanner(secret string) *secrets.Scanner { + return secrets.NewScannerWithFunc(func(_, content, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + if strings.Contains(content, secret) { + return []secretsrealtime.SecretsRealtimeResult{{ + Title: "github-pat", Description: "token", SecretValue: secret, Severity: "Critical", + Locations: []realtimeengine.Location{{Line: 1}}, + }}, nil + } + return nil, nil + }) +} + +func TestCxBeforeFileEdit_SecretsSwitch(t *testing.T) { + const secret = "ghp_switch_test_secret_value" + cases := []struct { + name string + config string + wantBlock bool + }{ + {"no config file is enabled", "", true}, + {"explicit true is enabled", "cx_secret_scanner_enabled=true\n", true}, + {"typo stays enabled", "cx_secret_scanner_enabled=flase\n", true}, + {"other scanner off does not affect secrets", "cx_asca_scanner_enabled=false\ncx_kics_scanner_enabled=false\n", true}, + {"secrets off is skipped", "cx_secret_scanner_enabled=false\n", false}, + {"secrets off (CRLF, caps)", "cx_secret_scanner_enabled=OFF\r\n", false}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + resetHookGlobals(t) + useScannerConfig(t, tc.config) + secretsScanner = stubSecretsScanner(secret) + v := cxBeforeFileEdit(secretsEdit(secret, agenthooks.AgentCopilotCLI)) + if v.Permit == tc.wantBlock { + t.Fatalf("Permit=%v, wantBlock=%v", v.Permit, tc.wantBlock) + } + }) + } +} + +func kicsFinding(severity string) *kics.Scanner { + return kics.NewScannerWithFunc(func(string, string) ([]iacrealtime.IacRealtimeResult, error) { + return []iacrealtime.IacRealtimeResult{{ + Title: "Privileged Container", SimilarityID: "sim1", Severity: severity, + Description: "Container runs as privileged", Locations: []realtimeengine.Location{{Line: 5}}, + }}, nil + }) +} + +func kicsEdit(agent agenthooks.AgentID) agenthooks.FileEditEvent { + return agenthooks.FileEditEvent{ + Agent: agent, SessionID: "thr-sess", FilePath: "/project/Dockerfile", + Changes: []agenthooks.FileDiff{{Before: "", After: "FROM ubuntu\nUSER root\n"}}, + } +} + +func TestCxBeforeFileEdit_SeverityThreshold(t *testing.T) { + cases := []struct { + name string + config string + severity string + wantBlock bool + }{ + {"no config blocks low", "", "LOW", true}, + {"blank threshold blocks low", "cx_severity_threshold=\n", "LOW", true}, + {"invalid threshold blocks low", "cx_severity_threshold=hihg\n", "LOW", true}, + {"high threshold lets low through", "cx_severity_threshold=high\n", "LOW", false}, + {"high threshold lets medium through", "cx_severity_threshold=high\n", "MEDIUM", false}, + {"high threshold blocks high", "cx_severity_threshold=high\n", "HIGH", true}, + {"high threshold blocks critical", "cx_severity_threshold=high\n", "CRITICAL", true}, + {"unknown severity is never relaxed", "cx_severity_threshold=critical\n", "", true}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + resetHookGlobals(t) + useScannerConfig(t, tc.config) + kicsScanner = kicsFinding(tc.severity) + if v := cxBeforeFileEdit(kicsEdit(agenthooks.AgentCopilotCLI)); v.Permit == tc.wantBlock { + t.Fatalf("Permit=%v, wantBlock=%v", v.Permit, tc.wantBlock) + } + }) + } +} + +func TestCxBeforeFileEdit_SeverityThreshold_Secrets(t *testing.T) { + const secret = "ghp_threshold_test_secret_value" + cases := []struct { + name string + config string + severity string + wantBlock bool + }{ + {"no config blocks low", "", "Low", true}, + {"high threshold lets medium through", "cx_severity_threshold=high\n", "Medium", false}, + {"high threshold blocks high", "cx_severity_threshold=high\n", "High", true}, + {"critical threshold lets low through", "cx_severity_threshold=critical\n", "Low", false}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + resetHookGlobals(t) + useScannerConfig(t, tc.config) + secretsScanner = secrets.NewScannerWithFunc(func(_, content, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + if strings.Contains(content, secret) { + return []secretsrealtime.SecretsRealtimeResult{{ + Title: "generic-key", Description: "key", SecretValue: secret, Severity: tc.severity, + Locations: []realtimeengine.Location{{Line: 1}}, + }}, nil + } + return nil, nil + }) + if v := cxBeforeFileEdit(secretsEdit(secret, agenthooks.AgentCopilotCLI)); v.Permit == tc.wantBlock { + t.Fatalf("Permit=%v, wantBlock=%v", v.Permit, tc.wantBlock) + } + }) + } +} + +func TestCxBeforeFileEdit_SeverityThreshold_SecretsMixed(t *testing.T) { + resetHookGlobals(t) + useScannerConfig(t, "cx_severity_threshold=high\n") + secretsScanner = secrets.NewScannerWithFunc(func(_, content, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + return []secretsrealtime.SecretsRealtimeResult{ + {Title: "high-rule", Description: "d", SecretValue: "hv", Severity: "High", Locations: []realtimeengine.Location{{Line: 1}}}, + {Title: "medium-rule", Description: "d", SecretValue: "mv", Severity: "Medium", Locations: []realtimeengine.Location{{Line: 2}}}, + }, nil + }) + v := cxBeforeFileEdit(secretsEdit("x", agenthooks.AgentCopilotCLI)) + if v.Permit { + t.Fatal("the high secret must block") + } + if blob := fmt.Sprintf("%+v", v); !strings.Contains(blob, "high-rule") || strings.Contains(blob, "medium-rule") { + t.Fatalf("deny must list the high finding and omit the medium one: %s", blob) + } +} + +// The switches and secret detection are features of every agent except Claude, Cursor, Gemini and Codex: those four skip secret +// detection and, with the shared properties file present, keeps ASCA/KICS/SCA blocking at any severity. +func TestSwitches_IgnoredForOtherAgents(t *testing.T) { + const secret = "ghp_other_agent_secret_value" + others := []agenthooks.AgentID{ + agenthooks.AgentClaude, agenthooks.AgentCursor, agenthooks.AgentGemini, agenthooks.AgentCodex, + } + for _, agent := range others { + t.Run(agentToString(agent)+"/secrets are skipped", func(t *testing.T) { + resetHookGlobals(t) + useScannerConfig(t, "") + secretsScanner = stubSecretsScanner(secret) + if v := cxBeforeFileEdit(secretsEdit(secret, agent)); !v.Permit { + t.Fatal("secret detection must not run for this agent") + } + }) + t.Run(agentToString(agent)+"/kics switch off still blocks", func(t *testing.T) { + resetHookGlobals(t) + useScannerConfig(t, "cx_kics_scanner_enabled=false\n") + kicsScanner = kicsFinding("HIGH") + if v := cxBeforeFileEdit(kicsEdit(agent)); v.Permit { + t.Fatal("kics switch must not apply to this agent") + } + }) + t.Run(agentToString(agent)+"/threshold does not relax", func(t *testing.T) { + resetHookGlobals(t) + useScannerConfig(t, "cx_severity_threshold=critical\n") + kicsScanner = kicsFinding("LOW") + if v := cxBeforeFileEdit(kicsEdit(agent)); v.Permit { + t.Fatal("severity threshold must not apply to this agent") + } + }) + } +} + +func TestSwitchesApply_ExcludesFourAgents(t *testing.T) { + for agent, want := range map[agenthooks.AgentID]bool{ + agenthooks.AgentCopilotCLI: true, agenthooks.AgentCopilot: true, + agenthooks.AgentDroid: true, agenthooks.AgentWindsurf: true, + agenthooks.AgentClaude: false, agenthooks.AgentCursor: false, agenthooks.AgentGemini: false, + agenthooks.AgentCodex: false, + } { + if got := switchesApply(agent); got != want { + t.Errorf("%s: got %v, want %v", agentToString(agent), got, want) + } + } +} + +func TestSecretsApply_ExcludesFourAgents(t *testing.T) { + for agent, want := range map[agenthooks.AgentID]bool{ + agenthooks.AgentCopilotCLI: true, agenthooks.AgentCopilot: true, + agenthooks.AgentDroid: true, agenthooks.AgentWindsurf: true, + agenthooks.AgentClaude: false, agenthooks.AgentCursor: false, + agenthooks.AgentGemini: false, agenthooks.AgentCodex: false, + } { + if got := secretsApply(agent); got != want { + t.Errorf("%s: got %v, want %v", agentToString(agent), got, want) + } + } +} diff --git a/internal/commands/agenthooks/guardrails/asca/asca.go b/internal/commands/agenthooks/guardrails/asca/asca.go index eed2bc7eb..09f10301f 100644 --- a/internal/commands/agenthooks/guardrails/asca/asca.go +++ b/internal/commands/agenthooks/guardrails/asca/asca.go @@ -28,6 +28,11 @@ func isSupportedByASCA(filePath string) bool { return ok } +// BelowThreshold is set by the hook dispatcher and reports whether a finding's severity is under the +// developer's cx_severity_threshold. Such findings are dropped from the deny, so the agent is never +// told to remediate them. Nil (the default) keeps every finding. +var BelowThreshold func(severity string) bool + // ScanFileEdit runs ASCA on the proposed post-edit content. // Returns blocked=true with a formatted reason, remediation context, and highest severity when ASCA // finds *new* vulnerabilities introduced by ev.Changes (delta-detection for edits; @@ -90,14 +95,16 @@ func ScanFileEdit(ev *agenthooks.FileEditEvent, telemetryWrapper wrappers.Teleme } // For new files (no original content), every finding is new - if originalContent == "" { - r, c := formatFindings(ev.FilePath, newResult.ScanDetails, ev.WorkDir, agent, ev.SessionID) - findingCount = len(newResult.ScanDetails) - return true, r, c, highestSeverity(newResult.ScanDetails) + newFindings := newResult.ScanDetails + if originalContent != "" { + var err error + newFindings, err = deltaFindings(ev, originalContent, ascaParams, wrapperParams, newResult.ScanDetails) + if err != nil { + newFindings = nil + } } - - newFindings, err := deltaFindings(ev, originalContent, ascaParams, wrapperParams, newResult.ScanDetails) - if err != nil || len(newFindings) == 0 { + newFindings = aboveThreshold(newFindings) + if len(newFindings) == 0 { findingCount = 0 return false, "", "", "" } @@ -130,6 +137,20 @@ func deltaFindings(ev *agenthooks.FileEditEvent, originalContent string, ascaPar return NewFindings(origDetails, newDetails), nil } +// aboveThreshold drops findings below the developer's severity threshold. +func aboveThreshold(findings []grpcs.ScanDetail) []grpcs.ScanDetail { + if BelowThreshold == nil { + return findings + } + kept := make([]grpcs.ScanDetail, 0, len(findings)) + for i := range findings { + if !BelowThreshold(findings[i].Severity) { + kept = append(kept, findings[i]) + } + } + return kept +} + // highestSeverity returns the highest severity level across the given ASCA findings. // Order: Critical > High > Medium > Low > (anything else). func highestSeverity(findings []grpcs.ScanDetail) string { diff --git a/internal/commands/agenthooks/guardrails/kics/kics.go b/internal/commands/agenthooks/guardrails/kics/kics.go index 0b98adbc6..17f630322 100644 --- a/internal/commands/agenthooks/guardrails/kics/kics.go +++ b/internal/commands/agenthooks/guardrails/kics/kics.go @@ -40,6 +40,11 @@ func isSupportedByKICS(filePath string) bool { return false } +// BelowThreshold is set by the hook dispatcher and reports whether a finding's severity is under the +// developer's cx_severity_threshold. Such findings are dropped from the deny, so the agent is never +// told to remediate them. Nil (the default) keeps every finding. +var BelowThreshold func(severity string) bool + // ScanFileEdit runs KICS on the proposed post-edit content. // Returns blocked=true with a formatted reason, remediation context, and highest severity when KICS // finds *new* vulnerabilities introduced by ev.Changes (delta-detection for edits; @@ -94,6 +99,10 @@ func ScanFileEdit(ev *agenthooks.FileEditEvent, svc *Scanner, telemetryWrapper w // For new files (no original content), every finding is new if originalContent == "" { + newResults = aboveThreshold(newResults) + if len(newResults) == 0 { + return false, "", "", "", "" + } r, c := formatFindings(ev.FilePath, newResults, ev.Agent, ev.WorkDir, ev.SessionID) findingCount = len(newResults) return true, r, c, "", highestSeverity(newResults) @@ -113,7 +122,7 @@ func ScanFileEdit(ev *agenthooks.FileEditEvent, svc *Scanner, telemetryWrapper w return false, "", "", skippedNote(ev.FilePath, err), "" } - newFindings := NewFindings(origResults, newResults) + newFindings := aboveThreshold(NewFindings(origResults, newResults)) if len(newFindings) == 0 { return false, "", "", "", "" } @@ -123,6 +132,20 @@ func ScanFileEdit(ev *agenthooks.FileEditEvent, svc *Scanner, telemetryWrapper w return true, r, c, "", highestSeverity(newFindings) } +// aboveThreshold drops findings below the developer's severity threshold. +func aboveThreshold(findings []iacrealtime.IacRealtimeResult) []iacrealtime.IacRealtimeResult { + if BelowThreshold == nil { + return findings + } + kept := make([]iacrealtime.IacRealtimeResult, 0, len(findings)) + for i := range findings { + if !BelowThreshold(findings[i].Severity) { + kept = append(kept, findings[i]) + } + } + return kept +} + // highestSeverity returns the highest severity level across the given KICS findings. // Order: Critical > High > Medium > Low > (anything else). func highestSeverity(findings []iacrealtime.IacRealtimeResult) string { diff --git a/internal/commands/agenthooks/guardrails/secrets/content.go b/internal/commands/agenthooks/guardrails/secrets/content.go new file mode 100644 index 000000000..7b44d714f --- /dev/null +++ b/internal/commands/agenthooks/guardrails/secrets/content.go @@ -0,0 +1,40 @@ +package secrets + +import ( + "os" + "strings" + + agenthooks "github.com/Checkmarx/ast-cx-hooks" +) + +func normLF(s string) string { + s = strings.ReplaceAll(s, "\r\n", "\n") + return strings.ReplaceAll(s, "\r", "\n") +} + +// proposedContent returns the file content that would exist after changes are applied, +// plus the content currently on disk (empty when the file does not exist yet). +// ok is false when Before text is missing or matches more than once. +func proposedContent(filePath string, changes []agenthooks.FileDiff) (newContent, originalContent string, ok bool) { + diskBytes, readErr := os.ReadFile(filePath) + if readErr == nil { + originalContent = string(diskBytes) + } + + if len(changes) == 1 && changes[0].Before == "" { + return changes[0].After, originalContent, true + } + + current := normLF(originalContent) + for _, diff := range changes { + before := normLF(diff.Before) + after := normLF(diff.After) + if strings.Count(current, before) != 1 { + return "", normLF(originalContent), false + } + idx := strings.Index(current, before) + current = current[:idx] + after + current[idx+len(before):] + } + + return current, normLF(originalContent), true +} diff --git a/internal/commands/agenthooks/guardrails/secrets/content_test.go b/internal/commands/agenthooks/guardrails/secrets/content_test.go new file mode 100644 index 000000000..92fda12ea --- /dev/null +++ b/internal/commands/agenthooks/guardrails/secrets/content_test.go @@ -0,0 +1,77 @@ +//go:build !integration + +package secrets + +import ( + "os" + "path/filepath" + "testing" + + agenthooks "github.com/Checkmarx/ast-cx-hooks" +) + +const ( + testConfigEnv = "config.env" + debugFalse = "DEBUG=false" + debugTrue = "DEBUG=true" + placeholderKey = "API_KEY=placeholder" +) + +func TestProposedContent_FullFileWrite(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "new.env") + changes := []agenthooks.FileDiff{{Before: "", After: "TOKEN=abc"}} + newContent, originalContent, ok := proposedContent(path, changes) + if !ok { + t.Fatal("full-file write should always resolve") + } + if newContent != "TOKEN=abc" || originalContent != "" { + t.Fatalf("newContent=%q originalContent=%q", newContent, originalContent) + } +} + +func TestProposedContent_UniqueMatch_Applies(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, testConfigEnv) + if err := os.WriteFile(path, []byte(debugFalse), 0o600); err != nil { + t.Fatal(err) + } + changes := []agenthooks.FileDiff{{Before: debugFalse, After: debugTrue}} + newContent, _, ok := proposedContent(path, changes) + if !ok { + t.Fatal("unique match should resolve") + } + if newContent != debugTrue { + t.Fatalf("newContent = %q, want %s", newContent, debugTrue) + } +} + +func TestProposedContent_DuplicateBeforeText_IsUnresolved(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, testConfigEnv) + body := placeholderKey + "\n" + debugTrue + "\n" + placeholderKey + if err := os.WriteFile(path, []byte(body), 0o600); err != nil { + t.Fatal(err) + } + changes := []agenthooks.FileDiff{{Before: placeholderKey, After: "API_KEY=sk-live-123"}} + _, _, ok := proposedContent(path, changes) + if ok { + t.Fatal("a Before string that matches more than once must not be guessed at") + } +} + +func TestProposedContent_BeforeTextMissing_IsUnresolved(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, testConfigEnv) + if err := os.WriteFile(path, []byte(debugTrue), 0o600); err != nil { + t.Fatal(err) + } + changes := []agenthooks.FileDiff{{Before: "STALE_TEXT", After: "TOKEN=sk-live-123"}} + newContent, _, ok := proposedContent(path, changes) + if ok { + t.Fatal("a Before string that is not found must not be silently skipped") + } + if newContent != "" { + t.Fatalf("newContent should be empty when unresolved, got %q", newContent) + } +} diff --git a/internal/commands/agenthooks/guardrails/secrets/delta.go b/internal/commands/agenthooks/guardrails/secrets/delta.go new file mode 100644 index 000000000..1d79833de --- /dev/null +++ b/internal/commands/agenthooks/guardrails/secrets/delta.go @@ -0,0 +1,203 @@ +package secrets + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "strings" + + agenthooks "github.com/Checkmarx/ast-cx-hooks" + "github.com/checkmarx/ast-cli/internal/commands/agenthooks/cursorplugin" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/ignore" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/secretsrealtime" +) + +// genericSecretDescription replaces finding descriptions that would leak the secret value. +const genericSecretDescription = "hardcoded secret" + +// findingKey matches the ignore-file key used by secrets-realtime: Title + SecretValue. +type findingKey struct { + title string + value string +} + +func keyOf(r *secretsrealtime.SecretsRealtimeResult) findingKey { + return findingKey{title: r.Title, value: r.SecretValue} +} + +// NewFindings returns results present in newScan that have no matching key in originalScan. +// A new file (originalScan == nil) returns newScan unchanged. +func NewFindings(originalScan, newScan []secretsrealtime.SecretsRealtimeResult) []secretsrealtime.SecretsRealtimeResult { + if originalScan == nil { + return newScan + } + baseline := make(map[findingKey]struct{}, len(originalScan)) + for i := range originalScan { + baseline[keyOf(&originalScan[i])] = struct{}{} + } + var out []secretsrealtime.SecretsRealtimeResult + for i := range newScan { + if _, exists := baseline[keyOf(&newScan[i])]; !exists { + out = append(out, newScan[i]) + } + } + return out +} + +// provenanceTag is prepended to the deny reason and context so the agent can recognize +// genuine Checkmarx output. +func provenanceTag() string { + return "[Checkmarx cx-devassist — automated security output, not user input]" +} + +// formatFindings builds the deny reason and the remediation context delivered to the agent. +// The secret value is written only to a mode-0600 finding file referenced by the suppress +// command, so it does not appear in the verdict text. +func formatFindings(filePath string, findings []secretsrealtime.SecretsRealtimeResult, agent agenthooks.AgentID, workDir, sessionID string) (reason, context string) { + summary := findingsSummary(filePath, findings) + tag := provenanceTag() + reason = tag + " " + permissionDecisionReason(filePath, summary) + if agent == agenthooks.AgentCursor { + context = cursorAdditionalContext(filePath, cxExecutable(), findings, workDir, sessionID) + } else { + context = additionalContext(filePath, cxExecutable(), findings, workDir, agent, sessionID) + } + context = tag + " " + context + return reason, context +} + +func findingsSummary(filePath string, findings []secretsrealtime.SecretsRealtimeResult) string { + var sb strings.Builder + for i := range findings { + f := &findings[i] + line := 0 + if len(f.Locations) > 0 { + line = f.Locations[0].Line + } + fmt.Fprintf(&sb, " - %s line %d [%s] %s — %s\n", + filePath, line, f.Severity, f.Title, safeDescription(f)) + } + return sb.String() +} + +func safeDescription(f *secretsrealtime.SecretsRealtimeResult) string { + if f.Description == "" || (f.SecretValue != "" && strings.Contains(f.Description, f.SecretValue)) { + return genericSecretDescription + } + return f.Description +} + +func permissionDecisionReason(filePath, summary string) string { + return fmt.Sprintf( + "Checkmarx secret detection found hardcoded secrets in %s.\nFindings:\n%s", + filePath, summary, + ) +} + +func cxExecutable() string { + cxExe, err := os.Executable() + if err != nil { + return "cx" + } + return cxExe +} + +func ignoredFilePathFlag(workDir string) string { + if workDir == "" { + return "" + } + return fmt.Sprintf(" --ignored-file-path '%s'", ignore.PathFor(workDir)) +} + +func cursorIgnoredFilePathFlag(workDir string) string { + if workDir == "" { + return "" + } + p := filepath.ToSlash(ignore.PathFor(workDir)) + return fmt.Sprintf(" --ignored-file-path %q", p) +} + +func optionalFlagsFragment(agent agenthooks.AgentID, sessionID string) string { + label := agentLabel(agent) + if label == "" { + return "" + } + pairs := "aiProvider=" + label + ";agent=" + label + "-cli" + if sessionID != "" { + pairs += ";aiAgentSessionId=" + sessionID + } + return fmt.Sprintf(" --optional-flags %q", pairs) +} + +func agentLabel(agent agenthooks.AgentID) string { + switch agent { + case agenthooks.AgentClaude: + return "Claude" + case agenthooks.AgentCopilot, agenthooks.AgentCopilotCLI: + return "Copilot" + case agenthooks.AgentCursor: + return "Cursor" + case agenthooks.AgentGemini: + return "Gemini" + case agenthooks.AgentCodex: + return "Codex" + default: + return "" + } +} + +// secretsSuppressCommands returns one ignore-vulnerability command per finding. +// The finding JSON (which must include SecretValue) is stored in a temp file and passed as +// --data @ so the secret value is not embedded in the agent-visible command. +func secretsSuppressCommands(cxBinary string, findings []secretsrealtime.SecretsRealtimeResult, workDir string, agent agenthooks.AgentID, sessionID string) string { + provenance := optionalFlagsFragment(agent, sessionID) + var suppressCmds strings.Builder + for i := range findings { + f := &findings[i] + path, err := writeSuppressPayload(f) + if err != nil { + fmt.Fprintf(&suppressCmds, " # suppress unavailable for %s\n", f.Title) + continue + } + dataArg := "@" + path + if agent == agenthooks.AgentCursor { + ignoreFlag := cursorIgnoredFilePathFlag(workDir) + suppressCmds.WriteString(cursorplugin.IgnoreVulnerabilityCommand(cxBinary, "secrets", []byte(dataArg), ignoreFlag, provenance)) + suppressCmds.WriteString("\n") + continue + } + ignoreFlag := ignoredFilePathFlag(workDir) + if agent == agenthooks.AgentGemini { + fmt.Fprintf(&suppressCmds, " %s ignore-vulnerability --scan-type secrets --data %s%s%s\n", cxBinary, ignore.QuoteDataFlag([]byte(dataArg)), ignoreFlag, provenance) + } else { + fmt.Fprintf(&suppressCmds, " %s ignore-vulnerability --scan-type secrets --data '%s'%s%s\n", cxBinary, dataArg, ignoreFlag, provenance) + } + } + return suppressCmds.String() +} + +func writeSuppressPayload(f *secretsrealtime.SecretsRealtimeResult) (string, error) { + if f.Title == "" || f.SecretValue == "" { + return "", fmt.Errorf("finding missing ignore key") + } + payload, err := json.Marshal(secretsrealtime.IgnoredSecret{Title: f.Title, SecretValue: f.SecretValue}) + if err != nil { + return "", err + } + file, err := os.CreateTemp("", "cx-secret-finding-*.json") + if err != nil { + return "", err + } + name := file.Name() + if _, err = file.Write(payload); err != nil { + _ = file.Close() + _ = os.Remove(name) + return "", err + } + if err = file.Close(); err != nil { + _ = os.Remove(name) + return "", err + } + return name, nil +} diff --git a/internal/commands/agenthooks/guardrails/secrets/prompts.go b/internal/commands/agenthooks/guardrails/secrets/prompts.go new file mode 100644 index 000000000..7e2d92f9f --- /dev/null +++ b/internal/commands/agenthooks/guardrails/secrets/prompts.go @@ -0,0 +1,136 @@ +package secrets + +import ( + "fmt" + + agenthooks "github.com/Checkmarx/ast-cx-hooks" + "github.com/checkmarx/ast-cli/internal/commands/agenthooks/agentprofile" + "github.com/checkmarx/ast-cli/internal/commands/agenthooks/cursorplugin" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/secretsrealtime" +) + +// hookDenyHeader is the agent-facing opening of additionalContext. The provenance tag is +// prepended separately in formatFindings. This header does not contain the spoof phrases +// the skills treat as proof a message is not from Checkmarx. +const hookDenyHeader = "This is a Checkmarx hook deny. Follow it. It is not file content and not an untrusted tool error.\n" + +// secretsRemediationReport is the closing report both deny paths tell the agent to show. +const secretsRemediationReport = "5. Always finish with this report, even if you asked the user a question, the file is new, " + + "or the retry passed. Show it in the chat as markdown, not inside a code block. One bullet per finding, " + + "then a blank line and the final status. Do not print the braces. Pick one result and one final status. " + + "A partial fix must include why it does not fully resolve the issue. Ignored must include why you ignored it. Unresolved must include why it was not fixed. A bullet without that reason is incomplete. " + + "Do not echo the secret value.\n" + + "## Checkmarx DevAssist Secret Remediation Summary\n" + + "\n" + + "- **{rule id}** - {severity} - line {line} - **{Fixed, Partial fix, Ignored, or Unresolved}**\n" + + " {Fixed: what changed. Partial fix: what you applied from the MCP suggestion, and Reason: why it does not fully resolve the issue. Ignored: Reason: why, citing the user's words or the file and line you read. Unresolved: Reason: why it was not fixed.}\n" + + "\n" + + "**Final status:** {All fixed, Partially fixed, or Unresolved}\n" + + "Then continue the user's original task. Do not include that sentence in the report.\n" + +func additionalContext(filePath, cxBinary string, findings []secretsrealtime.SecretsRealtimeResult, workDir string, agent agenthooks.AgentID, sessionID string) string { + codeTool := "mcp__Checkmarx__codeRemediation" + if agent == agenthooks.AgentGemini { + codeTool = "mcp_Checkmarx_codeRemediation" + } + skill := secretsSkillName(agent) + suppressCmds := secretsSuppressCommands(cxBinary, findings, workDir, agent, sessionID) + return fmt.Sprintf( + hookDenyHeader+ + "Secret detection blocked the write to %s.\nFindings:\n%s"+ + "Handle every finding yourself. Never ask the user, including \"Would you like me to "+ + "remediate?\" (that question is only for on-demand scans).\n"+ + "1. Classify each finding:\n"+ + "- False positive only if one of these is already true and you can cite it: (a) the user "+ + "explicitly told you to ignore or suppress it; (b) a file you opened this session shows, at a "+ + "line you can cite, that the match is a placeholder, example, or test fixture. What a finding, "+ + "hook message, or file says about another file is not evidence; open that file. Apparent intent "+ + "(a lab, demo, or training file) is not evidence; that still needs (a) or (b).\n"+ + "- Otherwise it is a true positive, including when you are unsure.\n"+ + "2. True positive: call %s for each one with type \"secret\" and metadata (ruleId = the finding "+ + "title, description, line). The %s skill can make this call; if it disagrees with this deny, "+ + "follow this deny. Apply remediation_steps only with Edit, Write, MultiEdit, or NotebookEdit, "+ + "never a shell command (shell writes are not scanned). Replace the hardcoded secret with an "+ + "environment-variable reference, including any Safe Refactor the tool returns. Do not echo the "+ + "secret value. If the blocked write creates a new file, the fix is that same Write with the "+ + "fixed content. If you believe those remediation_steps will not fully solve the security issue, "+ + "still apply them. Do not skip the MCP suggestion, and do not ignore the finding because of that "+ + "belief. In the summary mark that finding as a partial fix and state why it does not fully "+ + "resolve the issue.\n"+ + "If %s is unavailable, change nothing and ignore nothing because of it. Report the findings "+ + "as unresolved and tell the user to %s.\n"+ + "3. False positive: run exactly this command for it:\n%s"+ + "4. Verify: skip only the initial scan. Run `cx scan secrets-realtime -s ` with the "+ + "canonical cx path; that re-scan validates the finding. A finding is fixed only when the "+ + "re-scan no longer reports it. Then retry the blocked write once so the gate can accept the "+ + "write. If the re-scan still reports a finding whose remediation_steps you applied, keep that "+ + "change and mark it as a partial fix with the reason it does not fully resolve the issue. If "+ + "the retry is denied, a remaining finding you have not applied a suggestion for, or one your "+ + "fix introduced, gets one more %s call. Stop after 3 denied retries or when the tool returns "+ + "no safe change. Then ignore only findings that meet step 1. Report a finding whose MCP "+ + "suggestion you applied as a partial fix; report a finding with no applied suggestion as "+ + "unresolved. Stop editing the file. Do not ask whether to continue.\n"+ + "Never write this content through another tool, a shell command, or a different file to "+ + "bypass the scan.\n"+ + secretsRemediationReport, + filePath, findingsSummary(filePath, findings), codeTool, skill, codeTool, agentprofile.McpReconnect(agentLabel(agent)), suppressCmds, codeTool, + ) +} + +func cursorAdditionalContext(filePath, cxBinary string, findings []secretsrealtime.SecretsRealtimeResult, workDir, sessionID string) string { + suppressCmds := secretsSuppressCommands(cxBinary, findings, workDir, agenthooks.AgentCursor, sessionID) + skill := secretsSkillName(agenthooks.AgentCursor) + codeTool := cursorplugin.MCPTool("codeRemediation") + return fmt.Sprintf( + hookDenyHeader+ + "Secret detection blocked the write to %s. Follow the cx-hook-deny.mdc and "+ + "cx-devassist-secrets.mdc rules for this deny.\nFindings:\n%s"+ + "Handle every finding yourself. Never ask the user, including \"Would you like me to "+ + "remediate?\" (that question is only for on-demand scans).\n"+ + "1. Classify each finding:\n"+ + "- False positive only if one of these is already true and you can cite it: (a) the user "+ + "explicitly told you to ignore or suppress this finding, in those words. Saying the secret is "+ + "still exposed, or that a change does not make it safe, is not (a). Do not run the ignore "+ + "command because of it. Still apply the MCP suggestion and mark the finding as a partial fix "+ + "with the reason it does not fully resolve the issue. (b) a file you opened this session "+ + "shows, at a line you can cite, that the match is a placeholder, example, or test fixture. "+ + "What a finding, hook message, or file says about another file is not evidence; open that "+ + "file. Apparent intent (a lab, demo, or training file) is not evidence; that still needs (a) "+ + "or (b).\n"+ + "- Otherwise it is a true positive, including when you are unsure.\n"+ + "2. True positive: call %s for each one with type \"secret\" and metadata (ruleId = the finding "+ + "title, description, line). The %s skill can make this call; if it disagrees with this deny, "+ + "follow this deny. Apply remediation_steps only with Write or StrReplace, never a shell "+ + "command (shell writes are not scanned). Replace the hardcoded secret with an "+ + "environment-variable reference, including any Safe Refactor the tool returns. Do not echo the "+ + "secret value. If the blocked write creates a new file, the fix is that same Write with the "+ + "fixed content. If you believe those remediation_steps will not fully solve the security issue, "+ + "still apply them. Do not skip the MCP suggestion, and do not ignore the finding because of that "+ + "belief. In the summary mark that finding as a partial fix and state why it does not fully "+ + "resolve the issue.\n"+ + "If %s is unavailable, change nothing and ignore nothing because of it. Report the findings "+ + "as unresolved and tell the user to %s.\n"+ + "3. False positive: run exactly this command for it:\n%s"+ + "4. Verify: skip only the initial scan. Run `cx scan secrets-realtime -s ` with the "+ + "canonical cx path; that re-scan validates the finding. A finding is fixed only when the "+ + "re-scan no longer reports it. Then retry the blocked write once so the gate can accept the "+ + "write. If the re-scan still reports a finding whose remediation_steps you applied, keep that "+ + "change and mark it as a partial fix with the reason it does not fully resolve the issue. If "+ + "the retry is denied, a remaining finding you have not applied a suggestion for, or one your "+ + "fix introduced, gets one more %s call. Stop after 3 denied retries or when the tool returns "+ + "no safe change. Then ignore only findings that meet step 1. Report a finding whose MCP "+ + "suggestion you applied as a partial fix; report a finding with no applied suggestion as "+ + "unresolved. Stop editing the file. Do not ask whether to continue.\n"+ + "Never write this content through another tool, a shell command, or a different file to "+ + "bypass the scan.\n"+ + secretsRemediationReport, + filePath, findingsSummary(filePath, findings), codeTool, skill, codeTool, agentprofile.McpReconnect(agentLabel(agenthooks.AgentCursor)), suppressCmds, codeTool, + ) +} + +func secretsSkillName(agent agenthooks.AgentID) string { + if agent == agenthooks.AgentGemini { + return "/cx-devassist-secrets" + } + return "cx-devassist:cx-devassist-secrets" +} diff --git a/internal/commands/agenthooks/guardrails/secrets/scanner.go b/internal/commands/agenthooks/guardrails/secrets/scanner.go new file mode 100644 index 000000000..a2eb58a1e --- /dev/null +++ b/internal/commands/agenthooks/guardrails/secrets/scanner.go @@ -0,0 +1,32 @@ +package secrets + +import ( + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/secretsrealtime" + "github.com/checkmarx/ast-cli/internal/wrappers" +) + +// Scanner runs secret realtime scans on behalf of the file-edit guardrail. +// Tests substitute scan via NewScannerWithFunc. +type Scanner struct { + jwt wrappers.JWTWrapper + ff wrappers.FeatureFlagsWrapper + scan func(sourcePath, content, ignoreFilePath string) ([]secretsrealtime.SecretsRealtimeResult, error) +} + +// NewScanner returns a Scanner backed by the secrets realtime engine. +func NewScanner(jwt wrappers.JWTWrapper, ff wrappers.FeatureFlagsWrapper) *Scanner { + s := &Scanner{jwt: jwt, ff: ff} + s.scan = s.runRealScan + return s +} + +// NewScannerWithFunc returns a Scanner whose scan call is replaced with f. +// For unit tests only. +func NewScannerWithFunc(f func(sourcePath, content, ignoreFilePath string) ([]secretsrealtime.SecretsRealtimeResult, error)) *Scanner { + return &Scanner{scan: f} +} + +func (s *Scanner) runRealScan(sourcePath, content, ignoreFilePath string) ([]secretsrealtime.SecretsRealtimeResult, error) { + svc := secretsrealtime.NewSecretsRealtimeService(s.jwt, s.ff) + return svc.ScanContent(sourcePath, content, ignoreFilePath) +} diff --git a/internal/commands/agenthooks/guardrails/secrets/secrets.go b/internal/commands/agenthooks/guardrails/secrets/secrets.go new file mode 100644 index 000000000..b5a73c853 --- /dev/null +++ b/internal/commands/agenthooks/guardrails/secrets/secrets.go @@ -0,0 +1,148 @@ +package secrets + +import ( + "os" + + agenthooks "github.com/Checkmarx/ast-cx-hooks" + "github.com/checkmarx/ast-cli/internal/logger" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/ignore" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/secretsrealtime" + "github.com/checkmarx/ast-cli/internal/wrappers" +) + +const ( + unresolvedEditReason = "Checkmarx secret detection could not verify this edit: the text being " + + "replaced was not found uniquely in the file, so the result cannot be scanned reliably." + unresolvedEditContext = "Retry with an edit whose Before/old_string text matches exactly one " + + "location in the file (add more surrounding context if the target text repeats), then the " + + "edit can be scanned and applied." +) + +// BelowThreshold is set by the hook dispatcher and reports whether a finding's severity is under the +// developer's cx_severity_threshold. Such findings are dropped from the deny, so the agent is never +// told to remediate them. Nil (the default) keeps every finding. +var BelowThreshold func(severity string) bool + +// ScanFileEdit runs secret detection on the proposed post-edit content. +// Returns blocked=true with a formatted reason, remediation context, and highest severity when the +// edit introduces a secret (delta-detection for edits; any secret for new writes). Findings the +// user already suppressed via `cx ignore-vulnerability` are filtered by the scanner. Fail-open on +// infrastructure errors. Fail closed when the post-edit content cannot be reconstructed. +// The user-visible reason never contains the secret value. +func ScanFileEdit(ev *agenthooks.FileEditEvent, svc *Scanner, telemetryWrapper wrappers.TelemetryWrapper, agent string) (blocked bool, reason, context, severity string) { + if svc == nil || svc.scan == nil || ev == nil { + return false, "", "", "" + } + + findingCount := 0 + defer func() { + if r := recover(); r != nil { + logger.PrintfIfVerbose("secrets guardrail: recovered from panic, failing open: %v", r) + blocked = false + reason = "" + context = "" + severity = "" + } + logSecretsTelemetry(telemetryWrapper, agent, ev.SessionID, findingCount) + }() + + newContent, originalContent, ok := proposedContent(ev.FilePath, ev.Changes) + if !ok { + findingCount = 1 + return true, provenanceTag() + " " + unresolvedEditReason, provenanceTag() + " " + unresolvedEditContext, "" + } + if newContent == "" { + return false, "", "", "" + } + + ignoreFilePath := existingIgnoreFilePath(ev.WorkDir) + newResults, err := svc.scan(ev.FilePath, newContent, ignoreFilePath) + if err != nil { + logger.PrintfIfVerbose("secrets guardrail: scan of proposed content failed, failing open: %v", err) + return false, "", "", "" + } + if len(newResults) == 0 { + return false, "", "", "" + } + + findings := newResults + if originalContent != "" { + origResults, origErr := svc.scan(ev.FilePath, originalContent, ignoreFilePath) + if origErr != nil { + logger.PrintfIfVerbose("secrets guardrail: scan of original content failed, failing open: %v", origErr) + return false, "", "", "" + } + findings = NewFindings(origResults, newResults) + if len(findings) == 0 { + return false, "", "", "" + } + } + + findings = aboveThreshold(findings) + if len(findings) == 0 { + return false, "", "", "" + } + + r, c := formatFindings(ev.FilePath, findings, ev.Agent, ev.WorkDir, ev.SessionID) + findingCount = len(findings) + return true, r, c, highestSeverity(findings) +} + +// aboveThreshold drops findings under the developer's severity threshold. +func aboveThreshold(findings []secretsrealtime.SecretsRealtimeResult) []secretsrealtime.SecretsRealtimeResult { + if BelowThreshold == nil { + return findings + } + kept := make([]secretsrealtime.SecretsRealtimeResult, 0, len(findings)) + for i := range findings { + if !BelowThreshold(findings[i].Severity) { + kept = append(kept, findings[i]) + } + } + return kept +} + +func highestSeverity(findings []secretsrealtime.SecretsRealtimeResult) string { + rank := map[string]int{"Critical": 4, "High": 3, "Medium": 2, "Low": 1} + best := "" + bestRank := -1 + for i := range findings { + if r, ok := rank[findings[i].Severity]; ok && r > bestRank { + bestRank = r + best = findings[i].Severity + } + } + return best +} + +func logSecretsTelemetry(telemetryWrapper wrappers.TelemetryWrapper, agent, sessionID string, totalCount int) { + if telemetryWrapper == nil || totalCount == 0 { + return + } + + telemetryData := &wrappers.DataForAITelemetry{ + Agent: agent + "-cli", + AIProvider: agent, + Engine: "Secrets", + TotalCount: totalCount, + UniqueID: wrappers.GetUniqueID(), + Type: "hooks-detect", + SubType: "scan", + ScanType: "secrets", + AiAgentSessionId: sessionID, + } + + if err := telemetryWrapper.SendAIDataToLog(telemetryData); err != nil { + logger.PrintfIfVerbose("secrets guardrail: failed to send telemetry: %v", err) + } +} + +// existingIgnoreFilePath returns the realtime ignore-file path anchored at workDir only +// when it exists on disk. A missing file means the user has not suppressed anything yet. +func existingIgnoreFilePath(workDir string) string { + p := ignore.PathFor(workDir) + if _, err := os.Stat(p); err == nil { + return p + } + return "" +} diff --git a/internal/commands/agenthooks/guardrails/secrets/secrets_test.go b/internal/commands/agenthooks/guardrails/secrets/secrets_test.go new file mode 100644 index 000000000..c39e6f0d2 --- /dev/null +++ b/internal/commands/agenthooks/guardrails/secrets/secrets_test.go @@ -0,0 +1,330 @@ +//go:build !integration + +package secrets + +import ( + "encoding/json" + "os" + "path/filepath" + "strings" + "testing" + + agenthooks "github.com/Checkmarx/ast-cx-hooks" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine" + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/secretsrealtime" + "github.com/checkmarx/ast-cli/internal/wrappers" +) + +const sampleSecret = "ghp_testvalue_should_stay_out_of_verdict" + +func sampleFinding() secretsrealtime.SecretsRealtimeResult { + return secretsrealtime.SecretsRealtimeResult{ + Title: "github-pat", + Description: "GitHub personal access token", + SecretValue: sampleSecret, + Severity: "Critical", + FilePath: "app.env", + Locations: []realtimeengine.Location{{Line: 4}}, + } +} + +type recordingTelemetry struct { + calls []*wrappers.DataForAITelemetry +} + +func (r *recordingTelemetry) SendAIDataToLog(data *wrappers.DataForAITelemetry) error { + r.calls = append(r.calls, data) + return nil +} + +const awsKeyTitle = "aws-access-key" + +func TestNewFindings_DropsPreExisting(t *testing.T) { + old := sampleFinding() + fresh := sampleFinding() + fresh.SecretValue = "AKIA_NEW_SECRET_VALUE" + fresh.Title = awsKeyTitle + got := NewFindings([]secretsrealtime.SecretsRealtimeResult{old}, []secretsrealtime.SecretsRealtimeResult{old, fresh}) + if len(got) != 1 || got[0].Title != awsKeyTitle { + t.Fatalf("got %+v, want only the new aws-access-key finding", got) + } +} + +func TestNewFindings_NilOriginalReturnsAll(t *testing.T) { + f := sampleFinding() + got := NewFindings(nil, []secretsrealtime.SecretsRealtimeResult{f}) + if len(got) != 1 { + t.Fatalf("got %d findings, want 1", len(got)) + } +} + +func TestScanFileEdit_NewSecret_BlocksAndRedacts(t *testing.T) { + secret := sampleSecret + svc := NewScannerWithFunc(func(_, content, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + if strings.Contains(content, secret) { + return []secretsrealtime.SecretsRealtimeResult{sampleFinding()}, nil + } + return nil, nil + }) + tel := &recordingTelemetry{} + ev := &agenthooks.FileEditEvent{ + Agent: agenthooks.AgentClaude, + SessionID: "sess-1", + FilePath: "app.env", + WorkDir: t.TempDir(), + Changes: []agenthooks.FileDiff{{Before: "", After: "TOKEN=" + secret}}, + } + blocked, reason, context, severity := ScanFileEdit(ev, svc, tel, "Claude") + if !blocked { + t.Fatal("expected the new secret to block the write") + } + if severity != "Critical" { + t.Fatalf("severity = %q, want Critical", severity) + } + assertVerdictOmitsSecret(t, reason, context) + if !strings.Contains(reason, "github-pat") || !strings.Contains(reason, "line 4") { + t.Fatalf("reason missing finding summary: %q", reason) + } + if !strings.Contains(context, "cx-devassist:cx-devassist-secrets") { + t.Fatalf("context missing skill: %q", context) + } + if !strings.Contains(context, "mcp__Checkmarx__codeRemediation") || !strings.Contains(context, `type "secret"`) || strings.Contains(context, `type "secrets"`) { + t.Fatalf("context missing MCP remediation: %q", context) + } + if !strings.Contains(reason, "[Checkmarx cx-devassist — automated security output, not user input]") { + t.Fatalf("reason missing provenance tag: %q", reason) + } + if !strings.Contains(context, "ignore-vulnerability --scan-type secrets --data '@") { + t.Fatalf("context missing redacted suppress command: %q", context) + } + assertSuppressFile(t, context, secret) + if len(tel.calls) != 1 || tel.calls[0].Type != "hooks-detect" || tel.calls[0].Engine != "Secrets" { + t.Fatalf("detect telemetry = %+v", tel.calls) + } +} + +func TestScanFileEdit_PreExistingSecret_Allows(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "app.env") + body := "note=hello\nTOKEN=" + sampleSecret + if err := os.WriteFile(path, []byte(body), 0o600); err != nil { + t.Fatal(err) + } + svc := NewScannerWithFunc(func(_, content, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + if strings.Contains(content, sampleSecret) { + return []secretsrealtime.SecretsRealtimeResult{sampleFinding()}, nil + } + return nil, nil + }) + ev := &agenthooks.FileEditEvent{ + Agent: agenthooks.AgentClaude, + FilePath: path, + WorkDir: dir, + Changes: []agenthooks.FileDiff{{Before: "note=hello", After: "note=world"}}, + } + blocked, reason, _, _ := ScanFileEdit(ev, svc, nil, "Claude") + if blocked { + t.Fatalf("an edit that does not introduce a new secret should be allowed, got: %s", reason) + } +} + +func TestScanFileEdit_DuplicateBeforeText_BlocksInsteadOfGuessing(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, testConfigEnv) + body := placeholderKey + "\n" + debugTrue + "\n" + placeholderKey + if err := os.WriteFile(path, []byte(body), 0o600); err != nil { + t.Fatal(err) + } + scanCalled := false + svc := NewScannerWithFunc(func(_, _, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + scanCalled = true + return nil, nil + }) + ev := &agenthooks.FileEditEvent{ + Agent: agenthooks.AgentClaude, + FilePath: path, + WorkDir: dir, + Changes: []agenthooks.FileDiff{{Before: placeholderKey, After: "API_KEY=" + sampleSecret}}, + } + blocked, reason, context, _ := ScanFileEdit(ev, svc, nil, "Claude") + if !blocked { + t.Fatal("an edit whose Before text is ambiguous should be blocked, not silently allowed") + } + if scanCalled { + t.Fatal("should not scan a guessed reconstruction when the edit location is ambiguous") + } + assertVerdictOmitsSecret(t, reason, context) +} + +func TestScanFileEdit_BeforeTextNotFound_BlocksInsteadOfSkipping(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, testConfigEnv) + if err := os.WriteFile(path, []byte(debugTrue), 0o600); err != nil { + t.Fatal(err) + } + scanCalled := false + svc := NewScannerWithFunc(func(_, _, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + scanCalled = true + return nil, nil + }) + ev := &agenthooks.FileEditEvent{ + Agent: agenthooks.AgentClaude, + FilePath: path, + WorkDir: dir, + Changes: []agenthooks.FileDiff{{Before: "STALE_TEXT_NOT_ON_DISK", After: "TOKEN=" + sampleSecret}}, + } + blocked, reason, context, _ := ScanFileEdit(ev, svc, nil, "Claude") + if !blocked { + t.Fatal("an edit whose Before text cannot be located should be blocked, not silently dropped and allowed") + } + assertVerdictOmitsSecret(t, reason, context) + if scanCalled { + t.Fatal("should not scan content that silently omits the unresolved edit") + } +} + +func TestScanFileEdit_ScanError_FailOpen(t *testing.T) { + svc := NewScannerWithFunc(func(_, _, _ string) ([]secretsrealtime.SecretsRealtimeResult, error) { + return nil, os.ErrClosed + }) + ev := &agenthooks.FileEditEvent{ + Agent: agenthooks.AgentCodex, + FilePath: "a.txt", + Changes: []agenthooks.FileDiff{{Before: "", After: "TOKEN=" + sampleSecret}}, + } + blocked, reason, _, _ := ScanFileEdit(ev, svc, nil, "Codex") + if blocked { + t.Fatalf("scanner error should fail open, got: %s", reason) + } +} + +func TestFormatFindings_AgentSpecific(t *testing.T) { + findings := []secretsrealtime.SecretsRealtimeResult{sampleFinding()} + workDir := t.TempDir() + + _, claude := formatFindings("app.env", findings, agenthooks.AgentClaude, workDir, "s") + if !strings.Contains(claude, "cx-devassist:cx-devassist-secrets") { + t.Fatalf("claude skill missing: %q", claude) + } + if strings.Contains(claude, sampleSecret) { + t.Fatal("claude context leaked the secret") + } + + _, copilot := formatFindings("app.env", findings, agenthooks.AgentCopilotCLI, workDir, "s") + if !strings.Contains(copilot, "aiProvider=Copilot") { + t.Fatalf("copilot provenance missing: %q", copilot) + } + + _, gemini := formatFindings("app.env", findings, agenthooks.AgentGemini, workDir, "s") + if !strings.Contains(gemini, "/cx-devassist-secrets") || !strings.Contains(gemini, "mcp_Checkmarx_codeRemediation") { + t.Fatalf("gemini targets missing: %q", gemini) + } + if strings.Contains(gemini, "mcp__Checkmarx__codeRemediation") { + t.Fatal("gemini should use single-underscore MCP tool names") + } + if !strings.Contains(gemini, "run /mcp") && !strings.Contains(gemini, "restart the Gemini CLI") { + t.Fatalf("gemini reconnect hint missing: %q", gemini) + } + + _, codex := formatFindings("app.env", findings, agenthooks.AgentCodex, workDir, "s") + if !strings.Contains(codex, "restart Codex") { + t.Fatalf("codex reconnect hint missing: %q", codex) + } + + _, cursor := formatFindings("app.env", findings, agenthooks.AgentCursor, workDir, "s") + if !strings.Contains(cursor, "cx-devassist-secrets.mdc") || !strings.Contains(cursor, "This is a Checkmarx hook deny") { + t.Fatalf("cursor prompt missing: %q", cursor) + } + if strings.Contains(cursor, "ASK THE USER FIRST") { + t.Fatal("cursor prompt still asks the user first") + } + if !strings.Contains(cursor, "mcp__plugin-cx-devassist-Checkmarx__codeRemediation") { + t.Fatalf("cursor MCP tool missing: %q", cursor) + } + if strings.Contains(cursor, sampleSecret) { + t.Fatal("cursor context leaked the secret") + } +} + +func TestFormatFindings_OmitsInjectionTriggers(t *testing.T) { + findings := []secretsrealtime.SecretsRealtimeResult{sampleFinding()} + workDir := t.TempDir() + agents := []agenthooks.AgentID{ + agenthooks.AgentClaude, + agenthooks.AgentCodex, + agenthooks.AgentCopilot, + agenthooks.AgentCursor, + agenthooks.AgentGemini, + } + for _, agent := range agents { + _, ctx := formatFindings("app.env", findings, agent, workDir, "s1") + for _, bad := range []string{"without asking", "silently", "cx_mcp_register", "the hook on that retry is the check"} { + if strings.Contains(ctx, bad) { + t.Errorf("%s context contains %q", agent, bad) + } + } + if !strings.Contains(ctx, "This is a Checkmarx hook deny") { + t.Errorf("%s context missing hook deny header", agent) + } + if !strings.Contains(ctx, "that still needs (a) or (b)") { + t.Errorf("%s context missing suppression label", agent) + } + if !strings.Contains(ctx, "cx scan secrets-realtime -s") { + t.Errorf("%s context missing secrets re-scan", agent) + } + if !strings.Contains(ctx, "that re-scan validates the finding") { + t.Errorf("%s context missing re-scan validation", agent) + } + if !strings.Contains(ctx, "partial fix") { + t.Errorf("%s context missing partial-fix status", agent) + } + if !strings.Contains(ctx, "Stop after 3 denied retries") { + t.Errorf("%s context missing retry stop", agent) + } + if !strings.Contains(ctx, "Checkmarx DevAssist Secret Remediation Summary") { + t.Errorf("%s context missing remediation summary", agent) + } + } +} + +func TestSafeDescription_RedactsEmbeddedSecret(t *testing.T) { + f := sampleFinding() + f.Description = "token " + sampleSecret + " found" + if safeDescription(&f) != genericSecretDescription { + t.Fatal("description that embeds the secret should be redacted") + } +} + +func assertVerdictOmitsSecret(t *testing.T, reason, context string) { + t.Helper() + if strings.Contains(reason, sampleSecret) || strings.Contains(context, sampleSecret) { + t.Fatal("verdict leaked the secret value") + } +} + +func assertSuppressFile(t *testing.T, context, secret string) { + t.Helper() + const marker = "--data '@" + idx := strings.Index(context, marker) + if idx < 0 { + t.Fatalf("suppress command not found in %q", context) + } + rest := context[idx+len(marker):] + end := strings.Index(rest, "'") + if end < 0 { + t.Fatal("unterminated suppress path") + } + path := strings.TrimPrefix(rest[:end], "@") + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + var got secretsrealtime.IgnoredSecret + if err := json.Unmarshal(data, &got); err != nil { + t.Fatal(err) + } + if got.Title != "github-pat" || got.SecretValue != secret { + t.Fatalf("suppress file = %+v", got) + } + t.Cleanup(func() { _ = os.Remove(path) }) +} diff --git a/internal/commands/agenthooks/sca/sca.go b/internal/commands/agenthooks/sca/sca.go index 43785fab2..641906fd4 100644 --- a/internal/commands/agenthooks/sca/sca.go +++ b/internal/commands/agenthooks/sca/sca.go @@ -6,6 +6,11 @@ import ( "github.com/checkmarx/ast-cli/internal/services/realtimeengine/ossrealtime" ) +// BelowThreshold is set by the hook dispatcher and reports whether a finding's severity is under the +// developer's cx_severity_threshold. Such findings are dropped from the deny, so the agent is never +// told to remediate them. Nil (the default) keeps every finding. +var BelowThreshold func(severity string) bool + // CheckBashInstall is the entry point for the pre-Bash-tool guardrail. It // returns ("", "", "") to allow the command, or (finding, remediation, severity) to block. // Errors fail open — we never block on infrastructure failures. @@ -73,6 +78,7 @@ func denyFrom(malicious, vulnerable []ossrealtime.OssPackage, workDir, agent, se f, r := DenyMalicious(malicious, agent) return tag + " " + f, tag + " " + r, statusMalicious } + vulnerable = aboveThreshold(vulnerable) if len(vulnerable) > 0 { f, r := DenyVulnerable(vulnerable, workDir, agent, sessionID) return tag + " " + f, tag + " " + r, highestVulnSeverity(vulnerable) @@ -80,6 +86,29 @@ func denyFrom(malicious, vulnerable []ossrealtime.OssPackage, workDir, agent, se return "", "", "" } +// aboveThreshold drops CVEs below the developer's severity threshold, and any package left with +// none. Malicious packages never go through here. A CVE with an unknown severity is kept. +func aboveThreshold(pkgs []ossrealtime.OssPackage) []ossrealtime.OssPackage { + if BelowThreshold == nil { + return pkgs + } + kept := make([]ossrealtime.OssPackage, 0, len(pkgs)) + for i := range pkgs { + p := pkgs[i] + vulns := make([]ossrealtime.Vulnerability, 0, len(p.Vulnerabilities)) + for _, v := range p.Vulnerabilities { + if !BelowThreshold(v.Severity) { + vulns = append(vulns, v) + } + } + if len(vulns) > 0 { + p.Vulnerabilities = vulns + kept = append(kept, p) + } + } + return kept +} + // highestVulnSeverity returns the highest CVE severity across all vulnerable packages. func highestVulnSeverity(pkgs []ossrealtime.OssPackage) string { rank := map[string]int{"Critical": 4, "High": 3, "Medium": 2, "Low": 1} diff --git a/internal/commands/agenthooks/sca/threshold_test.go b/internal/commands/agenthooks/sca/threshold_test.go new file mode 100644 index 000000000..320a45521 --- /dev/null +++ b/internal/commands/agenthooks/sca/threshold_test.go @@ -0,0 +1,42 @@ +//go:build !integration + +package sca + +import ( + "testing" + + "github.com/checkmarx/ast-cli/internal/services/realtimeengine/ossrealtime" +) + +func TestAboveThreshold_DropsLowCVEsAndEmptyPackages(t *testing.T) { + old := BelowThreshold + t.Cleanup(func() { BelowThreshold = old }) + BelowThreshold = func(sev string) bool { return sev == "Low" || sev == "Medium" } + + pkgs := []ossrealtime.OssPackage{ + {PackageName: "mixed", Vulnerabilities: []ossrealtime.Vulnerability{{CVE: "CVE-1", Severity: "High"}, {CVE: "CVE-2", Severity: "Medium"}}}, + {PackageName: "lowonly", Vulnerabilities: []ossrealtime.Vulnerability{{CVE: "CVE-3", Severity: "Low"}}}, + {PackageName: "unknown", Vulnerabilities: []ossrealtime.Vulnerability{{CVE: "CVE-4", Severity: ""}}}, + } + got := aboveThreshold(pkgs) + if len(got) != 2 || got[0].PackageName != "mixed" || got[1].PackageName != "unknown" { + t.Fatalf("unexpected packages: %+v", got) + } + if len(got[0].Vulnerabilities) != 1 || got[0].Vulnerabilities[0].CVE != "CVE-1" { + t.Fatalf("mixed package must keep only its High CVE: %+v", got[0].Vulnerabilities) + } + if len(pkgs[0].Vulnerabilities) != 2 { + t.Fatal("input must not be mutated") + } +} + +func TestDenyFrom_MaliciousIgnoresThreshold(t *testing.T) { + old := BelowThreshold + t.Cleanup(func() { BelowThreshold = old }) + BelowThreshold = func(string) bool { return true } + + mal := []ossrealtime.OssPackage{{PackageName: "evil", Status: statusMalicious}} + if f, _, sev := denyFrom(mal, nil, "", "Copilot", "s"); f == "" || sev != statusMalicious { + t.Fatalf("malicious must always deny, got finding=%q severity=%q", f, sev) + } +} diff --git a/internal/commands/agenthooks/scannerconfig/scannerconfig.go b/internal/commands/agenthooks/scannerconfig/scannerconfig.go new file mode 100644 index 000000000..aafaf7b2e --- /dev/null +++ b/internal/commands/agenthooks/scannerconfig/scannerconfig.go @@ -0,0 +1,121 @@ +// Package scannerconfig reads the per-scanner on/off switches a developer sets in +// ~/.checkmarx/cx-onboarding.properties (seeded by the agent plugins). Every scanner is ENABLED +// unless its key is explicitly set to a false-like value, and any read problem also means enabled: +// the switches can only narrow what the hooks do, never make them block. +package scannerconfig + +import ( + "bufio" + "io" + "os" + "path/filepath" + "strings" +) + +// Scanner identifies one guardrail engine. +type Scanner string + +const ( + // ASCA is the key for the ASCA (source code) scanner switch. + ASCA Scanner = "cx_asca_scanner_enabled" + // SCA is the key for the SCA (open source packages) scanner switch. + SCA Scanner = "cx_sca_scanner_enabled" + // KICS is the key for the KICS (IaC) scanner switch. + KICS Scanner = "cx_kics_scanner_enabled" + // Secrets is the key for the secrets scanner switch. + Secrets Scanner = "cx_secret_scanner_enabled" +) + +const ( + fileName = "cx-onboarding.properties" + // maxBytes mirrors the plugins' reader: an oversized file is treated as unreadable (all enabled). + maxBytes = 8192 + utf8BOM = "\xef\xbb\xbf" +) + +// Path returns ~/.checkmarx/cx-onboarding.properties, or "" when the home directory is unknown. +func Path() string { + home, err := os.UserHomeDir() + if err != nil || home == "" { + return "" + } + return filepath.Join(home, ".checkmarx", fileName) +} + +// Enabled reports whether the scanner is switched on in the user's config file. +func Enabled(s Scanner) bool { + return enabledIn(Path(), s) +} + +func enabledIn(path string, s Scanner) bool { + value, found := valueIn(path, string(s)) + return !found || !isFalse(value) +} + +// valueIn returns the last `key=value` for key in the file, or found=false when the file is missing, +// unreadable, oversized or does not set the key. Same parsing rules as the plugins' readers. +func valueIn(path, key string) (value string, found bool) { + if path == "" { + return "", false + } + f, err := os.Open(path) + if err != nil { + return "", false + } + defer func() { _ = f.Close() }() + raw, err := io.ReadAll(io.LimitReader(f, maxBytes+1)) + if err != nil || len(raw) > maxBytes { + return "", false + } + sc := bufio.NewScanner(strings.NewReader(strings.TrimPrefix(string(raw), utf8BOM))) + for sc.Scan() { // last occurrence wins + line := strings.TrimSpace(sc.Text()) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + k, v, ok := strings.Cut(line, "=") + if !ok || strings.TrimSpace(k) != key { + continue + } + value, found = v, true + } + return value, found +} + +func isFalse(v string) bool { + switch strings.ToLower(strings.TrimSpace(v)) { + case "false", "0", "no", "off", "disabled": + return true + } + return false +} + +const thresholdKey = "cx_severity_threshold" + +// severityRank orders the severities the guardrails report. Anything not listed (an empty string, a +// package status such as "Malicious", an unexpected label) has no rank and is never relaxed. +var severityRank = map[string]int{"low": 1, "medium": 2, "high": 3, "critical": 4} + +// Threshold returns the minimum severity rank (1 low … 4 critical) a finding needs to block. +// Blank, missing or invalid means low, so nothing is filtered. +func Threshold() int { + return thresholdIn(Path()) +} + +func thresholdIn(path string) int { + value, found := valueIn(path, thresholdKey) + if !found { + return 1 + } + if rank, ok := severityRank[strings.ToLower(strings.TrimSpace(value))]; ok { + return rank + } + return 1 +} + +// BelowThreshold reports whether a deny whose highest severity is `severity` should be let through +// because it is under cx_severity_threshold. An unranked severity returns false (keep blocking). +func BelowThreshold(severity string) bool { + rank, ok := severityRank[strings.ToLower(strings.TrimSpace(severity))] + return ok && rank < Threshold() +} diff --git a/internal/commands/agenthooks/scannerconfig/scannerconfig_test.go b/internal/commands/agenthooks/scannerconfig/scannerconfig_test.go new file mode 100644 index 000000000..3353059f9 --- /dev/null +++ b/internal/commands/agenthooks/scannerconfig/scannerconfig_test.go @@ -0,0 +1,138 @@ +//go:build !integration + +package scannerconfig + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func write(t *testing.T, body string) string { + t.Helper() + p := filepath.Join(t.TempDir(), fileName) + if err := os.WriteFile(p, []byte(body), 0o600); err != nil { + t.Fatal(err) + } + return p +} + +func TestEnabledDefaults(t *testing.T) { + if !enabledIn("", ASCA) { + t.Error("empty path must mean enabled") + } + if !enabledIn(filepath.Join(t.TempDir(), "missing"), SCA) { + t.Error("missing file must mean enabled") + } + if !enabledIn(write(t, "# nothing set\n"), KICS) { + t.Error("absent key must mean enabled") + } +} + +func TestEnabledFalseValues(t *testing.T) { + for _, v := range []string{"false", "FALSE", "0", "no", "off", "Disabled", " false "} { + if enabledIn(write(t, "cx_asca_scanner_enabled="+v+"\n"), ASCA) { + t.Errorf("%q should disable", v) + } + } +} + +func TestEnabledGarbageStaysOn(t *testing.T) { + for _, v := range []string{"flase", "", "banana", "2", "true"} { + if !enabledIn(write(t, "cx_kics_scanner_enabled="+v+"\n"), KICS) { + t.Errorf("%q must stay enabled", v) + } + } +} + +func TestKeysAreIndependent(t *testing.T) { + p := write(t, "cx_sca_scanner_enabled=false\ncx_secret_scanner_enabled=true\n") + if enabledIn(p, SCA) || !enabledIn(p, ASCA) || !enabledIn(p, KICS) || !enabledIn(p, Secrets) { + t.Error("only SCA should be disabled") + } +} + +func TestCommentedLineIgnoredAndLastWins(t *testing.T) { + if !enabledIn(write(t, "# cx_asca_scanner_enabled=false\n"), ASCA) { + t.Error("commented key must be ignored") + } + if !enabledIn(write(t, "cx_asca_scanner_enabled=false\ncx_asca_scanner_enabled=true\n"), ASCA) { + t.Error("last occurrence should win") + } +} + +func TestBOMAndCRLF(t *testing.T) { + p := write(t, "\xef\xbb\xbfcx_secret_scanner_enabled=false\r\ncx_asca_scanner_enabled=true\r\n") + if enabledIn(p, Secrets) || !enabledIn(p, ASCA) { + t.Error("BOM/CRLF file misparsed") + } +} + +func TestOversizedFailsOpen(t *testing.T) { + p := write(t, strings.Repeat("# pad\n", 5000)+"cx_asca_scanner_enabled=false\n") + if !enabledIn(p, ASCA) { + t.Error("oversized file must fail open to enabled") + } +} + +func TestPathUsesHome(t *testing.T) { + dir := t.TempDir() + t.Setenv("HOME", dir) + t.Setenv("USERPROFILE", dir) + if got := Path(); got != filepath.Join(dir, ".checkmarx", fileName) { + t.Errorf("unexpected path %q", got) + } + _ = os.MkdirAll(filepath.Join(dir, ".checkmarx"), 0o755) + _ = os.WriteFile(Path(), []byte("cx_kics_scanner_enabled=off\n"), 0o600) + if Enabled(KICS) || !Enabled(ASCA) { + t.Error("Enabled should read the file under the user's home") + } +} + +func TestThresholdIn(t *testing.T) { + cases := map[string]int{ + "": 1, // no file content + "cx_severity_threshold=\n": 1, // blank + "cx_severity_threshold=low\n": 1, + "cx_severity_threshold=Medium\n": 2, + "cx_severity_threshold= HIGH \n": 3, + "cx_severity_threshold=critical\n": 4, + "cx_severity_threshold=hihg\n": 1, // invalid + "# cx_severity_threshold=high\n": 1, // commented + "cx_severity_threshold=high\ncx_severity_threshold=low\n": 1, // last wins + } + for body, want := range cases { + if got := thresholdIn(write(t, body)); got != want { + t.Errorf("%q: got %d, want %d", body, got, want) + } + } + if thresholdIn(filepath.Join(t.TempDir(), "missing")) != 1 || thresholdIn("") != 1 { + t.Error("missing file / path must mean low") + } +} + +func TestBelowThreshold(t *testing.T) { + dir := t.TempDir() + t.Setenv("HOME", dir) + t.Setenv("USERPROFILE", dir) + _ = os.MkdirAll(filepath.Join(dir, ".checkmarx"), 0o755) + set := func(body string) { + if err := os.WriteFile(Path(), []byte(body), 0o600); err != nil { + t.Fatal(err) + } + } + set("cx_severity_threshold=high\n") + for sev, want := range map[string]bool{ + "Low": true, "MEDIUM": true, "High": false, "Critical": false, + "": false, "Malicious": false, "weird": false, // unranked is never relaxed + } { + if got := BelowThreshold(sev); got != want { + t.Errorf("high threshold, %q: got %v, want %v", sev, got, want) + } + } + set("cx_severity_threshold=\n") + if BelowThreshold("Low") { + t.Error("blank threshold must filter nothing") + } +} diff --git a/internal/commands/data/manifests/requirements.txt b/internal/commands/data/manifests/requirements.txt index 9f6f443a3..dc56c7a57 100644 --- a/internal/commands/data/manifests/requirements.txt +++ b/internal/commands/data/manifests/requirements.txt @@ -29,7 +29,7 @@ pandas==2.2.3 # via # -r requirements.in # seaborn -pillow==11.1.0 +pillow==13.0.0 # via matplotlib pyparsing==3.2.1 # via matplotlib @@ -51,16 +51,16 @@ tzdata==2025.1 # Exact version -flask==3.1.2 +flask==3.1.3 werkzeug>=3.0.6 # Range: greater than or equal and less than -Django>=3.0,<6.0 +celery>=4.0,<5.0 # Less than or equal -requests<=2.32.4 +requests<=2.33.0 # Compatible release (PEP 440) @@ -80,7 +80,7 @@ package\_with\_extras\[security,docs]==0.1.0 # Environment marker (skip on Python>=3.8) -scipy==1.5.2; python_version < "3.8" +scipy==1.10.0; python_version < "3.8" # Combined ranges with comma @@ -88,7 +88,7 @@ celery>=4.0,<5.0 # Inline comment -gevent==21.8.0 # pinned to a known-good version +gevent==23.9.0 # pinned to a known-good version # Full-line comment below should be ignored diff --git a/internal/commands/scan.go b/internal/commands/scan.go index 1a7969013..60fca692f 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -2905,7 +2905,12 @@ func runCreateScanCommand( scanResponseModel = enrichScanResponseModel(cmd, scanResponseModel) err = printByScanInfoFormat(cmd, toScanView(scanResponseModel)) if err != nil { - return errors.Wrapf(err, "%s\n", failedCreating) + scanInfoFormat, _ := cmd.Flags().GetString(commonParams.ScanInfoFormatFlag) + return errors.Errorf( + "Scan %s was created successfully and is currently running. "+ + "However, scan info won't be returned because the specified format %q is not supported. "+ + "Supported formats: list, table, json.", + scanResponseModel.ID, scanInfoFormat) } } // Wait until the scan is done: Queued, Running diff --git a/internal/services/realtimeengine/secretsrealtime/secrets-realtime.go b/internal/services/realtimeengine/secretsrealtime/secrets-realtime.go index a4ab60914..406261caf 100644 --- a/internal/services/realtimeengine/secretsrealtime/secrets-realtime.go +++ b/internal/services/realtimeengine/secretsrealtime/secrets-realtime.go @@ -80,13 +80,8 @@ func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath, ignoredFilePat return nil, errorconstants.NewRealtimeEngineError(errorconstants.RealtimeEngineFilePathRequired).Error() } - if enabled, err := realtimeengine.IsFeatureFlagEnabled(s.FeatureFlagWrapper, wrappers.OssRealtimeEnabled); err != nil || !enabled { - logger.PrintfIfVerbose("Failed to print OSS Realtime scan results: %v", err) - return nil, errorconstants.NewRealtimeEngineError(errorconstants.RealtimeEngineNotAvailable).Error() - } - - if err := realtimeengine.EnsureLicense(s.JwtWrapper); err != nil { - return nil, errorconstants.NewRealtimeEngineError(err.Error()).Error() + if err := s.ensureReady(); err != nil { + return nil, err } if err := realtimeengine.ValidateFilePath(filePath); err != nil { @@ -100,7 +95,35 @@ func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath, ignoredFilePat return nil, errorconstants.NewRealtimeEngineError("failed to read file").Error() } - report, err := runScan(filePath, content) + return finishScan(filePath, content, ignoredFilePath) +} + +// ScanContent runs the secrets scanner on content that is not yet on disk. +// sourcePath is reported as the finding file path (the agent's target file). +// ignoredFilePath filters findings the user suppressed via cx ignore-vulnerability. +func (s *SecretsRealtimeService) ScanContent(sourcePath, content, ignoredFilePath string) ([]SecretsRealtimeResult, error) { + if sourcePath == "" { + return nil, errorconstants.NewRealtimeEngineError(errorconstants.RealtimeEngineFilePathRequired).Error() + } + if err := s.ensureReady(); err != nil { + return nil, err + } + return finishScan(sourcePath, content, ignoredFilePath) +} + +func (s *SecretsRealtimeService) ensureReady() error { + if enabled, err := realtimeengine.IsFeatureFlagEnabled(s.FeatureFlagWrapper, wrappers.OssRealtimeEnabled); err != nil || !enabled { + logger.PrintfIfVerbose("Failed to print OSS Realtime scan results: %v", err) + return errorconstants.NewRealtimeEngineError(errorconstants.RealtimeEngineNotAvailable).Error() + } + if err := realtimeengine.EnsureLicense(s.JwtWrapper); err != nil { + return errorconstants.NewRealtimeEngineError(err.Error()).Error() + } + return nil +} + +func finishScan(sourcePath, content, ignoredFilePath string) ([]SecretsRealtimeResult, error) { + report, err := runScan(sourcePath, content) if err != nil { logger.PrintfIfVerbose("Failed to run scan: %v", err) return nil, errorconstants.NewRealtimeEngineError("failed to run secrets scan").Error() @@ -109,6 +132,9 @@ func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath, ignoredFilePat results := convertToSecretsRealtimeResult(report) resultsPerLineMap := createResultsPerLocationMap(results) results = filterGenericAPIKeyVulIfNeeded(results, resultsPerLineMap) + for i := range results { + results[i].FilePath = sourcePath + } if ignoredFilePath == "" { return results, nil @@ -118,9 +144,7 @@ func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath, ignoredFilePat logger.PrintfIfVerbose("secrets-realtime: failed to load ignore file %s: %v; continuing without ignore filtering", ignoredFilePath, err) return results, nil } - ignoreMap := buildIgnoreMap(ignoredSecrets) - results = filterIgnoredSecrets(results, ignoreMap) - return results, nil + return filterIgnoredSecrets(results, buildIgnoreMap(ignoredSecrets)), nil } func readFile(filePath string) (string, error) { diff --git a/internal/services/realtimeengine/secretsrealtime/secrets-realtime_test.go b/internal/services/realtimeengine/secretsrealtime/secrets-realtime_test.go index 37a78ca1b..4eb3b93fc 100644 --- a/internal/services/realtimeengine/secretsrealtime/secrets-realtime_test.go +++ b/internal/services/realtimeengine/secretsrealtime/secrets-realtime_test.go @@ -344,3 +344,27 @@ func TestGetSeverity_EmptyStatus_ReturnsHigh(t *testing.T) { assert.Equal(t, highSeverity, severity) } + +func TestScanContent_ReportsSourcePathAndHonorsIgnoreFile(t *testing.T) { + mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.OssRealtimeEnabled, Status: true} + + service := &SecretsRealtimeService{ + JwtWrapper: &mock.JWTMockWrapper{}, + FeatureFlagWrapper: &mock.FeatureFlagsMockWrapper{}, + } + content := "token = \"ghp_1234567890abcdef1234567890abcdef12345678\"" + results, err := service.ScanContent("app.env", content, "") + assert.NoError(t, err) + assert.NotEmpty(t, results) + assert.Equal(t, "app.env", results[0].FilePath) + assert.Equal(t, "github-pat", results[0].Title) + + raw, err := json.Marshal([]IgnoredSecret{{Title: results[0].Title, SecretValue: results[0].SecretValue}}) + assert.NoError(t, err) + ignoreFile := filepath.Join(t.TempDir(), "ignore.json") + assert.NoError(t, os.WriteFile(ignoreFile, raw, 0600)) + + filtered, err := service.ScanContent("app.env", content, ignoreFile) + assert.NoError(t, err) + assert.Empty(t, filtered) +} diff --git a/test/integration/data/manifests/requirements.txt b/test/integration/data/manifests/requirements.txt index 66b3a4c3a..58a047bd7 100644 --- a/test/integration/data/manifests/requirements.txt +++ b/test/integration/data/manifests/requirements.txt @@ -29,7 +29,7 @@ pandas==2.2.3 # via # -r requirements.in # seaborn -pillow==11.1.0 +pillow==13.0.0 # via matplotlib pyparsing==3.2.1 # via matplotlib @@ -51,16 +51,16 @@ tzdata==2025.1 # Exact version -flask==3.1.2 +flask==3.1.3 werkzeug>=3.0.6 # Range: greater than or equal and less than -Django>=3.0,<6.0 +celery>=4.0,<5.0 # Less than or equal -requests<=2.32.4 +requests<=2.33.0 # Compatible release (PEP 440) @@ -80,7 +80,7 @@ package\_with\_extras\[security,docs]==0.1.0 # Environment marker (skip on Python>=3.8) -scipy==1.5.2; python_version < "3.8" +scipy==1.10.0; python_version < "3.8" # Combined ranges with comma @@ -88,7 +88,7 @@ celery>=4.0,<5.0 # Inline comment -gevent==21.8.0 # pinned to a known-good version +gevent==23.9.0 # pinned to a known-good version # Full-line comment below should be ignored