Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kargo-cli for openSUSE:Factory 
checked in at 2026-03-05 17:16:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kargo-cli (Old)
 and      /work/SRC/openSUSE:Factory/.kargo-cli.new.561 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kargo-cli"

Thu Mar  5 17:16:11 2026 rev:47 rq:1336636 version:1.9.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/kargo-cli/kargo-cli.changes      2026-03-02 
17:39:39.761692932 +0100
+++ /work/SRC/openSUSE:Factory/.kargo-cli.new.561/kargo-cli.changes     
2026-03-05 17:24:22.169602850 +0100
@@ -1,0 +2,6 @@
+Tue Mar 03 05:44:22 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- Update to version 1.9.5:
+  no CLI-related changes or dependency updates
+
+-------------------------------------------------------------------

Old:
----
  kargo-cli-1.9.4.obscpio

New:
----
  kargo-cli-1.9.5.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kargo-cli.spec ++++++
--- /var/tmp/diff_new_pack.6ro9G4/_old  2026-03-05 17:24:23.437654161 +0100
+++ /var/tmp/diff_new_pack.6ro9G4/_new  2026-03-05 17:24:23.441654323 +0100
@@ -19,7 +19,7 @@
 %define executable_name kargo
 
 Name:           kargo-cli
-Version:        1.9.4
+Version:        1.9.5
 Release:        0
 Summary:        CLI for the Kubernetes Application lifecycle orchestration
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.6ro9G4/_old  2026-03-05 17:24:23.485656104 +0100
+++ /var/tmp/diff_new_pack.6ro9G4/_new  2026-03-05 17:24:23.493656427 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/akuity/kargo</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v1.9.4</param>
+    <param name="revision">v1.9.5</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.6ro9G4/_old  2026-03-05 17:24:23.517657398 +0100
+++ /var/tmp/diff_new_pack.6ro9G4/_new  2026-03-05 17:24:23.521657560 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/akuity/kargo</param>
-              <param 
name="changesrevision">fefda31245c559f016baac40d3fcd20674315e44</param></service></servicedata>
+              <param 
name="changesrevision">fd25620c2473ed19bec4be4d0f181287ef0f0391</param></service></servicedata>
 (No newline at EOF)
 

++++++ kargo-cli-1.9.4.obscpio -> kargo-cli-1.9.5.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kargo-cli-1.9.4/pkg/net/safe_dialer.go 
new/kargo-cli-1.9.5/pkg/net/safe_dialer.go
--- old/kargo-cli-1.9.4/pkg/net/safe_dialer.go  1970-01-01 01:00:00.000000000 
+0100
+++ new/kargo-cli-1.9.5/pkg/net/safe_dialer.go  2026-03-02 21:00:56.000000000 
+0100
@@ -0,0 +1,82 @@
+package net
+
+import (
+       "context"
+       "fmt"
+       "net"
+       "net/http"
+       "time"
+)
+
+var (
+       linkLocalV4 = net.IPNet{
+               IP:   net.IP{169, 254, 0, 0},
+               Mask: net.CIDRMask(16, 32),
+       }
+       linkLocalV6 = net.IPNet{
+               IP:   net.ParseIP("fe80::"),
+               Mask: net.CIDRMask(10, 128),
+       }
+)
+
+// isLinkLocal returns true if the given IP is in the IPv4 link-local range
+// (169.254.0.0/16) or the IPv6 link-local range (fe80::/10).
+func isLinkLocal(ip net.IP) bool {
+       return linkLocalV4.Contains(ip) || linkLocalV6.Contains(ip)
+}
+
+// SafeDialContext returns a DialContext function that blocks connections to
+// link-local IP addresses (169.254.0.0/16 and fe80::/10). This prevents SSRF
+// attacks targeting cloud instance metadata endpoints (e.g. 169.254.169.254).
+//
+// The returned function resolves the hostname before connecting and rejects 
the
+// connection if all resolved addresses are link-local.
+func SafeDialContext(dialer *net.Dialer) func(
+       ctx context.Context,
+       network string,
+       addr string,
+) (net.Conn, error) {
+       return func(ctx context.Context, network, addr string) (net.Conn, 
error) {
+               host, port, err := net.SplitHostPort(addr)
+               if err != nil {
+                       return nil, fmt.Errorf("failed to parse address %q: 
%w", addr, err)
+               }
+
+               // Resolve the hostname to IP addresses.
+               ips, err := net.DefaultResolver.LookupIPAddr(ctx, host)
+               if err != nil {
+                       return nil, fmt.Errorf("failed to resolve host %q: %w", 
host, err)
+               }
+
+               // Filter out link-local addresses.
+               var safe []net.IPAddr
+               for _, ip := range ips {
+                       if !isLinkLocal(ip.IP) {
+                               safe = append(safe, ip)
+                       }
+               }
+
+               if len(safe) == 0 {
+                       return nil, fmt.Errorf(
+                               "connections to link-local addresses are not 
permitted "+
+                                       "(host %q resolved to link-local IPs 
only)",
+                               host,
+                       )
+               }
+
+               // Dial using the first safe address.
+               safeAddr := net.JoinHostPort(safe[0].IP.String(), port)
+               return dialer.DialContext(ctx, network, safeAddr)
+       }
+}
+
+// SafeTransport wraps the given transport's DialContext to block connections 
to
+// link-local IP addresses.
+func SafeTransport(t *http.Transport) *http.Transport {
+       dialer := &net.Dialer{
+               Timeout:   30 * time.Second,
+               KeepAlive: 30 * time.Second,
+       }
+       t.DialContext = SafeDialContext(dialer)
+       return t
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kargo-cli-1.9.4/pkg/net/safe_dialer_test.go 
new/kargo-cli-1.9.5/pkg/net/safe_dialer_test.go
--- old/kargo-cli-1.9.4/pkg/net/safe_dialer_test.go     1970-01-01 
01:00:00.000000000 +0100
+++ new/kargo-cli-1.9.5/pkg/net/safe_dialer_test.go     2026-03-02 
21:00:56.000000000 +0100
@@ -0,0 +1,88 @@
+package net
+
+import (
+       "net"
+       "testing"
+
+       "github.com/stretchr/testify/assert"
+)
+
+func Test_isLinkLocal(t *testing.T) {
+       tests := []struct {
+               name     string
+               ip       string
+               expected bool
+       }{
+               {
+                       name:     "IPv4 link-local lower bound",
+                       ip:       "169.254.0.0",
+                       expected: true,
+               },
+               {
+                       name:     "IPv4 link-local metadata endpoint",
+                       ip:       "169.254.169.254",
+                       expected: true,
+               },
+               {
+                       name:     "IPv4 link-local upper bound",
+                       ip:       "169.254.255.255",
+                       expected: true,
+               },
+               {
+                       name:     "IPv4 just below link-local range",
+                       ip:       "169.253.255.255",
+                       expected: false,
+               },
+               {
+                       name:     "IPv4 just above link-local range",
+                       ip:       "169.255.0.0",
+                       expected: false,
+               },
+               {
+                       name:     "IPv4 private 10.x",
+                       ip:       "10.0.0.1",
+                       expected: false,
+               },
+               {
+                       name:     "IPv4 public",
+                       ip:       "8.8.8.8",
+                       expected: false,
+               },
+               {
+                       name:     "IPv4 loopback",
+                       ip:       "127.0.0.1",
+                       expected: false,
+               },
+               {
+                       name:     "IPv6 link-local",
+                       ip:       "fe80::1",
+                       expected: true,
+               },
+               {
+                       name:     "IPv6 link-local upper bound",
+                       ip:       "febf::ffff",
+                       expected: true,
+               },
+               {
+                       name:     "IPv6 just outside link-local",
+                       ip:       "fec0::1",
+                       expected: false,
+               },
+               {
+                       name:     "IPv6 loopback",
+                       ip:       "::1",
+                       expected: false,
+               },
+               {
+                       name:     "IPv6 public",
+                       ip:       "2001:db8::1",
+                       expected: false,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       ip := net.ParseIP(tt.ip)
+                       assert.Equal(t, tt.expected, isLinkLocal(ip))
+               })
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kargo-cli-1.9.4/pkg/promotion/runner/builtin/http_downloader.go 
new/kargo-cli-1.9.5/pkg/promotion/runner/builtin/http_downloader.go
--- old/kargo-cli-1.9.4/pkg/promotion/runner/builtin/http_downloader.go 
2026-02-27 17:07:48.000000000 +0100
+++ new/kargo-cli-1.9.5/pkg/promotion/runner/builtin/http_downloader.go 
2026-03-02 21:00:56.000000000 +0100
@@ -18,6 +18,7 @@
        kargoapi "github.com/akuity/kargo/api/v1alpha1"
        "github.com/akuity/kargo/pkg/io/fs"
        "github.com/akuity/kargo/pkg/logging"
+       kargonet "github.com/akuity/kargo/pkg/net"
        "github.com/akuity/kargo/pkg/promotion"
        "github.com/akuity/kargo/pkg/x/promotion/runner/builtin"
 )
@@ -156,6 +157,8 @@
                return nil, fmt.Errorf("error creating HTTP client: %w", err)
        }
 
+       // #nosec G704 -- The client is using a custom dialer that mitigates 
the worst
+       // practical risks of SSRF by refusing to dial link-local addresses.
        resp, err := client.Do(req)
        if err != nil {
                return nil, fmt.Errorf("error sending HTTP request: %w", err)
@@ -190,7 +193,7 @@
 
 // buildHTTPClient creates an HTTP client with the specified configuration.
 func (d *httpDownloader) buildHTTPClient(cfg builtin.HTTPDownloadConfig) 
(*http.Client, error) {
-       httpTransport := cleanhttp.DefaultTransport()
+       httpTransport := kargonet.SafeTransport(cleanhttp.DefaultTransport())
        if cfg.InsecureSkipTLSVerify {
                httpTransport.TLSClientConfig = &tls.Config{
                        InsecureSkipVerify: true, // nolint: gosec
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kargo-cli-1.9.4/pkg/promotion/runner/builtin/http_requester.go 
new/kargo-cli-1.9.5/pkg/promotion/runner/builtin/http_requester.go
--- old/kargo-cli-1.9.4/pkg/promotion/runner/builtin/http_requester.go  
2026-02-27 17:07:48.000000000 +0100
+++ new/kargo-cli-1.9.5/pkg/promotion/runner/builtin/http_requester.go  
2026-03-02 21:00:56.000000000 +0100
@@ -19,6 +19,7 @@
        kargoapi "github.com/akuity/kargo/api/v1alpha1"
        "github.com/akuity/kargo/pkg/io"
        "github.com/akuity/kargo/pkg/logging"
+       kargonet "github.com/akuity/kargo/pkg/net"
        "github.com/akuity/kargo/pkg/promotion"
        "github.com/akuity/kargo/pkg/x/promotion/runner/builtin"
 )
@@ -95,6 +96,8 @@
                return promotion.StepResult{Status: 
kargoapi.PromotionStepStatusErrored},
                        &promotion.TerminalError{Err: fmt.Errorf("error 
creating HTTP client: %w", err)}
        }
+       // #nosec G704 -- The client is using a custom dialer that mitigates 
the worst
+       // practical risks of SSRF by refusing to dial link-local addresses.
        resp, err := client.Do(req)
        if err != nil {
                return promotion.StepResult{Status: 
kargoapi.PromotionStepStatusErrored},
@@ -247,7 +250,7 @@
 }
 
 func (h *httpRequester) getClient(cfg builtin.HTTPConfig) (*http.Client, 
error) {
-       httpTransport := cleanhttp.DefaultTransport()
+       httpTransport := kargonet.SafeTransport(cleanhttp.DefaultTransport())
        if cfg.InsecureSkipTLSVerify {
                httpTransport.TLSClientConfig = &tls.Config{
                        InsecureSkipVerify: true, // nolint: gosec

++++++ kargo-cli.obsinfo ++++++
--- /var/tmp/diff_new_pack.6ro9G4/_old  2026-03-05 17:24:27.609822985 +0100
+++ /var/tmp/diff_new_pack.6ro9G4/_new  2026-03-05 17:24:27.621823471 +0100
@@ -1,5 +1,5 @@
 name: kargo-cli
-version: 1.9.4
-mtime: 1772208468
-commit: fefda31245c559f016baac40d3fcd20674315e44
+version: 1.9.5
+mtime: 1772481656
+commit: fd25620c2473ed19bec4be4d0f181287ef0f0391
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/kargo-cli/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.kargo-cli.new.561/vendor.tar.gz differ: char 13, 
line 1

Reply via email to