Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package melange for openSUSE:Factory checked 
in at 2026-03-02 17:39:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/melange (Old)
 and      /work/SRC/openSUSE:Factory/.melange.new.29461 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "melange"

Mon Mar  2 17:39:48 2026 rev:141 rq:1335691 version:0.43.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/melange/melange.changes  2026-02-25 
21:11:32.112557720 +0100
+++ /work/SRC/openSUSE:Factory/.melange.new.29461/melange.changes       
2026-03-02 17:39:58.114458951 +0100
@@ -1,0 +2,22 @@
+Mon Mar 02 06:17:10 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- Update to version 0.43.4:
+  * build(deps): bump actions/download-artifact from 7.0.0 to 8.0.0
+    (#2380)
+  * build(deps): bump actions/upload-artifact from 6.0.0 to 7.0.0
+    (#2381)
+  * fix(qemu): respect memory limits in pods (#2382)
+  * Fix melange parsing error line numbers (#2379)
+  * Add `shallow-submodules` and `submodule-jobs` options for
+    `git-checkout` (#2368)
+  * build(deps): bump actions/setup-go in the actions group (#2378)
+  * build(deps): bump github.com/cloudflare/circl from 1.6.1 to
+    1.6.3 (#2377)
+  * build(deps): bump github.com/go-git/go-git/v5 from 5.16.5 to
+    5.17.0 (#2375)
+  * build(deps): bump step-security/harden-runner in the actions
+    group (#2376)
+  * build(deps): bump github.com/google/go-containerregistry
+    (#2372)
+
+-------------------------------------------------------------------

Old:
----
  melange-0.43.3.obscpio

New:
----
  melange-0.43.4.obscpio

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

Other differences:
------------------
++++++ melange.spec ++++++
--- /var/tmp/diff_new_pack.pq7DqA/_old  2026-03-02 17:39:59.798529242 +0100
+++ /var/tmp/diff_new_pack.pq7DqA/_new  2026-03-02 17:39:59.802529409 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           melange
-Version:        0.43.3
+Version:        0.43.4
 Release:        0
 Summary:        Build APKs from source code
 License:        Apache-2.0
@@ -26,8 +26,8 @@
 Source1:        vendor.tar.gz
 BuildRequires:  bash-completion
 BuildRequires:  fish
+BuildRequires:  go1.25 >= 1.25.6
 BuildRequires:  zsh
-BuildRequires:  golang(API) >= 1.25
 
 %description
 Build apk packages using declarative pipelines.

++++++ _service ++++++
--- /var/tmp/diff_new_pack.pq7DqA/_old  2026-03-02 17:39:59.838530912 +0100
+++ /var/tmp/diff_new_pack.pq7DqA/_new  2026-03-02 17:39:59.842531079 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/chainguard-dev/melange</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v0.43.3</param>
+    <param name="revision">v0.43.4</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.pq7DqA/_old  2026-03-02 17:39:59.866532080 +0100
+++ /var/tmp/diff_new_pack.pq7DqA/_new  2026-03-02 17:39:59.870532248 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/chainguard-dev/melange</param>
-              <param 
name="changesrevision">66e9282b26b7537ac33b130a3499d9119a0e52f1</param></service></servicedata>
+              <param 
name="changesrevision">ba26216d9671b7fd8e2696a3a217f441f2e04b05</param></service></servicedata>
 (No newline at EOF)
 

++++++ melange-0.43.3.obscpio -> melange-0.43.4.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/go.mod new/melange-0.43.4/go.mod
--- old/melange-0.43.3/go.mod   2026-02-24 17:32:40.000000000 +0100
+++ new/melange-0.43.4/go.mod   2026-02-27 23:24:42.000000000 +0100
@@ -12,9 +12,9 @@
        github.com/docker/docker v28.5.2+incompatible
        github.com/dprotaso/go-yit v0.0.0-20250513224043-18a80f8f6df4
        github.com/github/go-spdx/v2 v2.4.0
-       github.com/go-git/go-git/v5 v5.16.5
+       github.com/go-git/go-git/v5 v5.17.0
        github.com/google/go-cmp v0.7.0
-       github.com/google/go-containerregistry v0.21.0
+       github.com/google/go-containerregistry v0.21.1
        github.com/google/licenseclassifier/v2 v2.0.0
        github.com/ijt/goparsify v0.0.0-20221203142333-3a5276334b8d
        github.com/in-toto/attestation v1.1.2
@@ -94,7 +94,7 @@
        github.com/charmbracelet/x/ansi v0.10.1 // indirect
        github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
        github.com/charmbracelet/x/term v0.2.1 // indirect
-       github.com/cloudflare/circl v1.6.1 // indirect
+       github.com/cloudflare/circl v1.6.3 // indirect
        github.com/common-nighthawk/go-figure 
v0.0.0-20210622060536-734e95fb86be // indirect
        github.com/containerd/containerd/v2 v2.1.5 // indirect
        github.com/containerd/log v0.1.0 // indirect
@@ -110,7 +110,7 @@
        github.com/emirpasic/gods v1.18.1 // indirect
        github.com/felixge/httpsnoop v1.0.4 // indirect
        github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
-       github.com/go-git/go-billy/v5 v5.6.2 // indirect
+       github.com/go-git/go-billy/v5 v5.8.0 // indirect
        github.com/go-jose/go-jose/v3 v3.0.4 // indirect
        github.com/go-logfmt/logfmt v0.6.0 // indirect
        github.com/go-logr/logr v1.4.3 // indirect
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/go.sum new/melange-0.43.4/go.sum
--- old/melange-0.43.3/go.sum   2026-02-24 17:32:40.000000000 +0100
+++ new/melange-0.43.4/go.sum   2026-02-27 23:24:42.000000000 +0100
@@ -63,8 +63,8 @@
 github.com/clipperhouse/stringish v0.1.1/go.mod 
h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
 github.com/clipperhouse/uax29/v2 v2.3.0 
h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
 github.com/clipperhouse/uax29/v2 v2.3.0/go.mod 
h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
-github.com/cloudflare/circl v1.6.1 
h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
-github.com/cloudflare/circl v1.6.1/go.mod 
h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
+github.com/cloudflare/circl v1.6.3 
h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
+github.com/cloudflare/circl v1.6.3/go.mod 
h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod 
h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be 
h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ=
 github.com/common-nighthawk/go-figure 
v0.0.0-20210622060536-734e95fb86be/go.mod 
h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=
@@ -127,12 +127,12 @@
 github.com/gliderlabs/ssh v0.3.8/go.mod 
h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 
h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod 
h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
-github.com/go-git/go-billy/v5 v5.6.2 
h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
-github.com/go-git/go-billy/v5 v5.6.2/go.mod 
h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
+github.com/go-git/go-billy/v5 v5.8.0 
h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0=
+github.com/go-git/go-billy/v5 v5.8.0/go.mod 
h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY=
 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 
h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
 github.com/go-git/go-git-fixtures/v4 
v4.3.2-0.20231010084843-55a94097c399/go.mod 
h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
-github.com/go-git/go-git/v5 v5.16.5 
h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
-github.com/go-git/go-git/v5 v5.16.5/go.mod 
h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
+github.com/go-git/go-git/v5 v5.17.0 
h1:AbyI4xf+7DsjINHMu35quAh4wJygKBKBuXVjV/pxesM=
+github.com/go-git/go-git/v5 v5.17.0/go.mod 
h1:f82C4YiLx+Lhi8eHxltLeGC5uBTXSFa6PC5WW9o4SjI=
 github.com/go-jose/go-jose/v3 v3.0.4 
h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
 github.com/go-jose/go-jose/v3 v3.0.4/go.mod 
h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
 github.com/go-logfmt/logfmt v0.6.0 
h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
@@ -171,8 +171,8 @@
 github.com/google/go-cmp v0.5.9/go.mod 
h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 github.com/google/go-cmp v0.7.0/go.mod 
h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
-github.com/google/go-containerregistry v0.21.0 
h1:ocqxUOczFwAZQBMNE7kuzfqvDe0VWoZxQMOesXreCDI=
-github.com/google/go-containerregistry v0.21.0/go.mod 
h1:ctO5aCaewH4AK1AumSF5DPW+0+R+d2FmylMJdp5G7p0=
+github.com/google/go-containerregistry v0.21.1 
h1:sOt/o9BS2b87FnR7wxXPvRKU1XVJn2QCwOS5g8zQXlc=
+github.com/google/go-containerregistry v0.21.1/go.mod 
h1:ctO5aCaewH4AK1AumSF5DPW+0+R+d2FmylMJdp5G7p0=
 github.com/google/go-licenses/v2 v2.0.1 
h1:ti+9bi5o7DKbeeg5eBb/uZTgsaPNoJaLCh93cRcXsW8=
 github.com/google/go-licenses/v2 v2.0.1/go.mod 
h1:efibo0EDNGkau6AIMOViGW+rTNPudhxX9rCxtfw5zKE=
 github.com/google/go-replayers/httpreplay v1.2.0 
h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/pkg/build/compile.go 
new/melange-0.43.4/pkg/build/compile.go
--- old/melange-0.43.3/pkg/build/compile.go     2026-02-24 17:32:40.000000000 
+0100
+++ new/melange-0.43.4/pkg/build/compile.go     2026-02-27 23:24:42.000000000 
+0100
@@ -225,6 +225,11 @@
        // When compiling an already-compiled config, `uses` will be redundant 
and FYI only,
        // so ignore it if there is also a `pipelines` spelled out.
        if uses != "" && len(pipeline.Pipeline) == 0 {
+               // Validate that 'uses' does not contain path traversal 
sequences or absolute paths.
+               if filepath.IsAbs(uses) || strings.Contains(uses, "..") {
+                       return fmt.Errorf("invalid pipeline 'uses' value %q: 
must not contain absolute paths or '..' sequences", uses)
+               }
+
                var data []byte
                // Set this to fail up front in case there are no pipeline dirs 
specified
                // and we can't find them.
@@ -232,7 +237,12 @@
 
                for _, pd := range c.PipelineDirs {
                        log.Debugf("trying to load pipeline %q from %q", uses, 
pd)
-                       data, err = os.ReadFile(filepath.Join(pd, 
uses+".yaml")) // #nosec G304 - Loading pipeline definition from configured 
directory
+                       target := filepath.Join(pd, uses+".yaml")
+                       // Verify the resolved path is still within the 
pipeline directory.
+                       if rel, err := filepath.Rel(pd, 
filepath.Clean(target)); err != nil || strings.HasPrefix(rel, "..") {
+                               return fmt.Errorf("pipeline 'uses' value %q 
resolves outside pipeline directory %q", uses, pd)
+                       }
+                       data, err = os.ReadFile(target) // #nosec G304 - 
Loading pipeline definition from configured directory
                        if err == nil {
                                log.Debugf("Found pipeline %s", string(data))
                                break
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/pkg/build/pipelines/README.md 
new/melange-0.43.4/pkg/build/pipelines/README.md
--- old/melange-0.43.3/pkg/build/pipelines/README.md    2026-02-24 
17:32:40.000000000 +0100
+++ new/melange-0.43.4/pkg/build/pipelines/README.md    2026-02-27 
23:24:42.000000000 +0100
@@ -52,7 +52,9 @@
 | max-retries | false | Maximum number of retry attempts for git clone 
operation on failure.  | 3 |
 | recurse-submodules | false | Indicates whether --recurse-submodules should 
be passed to git clone.  | false |
 | repository | true | The repository to check out sources from.  |  |
+| shallow-submodules | false | Whether to use --shallow-submodules when 
recurse-submodules is true. Ignored if recurse-submodules is false.  | false |
 | sparse-paths | false | List of directory paths to checkout when using 
sparse-checkout (cone mode). This is useful for monorepos where you only need 
specific subdirectories. When specified, only these directories will be checked 
out from the repository. Uses cone mode for optimal performance. Example:   
sparse-paths:     - omnibump     - shared/lib  |  |
+| submodule-jobs | false | The number of concurrent jobs to use when 
recurse-submodules is true. Ignored if recurse-submodules is false.  | 1 |
 | tag | false | The tag to check out.  Branch and tag are mutually exclusive.  
|  |
 | type-hint | false | Type hint to use during SBOM generation for the provided 
git repository. This is primarily used to identify Gitlab based sources which 
are not heuristically identifiable as Gitlab.  Supported hints: gitlab.  |  |
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/pkg/build/pipelines/git-checkout.yaml 
new/melange-0.43.4/pkg/build/pipelines/git-checkout.yaml
--- old/melange-0.43.3/pkg/build/pipelines/git-checkout.yaml    2026-02-24 
17:32:40.000000000 +0100
+++ new/melange-0.43.4/pkg/build/pipelines/git-checkout.yaml    2026-02-27 
23:24:42.000000000 +0100
@@ -34,6 +34,16 @@
     description: |
       Indicates whether --recurse-submodules should be passed to git clone.
     default: false
+  shallow-submodules:
+    description: |
+      Whether to use --shallow-submodules when recurse-submodules is true.
+      Ignored if recurse-submodules is false.
+    default: false
+  submodule-jobs:
+    description: |
+      The number of concurrent jobs to use when recurse-submodules is true.
+      Ignored if recurse-submodules is false.
+    default: 1
   cherry-picks:
     description: |
       List of cherry picks to apply.
@@ -83,7 +93,8 @@
 pipeline:
   - runs: |
       #!/bin/sh
-      set -e
+      # shellcheck shell=busybox
+      set -eu
 
       msg() { echo "[git checkout]" "$@"; }
       fail() { msg FAIL "$@"; exit 1; }
@@ -98,7 +109,7 @@
           local attempt=0
           local backoff=$initial_backoff
 
-          while [ $attempt -le $max_retries ]; do
+          while [ $attempt -le "$max_retries" ]; do
               if [ $attempt -gt 0 ]; then
                   msg "Retry attempt $attempt/$max_retries after ${backoff}s 
backoff..."
               fi
@@ -108,7 +119,7 @@
               fi
 
               attempt=$((attempt + 1))
-              if [ $attempt -gt $max_retries ]; then
+              if [ $attempt -gt "$max_retries" ]; then
                   msg "All $max_retries retry attempts exhausted"
                   return 1
               fi
@@ -129,7 +140,7 @@
 
               # Exponential backoff: double the backoff time
               backoff=$((backoff * 2))
-              if [ $backoff -gt $max_backoff ]; then
+              if [ $backoff -gt "$max_backoff" ]; then
                   backoff=$max_backoff
               fi
           done
@@ -138,7 +149,7 @@
       }
 
       process_cherry_picks() {
-        local cpicksf="$1" oifs="$IFS" count=0
+        local cpicksf="$1" count=0
         local fetched_branches=""
         local sdate=${SOURCE_DATE_EPOCH:-0}
         if [ "$sdate" -lt 315532800 ]; then
@@ -166,7 +177,7 @@
             # Split the line into branch/hash and comment parts
             branch=${line%%:*}
             comment=${line#*:}
-            comment=$(set -f; echo $comment) # Strip leading/trailing 
whitespace
+            comment=$(set -f; echo "$comment") # Strip leading/trailing 
whitespace
 
             if [ -z "$comment" ]; then
                 msg "Empty comment for cherry-pick: $line"
@@ -186,7 +197,7 @@
             if [ -n "$branch" ]; then
                 case " $fetched_branches " in
                     *" $branch "*) ;;
-                    *) vr git fetch $unshallow_arg origin $branch:$branch || {
+                    *) vr git fetch $unshallow_arg origin "$branch:$branch" || 
{
                         msg "failed to fetch branch $branch"
                         return 1
                         }
@@ -216,15 +227,21 @@
           local tag=$5 expcommit=$6 recurse=${7:-false}
           local cherry_pick="$8" sparse_paths="$9"
           local max_retries="${10:-3}" initial_backoff="${11:-2}" 
max_backoff="${12:-60}"
+          local shallow_submodules="${13:-false}" submodule_jobs="${14:-1}"
           msg "repo='$repo' dest='$dest' depth='$depth' branch='$branch'" \
               "tag='$tag' expcommit='$expcommit' recurse='$recurse'" \
               "sparse_paths='$sparse_paths' max_retries='$max_retries'" \
-              "initial_backoff='$initial_backoff' max_backoff='$max_backoff'"
+              "initial_backoff='$initial_backoff' max_backoff='$max_backoff'" \
+              "shallow_submodules='$shallow_submodules' 
submodule_jobs='$submodule_jobs'"
 
           case "$recurse" in
               true|false) :;;
               *) fail "recurse must be true or false, not '$recurse'"
           esac
+          case "$shallow_submodules" in
+              true|false) :;;
+              *) fail "shallow_submodules must be true or false, not 
'$shallow_submodules'"
+          esac
 
           [ -n "$repo" ] || fail "repository not provided"
 
@@ -242,12 +259,15 @@
           flags="--config=advice.detachedHead=false"
           [ -n "$branch" ] && flags="$flags --branch=$branch"
           [ -n "$tag" ] && flags="$flags --branch=$tag"
-          [ "$recurse" = "true" ] && flags="$flags --recurse-submodules"
+          if [ "$recurse" = "true" ] ; then
+              flags="$flags --recurse-submodules --jobs=$submodule_jobs"
+              [ "$shallow_submodules" = "true" ] && flags="$flags 
--shallow-submodules"
+          fi
           [ -n "$sparse_paths" ] && flags="$flags --sparse --filter=blob:none"
 
           if [ "$depth" = "unset" ]; then
             depth=1
-            if [ -n "$branch" -a -n "$expcommit" ]; then
+            if [ -n "$branch" ] && [ -n "$expcommit" ]; then
               # if we're just checking out a specific commit on a branch
               # then we need to get history, otherwise it will break
               # if the expected commit is not tip of the branch.
@@ -266,6 +286,7 @@
           vr git config --global --add safe.directory "$dest_fullpath"
 
           msg "Attempting git clone with retry (max_retries=$max_retries, 
initial_backoff=${initial_backoff}s, max_backoff=${max_backoff}s)"
+          # shellcheck disable=SC2086
           retry_with_backoff "$max_retries" "$initial_backoff" "$max_backoff" \
               git clone $quiet "--origin=$remote" \
               "--config=user.name=Melange Build" \
@@ -279,14 +300,15 @@
           # Configure sparse-checkout if paths were provided
           if [ -n "$sparse_paths" ]; then
               msg "Configuring sparse-checkout with paths: $sparse_paths"
-              vr git sparse-checkout set --cone $sparse_paths ||
+              vr git sparse-checkout set --cone "$sparse_paths" ||
                   fail "failed to configure sparse-checkout --filter=blob:none"
           fi
 
           msg "tar -c . | tar -C \"$dest_fullpath\" -x"
           ( tar -c . ; echo $? > "$rcfile") | tar -C "$dest_fullpath" -x 
--no-same-owner
+          # shellcheck disable=SC2162 # ash doesn't support read -f
           read rc < "$rcfile" || fail "failed to read rc file"
-          [ $rc -eq 0 ] || fail "tar creation in $workdir failed"
+          [ "$rc" -eq 0 ] || fail "tar creation in $workdir failed"
 
           rm -rf "$workdir"
           vr cd "$dest_fullpath"
@@ -313,7 +335,7 @@
           # git clone --branch=X will pick the branch X if there
           # exists both a tag and a branch by that name.
           # since a tag was given, we want the tag.
-          vr git fetch $quiet $remote ${depthflag:-"$depthflag"} --no-tags \
+          vr git fetch $quiet $remote "${depthflag:-"$depthflag"}" --no-tags \
               "+refs/tags/$tag:refs/$remote/tags/$tag"
           vr git checkout $quiet "$remote/tags/$tag"
 
@@ -362,6 +384,7 @@
           "${{inputs.recurse-submodules}}" "$cpickf" \
           "${{inputs.sparse-paths}}" \
           "${{inputs.max-retries}}" "${{inputs.initial-backoff}}" \
-          "${{inputs.max-backoff}}"
+          "${{inputs.max-backoff}}" \
+          "${{inputs.shallow-submodules}}" "${{inputs.submodule-jobs}}"
 
       rm -f "$cpickf"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/pkg/config/config.go 
new/melange-0.43.4/pkg/config/config.go
--- old/melange-0.43.3/pkg/config/config.go     2026-02-24 17:32:40.000000000 
+0100
+++ new/melange-0.43.4/pkg/config/config.go     2026-02-27 23:24:42.000000000 
+0100
@@ -22,6 +22,7 @@
        "encoding/hex"
        "errors"
        "fmt"
+       "io"
        "io/fs"
        "iter"
        "maps"
@@ -1568,24 +1569,23 @@
        }
        defer f.Close()
 
+       data, err := io.ReadAll(f)
+       if err != nil {
+               return nil, fmt.Errorf("reading %s: %w", configurationFilePath, 
err)
+       }
+
        root := yaml.Node{}
 
        cfg := Configuration{root: &root}
 
-       // Unmarshal into a node first
-       decoderNode := yaml.NewDecoder(f)
+       // Unmarshal into a node first, so renovate can operate on its AST.
+       decoderNode := yaml.NewDecoder(bytes.NewReader(data))
        err = decoderNode.Decode(&root)
        if err != nil {
                return nil, fmt.Errorf("unable to decode configuration file %q: 
%w", configurationFilePath, err)
        }
 
-       // XXX(Elizafox) - Node.Decode doesn't allow setting of KnownFields, so 
we do this cheesy hack below
-       data, err := yaml.Marshal(&root)
-       if err != nil {
-               return nil, fmt.Errorf("unable to decode configuration file %q: 
%w", configurationFilePath, err)
-       }
-
-       // Now unmarshal it into the struct, part of said cheesy hack
+       // Also unmarshal it into the struct.
        reader := bytes.NewReader(data)
        decoder := yaml.NewDecoder(reader)
        decoder.KnownFields(true)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/pkg/config/config_test.go 
new/melange-0.43.4/pkg/config/config_test.go
--- old/melange-0.43.3/pkg/config/config_test.go        2026-02-24 
17:32:40.000000000 +0100
+++ new/melange-0.43.4/pkg/config/config_test.go        2026-02-27 
23:24:42.000000000 +0100
@@ -2311,3 +2311,32 @@
                require.Equal(t, goodLicense, result["Apache-2.0"])
        })
 }
+
+func TestLineNumbersInError(t *testing.T) {
+       ctx := slogtest.Context(t)
+
+       fp := filepath.Join(os.TempDir(), 
"melange-test-applySubstitutionsInProvides")
+       if err := os.WriteFile(fp, []byte(`# line 1 is blank so that it's 
easier to read below
+package:
+  name: replacement-provides
+  version: 0.0.1
+  epoch: 7
+  description: example using a replacement in provides
+
+environment:
+  # this is a typo for "contents"
+  content:
+    packages:
+      - dep~${{package.version}}
+`), 0o644); err != nil {
+               t.Fatal(err)
+       }
+       _, err := ParseConfiguration(ctx, fp)
+       if err == nil {
+               t.Fatal("wanted err, got nil")
+       }
+
+       // This is a bit brittle and will break if we change yaml parsers,
+       // but what we use doesn't expose the line number in a structured way.
+       require.Contains(t, err.Error(), "line 10")
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/pkg/container/qemu_runner.go 
new/melange-0.43.4/pkg/container/qemu_runner.go
--- old/melange-0.43.3/pkg/container/qemu_runner.go     2026-02-24 
17:32:40.000000000 +0100
+++ new/melange-0.43.4/pkg/container/qemu_runner.go     2026-02-27 
23:24:42.000000000 +0100
@@ -1645,11 +1645,47 @@
        return num * multiplier / 1024, nil
 }
 
+// getCgroupMemoryLimitKB reads the cgroup memory limit for the current 
process.
+// It checks cgroup v2 first, then falls back to cgroup v1. Returns 0 if no
+// cgroup limit is found or the limit is effectively unlimited.
+func getCgroupMemoryLimitKB() int {
+       // cgroup v2: /sys/fs/cgroup/memory.max
+       if data, err := os.ReadFile("/sys/fs/cgroup/memory.max"); err == nil {
+               s := strings.TrimSpace(string(data))
+               if s != "max" {
+                       if bytes, err := strconv.ParseInt(s, 10, 64); err == 
nil && bytes > 0 {
+                               return int(bytes / 1024)
+                       }
+               }
+       }
+
+       // cgroup v1: /sys/fs/cgroup/memory/memory.limit_in_bytes
+       if data, err := 
os.ReadFile("/sys/fs/cgroup/memory/memory.limit_in_bytes"); err == nil {
+               s := strings.TrimSpace(string(data))
+               if bytes, err := strconv.ParseInt(s, 10, 64); err == nil && 
bytes > 0 {
+                       // cgroup v1 reports a very large number (close to max 
int64) when unlimited
+                       const unlimitedThreshold = 1 << 50 // ~1 PiB, well 
above any real limit
+                       if bytes < unlimitedThreshold {
+                               return int(bytes / 1024)
+                       }
+               }
+       }
+
+       return 0
+}
+
 func getAvailableMemoryKB() int {
        mem := 16000000
 
        switch runtime.GOOS {
        case "linux":
+               // Check cgroup limits first — in a container (e.g. Kubernetes 
pod),
+               // /proc/meminfo reports the entire node's memory, not the 
pod's allocation.
+               // The cgroup limit reflects the actual memory available to 
this process.
+               if cgroupMem := getCgroupMemoryLimitKB(); cgroupMem > 0 {
+                       return cgroupMem
+               }
+
                f, e := os.Open("/proc/meminfo")
                if e != nil {
                        return mem
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/pkg/linter/results.go 
new/melange-0.43.4/pkg/linter/results.go
--- old/melange-0.43.3/pkg/linter/results.go    2026-02-24 17:32:40.000000000 
+0100
+++ new/melange-0.43.4/pkg/linter/results.go    2026-02-27 23:24:42.000000000 
+0100
@@ -20,6 +20,7 @@
        "fmt"
        "os"
        "path/filepath"
+       "strings"
 
        "github.com/chainguard-dev/clog"
 
@@ -27,6 +28,14 @@
        "chainguard.dev/melange/pkg/linter/types"
 )
 
+// containsPathTraversal checks if a string contains path traversal sequences
+// or path separators that could be used to escape the intended directory.
+func containsPathTraversal(s string) bool {
+       return strings.Contains(s, "..") ||
+               strings.Contains(s, string(filepath.Separator)) ||
+               strings.Contains(s, "/")
+}
+
 // saveLintResults saves the lint results to JSON files in the packages 
directory
 func saveLintResults(ctx context.Context, cfg *config.Configuration, results 
map[string]*types.PackageLintResults, outputDir, arch string) error {
        log := clog.FromContext(ctx)
@@ -37,6 +46,11 @@
                return nil
        }
 
+       // Validate arch to prevent path traversal
+       if containsPathTraversal(arch) {
+               return fmt.Errorf("invalid arch %q: contains path traversal 
sequence", arch)
+       }
+
        // Ensure the package directory exists
        packageDir := filepath.Join(outputDir, arch)
        if err := os.MkdirAll(packageDir, 0o755); err != nil {
@@ -45,6 +59,10 @@
 
        // Save results for each package
        for pkgName, pkgResults := range results {
+               // Validate pkgName to prevent path traversal
+               if containsPathTraversal(pkgName) {
+                       return fmt.Errorf("invalid package name %q: contains 
path traversal sequence", pkgName)
+               }
                // Generate the filename: 
lint-{packagename}-{version}-r{epoch}.json
                filename := fmt.Sprintf("lint-%s-%s-r%d.json", pkgName, 
cfg.Package.Version, cfg.Package.Epoch)
                filepath := filepath.Join(packageDir, filename)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.43.3/pkg/renovate/cache/cache.go 
new/melange-0.43.4/pkg/renovate/cache/cache.go
--- old/melange-0.43.3/pkg/renovate/cache/cache.go      2026-02-24 
17:32:40.000000000 +0100
+++ new/melange-0.43.4/pkg/renovate/cache/cache.go      2026-02-27 
23:24:42.000000000 +0100
@@ -26,6 +26,7 @@
        "os"
        "path"
        "strings"
+       "time"
 
        "github.com/chainguard-dev/clog"
        "github.com/dprotaso/go-yit"
@@ -219,6 +220,12 @@
        return nil
 }
 
+// maxDownloadSize is the maximum allowed download size (1 GB).
+const maxDownloadSize = 1 << 30 // 1 GiB
+
+// downloadTimeout is the maximum time allowed for the entire download.
+const downloadTimeout = 30 * time.Minute
+
 // downloadFile downloads a file and returns a path to it in temporary storage.
 func downloadFile(ctx context.Context, uri string) (string, error) {
        targetFile, err := os.CreateTemp("", "melange-update-*")
@@ -227,6 +234,10 @@
        }
        defer targetFile.Close()
 
+       // Apply a timeout to the download context to prevent hanging 
connections.
+       ctx, cancel := context.WithTimeout(ctx, downloadTimeout)
+       defer cancel()
+
        client := &http.Client{
                CheckRedirect: func(req *http.Request, via []*http.Request) 
error {
                        // delete the referer header else redirects with 
sourceforge do not work well.  See 
https://stackoverflow.com/questions/67203383/downloading-from-sourceforge-wait-and-redirect
@@ -254,8 +265,15 @@
                return "", fmt.Errorf("unexpected status code %d (%s) when 
fetching %s", resp.StatusCode, resp.Status, uri)
        }
 
-       if _, err := io.Copy(targetFile, resp.Body); err != nil {
-               return "", err
+       // Limit the download size to prevent unbounded resource consumption.
+       limitedReader := io.LimitReader(resp.Body, maxDownloadSize+1)
+       n, err := io.Copy(targetFile, limitedReader)
+       if err != nil {
+               return "", fmt.Errorf("failed to download %s: %w", uri, err)
+       }
+       if n > maxDownloadSize {
+               os.Remove(targetFile.Name())
+               return "", fmt.Errorf("download from %s exceeds maximum allowed 
size of %d bytes", uri, maxDownloadSize)
        }
 
        return targetFile.Name(), nil

++++++ melange.obsinfo ++++++
--- /var/tmp/diff_new_pack.pq7DqA/_old  2026-03-02 17:40:01.706608883 +0100
+++ /var/tmp/diff_new_pack.pq7DqA/_new  2026-03-02 17:40:01.718609384 +0100
@@ -1,5 +1,5 @@
 name: melange
-version: 0.43.3
-mtime: 1771950760
-commit: 66e9282b26b7537ac33b130a3499d9119a0e52f1
+version: 0.43.4
+mtime: 1772231082
+commit: ba26216d9671b7fd8e2696a3a217f441f2e04b05
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/melange/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.melange.new.29461/vendor.tar.gz differ: char 132, 
line 3

Reply via email to