Repository: chainguard-dev/apko
Pull request #1594 (2025-03-27 14:22:21)

build(deps): bump sigs.k8s.io/release-utils from 0.11.0 to 0.11.1
Bumps [sigs.k8s.io/release-utils](https://github.com/kubernetes-sigs/release-utils) from 0.11.0 to 0.11.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/kubernetes-sigs/release-utils/releases">sigs.k8s.io/release-utils's releases</a>.</em></p>
<blockquote>
<h2>v0.11.1</h2>
<p>No release notes provided.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/16d798b2ea0ae0d3c51740282fd87ff909bcb4c2"><code>16d798b</code></a> Merge pull request <a href="https://redirect.github.com/kubernetes-sigs/release-utils/issues/132">#132</a> from saschagrunert/lint</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/96f8ac4009301c963a6a6ce477fa9821125c76b2"><code>96f8ac4</code></a> Switch to golangci-lint v2</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/9aec958a6e9d2cdc25f06e0917174f87a0d573e5"><code>9aec958</code></a> Merge pull request <a href="https://redirect.github.com/kubernetes-sigs/release-utils/issues/131">#131</a> from kubernetes-sigs/dependabot/github_actions/action...</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/bfc6f685abfad006539103dcab0e6982d848989d"><code>bfc6f68</code></a> build(deps): bump actions/setup-go in the actions group</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/4873467be9da7142735da1aaa742f1e434432e3c"><code>4873467</code></a> Merge pull request <a href="https://redirect.github.com/kubernetes-sigs/release-utils/issues/130">#130</a> from cpanato/updates</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/538d777e3ea18eb6b24cfe9f982d2e25ab14de56"><code>538d777</code></a> update external deps</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/3d31c3671708a61fe276766549e9b68ff84d56ae"><code>3d31c36</code></a> update dependencies</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/f6de01024ea1f7e75599a6c64a7887edc78374b9"><code>f6de010</code></a> bump cosign and golanci-lint</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/9c55b4eac4bcff18c62fb22548fc65fde314848f"><code>9c55b4e</code></a> Merge pull request <a href="https://redirect.github.com/kubernetes-sigs/release-utils/issues/129">#129</a> from kubernetes-sigs/dependabot/go_modules/all-3cc2e6...</li>
<li><a href="https://github.com/kubernetes-sigs/release-utils/commit/0444df04661126455e81c8bb8f4ecd79740020d3"><code>0444df0</code></a> build(deps): bump github.com/avast/retry-go/v4 in the all group</li>
<li>Additional commits viewable in <a href="https://github.com/kubernetes-sigs/release-utils/compare/v0.11.0...v0.11.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigs.k8s.io/release-utils&package-manager=go_modules&previous-version=0.11.0&new-version=0.11.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml
index 24041a6..7ee3b9e 100644
--- a/.github/workflows/build-samples.yml
+++ b/.github/workflows/build-samples.yml
@@ -24,7 +24,7 @@ jobs:
         arch: [x86_64, aarch64]
 
     steps:
-      - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+      - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
         with:
           egress-policy: audit
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -65,7 +65,7 @@ jobs:
     runs-on: ${{ matrix.platform }}
 
     steps:
-      - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+      - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
         with:
           egress-policy: audit
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -95,7 +95,7 @@ jobs:
       contents: read
 
     steps:
-      - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+      - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
         with:
           egress-policy: audit
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -134,7 +134,7 @@ jobs:
       contents: read
 
     steps:
-      - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+      - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
         with:
           egress-policy: audit
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -173,7 +173,7 @@ jobs:
       contents: read
 
     steps:
-      - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+      - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
         with:
           egress-policy: audit
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 7cc35bb..e81d6a7 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -17,7 +17,7 @@ jobs:
       contents: read
 
     steps:
-      - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+      - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
         with:
           egress-policy: audit
 
@@ -43,7 +43,7 @@ jobs:
         run: |
           make ci
 
-      - uses: goreleaser/goreleaser-action@90a3faa9d0182683851fbfa97ca1a2cb983bfca3 # v2.8.1
+      - uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
         with:
           install-only: true
 
diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml
index 2d36ace..3f4a622 100644
--- a/.github/workflows/codeql.yaml
+++ b/.github/workflows/codeql.yaml
@@ -18,7 +18,7 @@ jobs:
       security-events: write
 
     steps:
-    - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+    - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
       with:
         egress-policy: audit
 
@@ -30,7 +30,7 @@ jobs:
         check-latest: true
 
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae
+      uses: github/codeql-action/init@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2
       with:
         languages: go
 
@@ -38,4 +38,4 @@ jobs:
       run: make apko
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae
+      uses: github/codeql-action/analyze@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index e0a6da6..61d4b1b 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -48,12 +48,12 @@ jobs:
       uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
 
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
+      uses: github/codeql-action/init@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14
       with:
         languages: ${{ matrix.language }}
         build-mode: ${{ matrix.build-mode }}
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
+      uses: github/codeql-action/analyze@fc7e4a0fa01c3cca5fd6a1fddec5c0740c977aa2 # v3.28.14
       with:
         category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 15d1571..08dc832 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -22,7 +22,7 @@ jobs:
       contents: write
 
     steps:
-    - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+    - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
       with:
         egress-policy: audit
     - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -33,7 +33,7 @@ jobs:
 
     - uses: sigstore/cosign-installer@d7d6bc7722e3daa8354c50bcb52f4837da5e9b6a # v3.8.1
 
-    - uses: goreleaser/goreleaser-action@90a3faa9d0182683851fbfa97ca1a2cb983bfca3 # v2.8.1
+    - uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
       with:
         install-only: true
 
diff --git a/go.mod b/go.mod
index 90585dc..2b22521 100644
--- a/go.mod
+++ b/go.mod
@@ -28,14 +28,14 @@ require (
 	go.opentelemetry.io/otel/trace v1.35.0
 	go.step.sm/crypto v0.59.1
 	golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
-	golang.org/x/sync v0.12.0
+	golang.org/x/sync v0.13.0
 	golang.org/x/sys v0.31.0
 	golang.org/x/time v0.11.0
 	google.golang.org/api v0.225.0
 	gopkg.in/ini.v1 v1.67.0
 	gopkg.in/yaml.v3 v3.0.1
 	k8s.io/apimachinery v0.32.3
-	sigs.k8s.io/release-utils v0.11.0
+	sigs.k8s.io/release-utils v0.11.1
 )
 
 require (
@@ -151,7 +151,7 @@ require (
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
 	golang.org/x/crypto v0.36.0 // indirect
-	golang.org/x/mod v0.22.0 // indirect
+	golang.org/x/mod v0.23.0 // indirect
 	golang.org/x/net v0.37.0 // indirect
 	golang.org/x/oauth2 v0.28.0 // indirect
 	golang.org/x/term v0.30.0 // indirect
diff --git a/go.sum b/go.sum
index 0f79647..ae09ce0 100644
--- a/go.sum
+++ b/go.sum
@@ -399,8 +399,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
-golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
+golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
+golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -427,8 +427,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
-golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
+golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -479,8 +479,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
-golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
+golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
+golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
 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=
@@ -529,5 +529,5 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
 k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
-sigs.k8s.io/release-utils v0.11.0 h1:FUVSw2dO67M7mfcQx9AITEGnTHoBOdJNbbQ3FT3o8mA=
-sigs.k8s.io/release-utils v0.11.0/go.mod h1:wAlXz8xruzvqZUsorI64dZ3lbkiDnYSlI4IYC6l2yEA=
+sigs.k8s.io/release-utils v0.11.1 h1:hzvXGpHgHJfLOJB6TRuu14bzWc3XEglHmXHJqwClSZE=
+sigs.k8s.io/release-utils v0.11.1/go.mod h1:ybR2V/uQAOGxYfzYtBenSYeXWkBGNP2qnEiX77ACtpc=
diff --git a/internal/cli/build-minirootfs.go b/internal/cli/build-minirootfs.go
index 5ec421b..2b2a0e1 100644
--- a/internal/cli/build-minirootfs.go
+++ b/internal/cli/build-minirootfs.go
@@ -24,9 +24,9 @@ import (
 
 	"github.com/chainguard-dev/clog"
 
-	apkfs "chainguard.dev/apko/pkg/apk/fs"
 	"chainguard.dev/apko/pkg/build"
 	"chainguard.dev/apko/pkg/build/types"
+	"chainguard.dev/apko/pkg/tarfs"
 )
 
 func buildMinirootFS() *cobra.Command {
@@ -81,8 +81,7 @@ func BuildMinirootFSCmd(ctx context.Context, opts ...build.Option) error {
 	}
 	defer os.RemoveAll(wd)
 
-	fs := apkfs.DirFS(wd, apkfs.WithCreateDir())
-	bc, err := build.New(ctx, fs, opts...)
+	bc, err := build.New(ctx, tarfs.New(), opts...)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/apk/fs/memfs.go b/pkg/apk/fs/memfs.go
index b477e19..a5167b2 100644
--- a/pkg/apk/fs/memfs.go
+++ b/pkg/apk/fs/memfs.go
@@ -326,11 +326,12 @@ func (m *memFS) Mknod(path string, mode uint32, dev int) error {
 		return os.ErrExist
 	}
 	anode.children[base] = &node{
-		name:   base,
-		mode:   fs.FileMode(mode) | os.ModeCharDevice | os.ModeDevice,
-		major:  unix.Major(uint64(dev)),
-		minor:  unix.Minor(uint64(dev)),
-		xattrs: map[string][]byte{},
+		name:    base,
+		mode:    fs.FileMode(mode) | os.ModeCharDevice | os.ModeDevice,
+		major:   unix.Major(uint64(dev)),
+		minor:   unix.Minor(uint64(dev)),
+		xattrs:  map[string][]byte{},
+		modTime: anode.modTime,
 	}
 
 	return nil
@@ -405,6 +406,7 @@ func (m *memFS) Symlink(oldname, newname string) error {
 		mode:       0o777 | os.ModeSymlink,
 		linkTarget: oldname,
 		xattrs:     map[string][]byte{},
+		modTime:    anode.modTime,
 	}
 	return nil
 }
diff --git a/pkg/build/busybox.go b/pkg/build/busybox.go
index 3a659b2..79f4724 100644
--- a/pkg/build/busybox.go
+++ b/pkg/build/busybox.go
@@ -53,7 +53,8 @@ var busyboxLinks map[string][]string
 
 func installBusyboxLinks(fsys apkfs.FullFS, installed []*apk.InstalledPackage) error {
 	// does busybox exist? if not, do not bother with symlinks
-	if _, err := fsys.Stat(busybox); err != nil {
+	busyboxInfo, err := fsys.Stat(busybox)
+	if err != nil {
 		if !errors.Is(err, os.ErrNotExist) {
 			return err
 		}
@@ -116,6 +117,10 @@ func installBusyboxLinks(fsys apkfs.FullFS, installed []*apk.InstalledPackage) e
 		if err := fsys.MkdirAll(dir, 0755); err != nil {
 			return fmt.Errorf("creating directory %s: %w", dir, err)
 		}
+		if err := fsys.Chtimes(dir, busyboxInfo.ModTime(), busyboxInfo.ModTime()); err != nil {
+			return fmt.Errorf("error chtimes on %s: %w", dir, err)
+		}
+
 		if err := fsys.Symlink(busybox, link); err != nil {
 			// sometimes the list generates links twice, so do not error on that
 			if errors.Is(err, os.ErrExist) {
diff --git a/pkg/paths/paths.go b/pkg/paths/paths.go
index 7083ffa..4394915 100644
--- a/pkg/paths/paths.go
+++ b/pkg/paths/paths.go
@@ -18,6 +18,7 @@ import (
 	"fmt"
 	"os"
 	"path"
+	"path/filepath"
 )
 
 func ResolvePath(p string, includePaths []string) (string, error) {
@@ -41,6 +42,11 @@ func ResolvePath(p string, includePaths []string) (string, error) {
 // and we can safely move on. We will also perform a best-effort attempt to clean up the
 // unadvertised file at `src`.
 func AdvertiseCachedFile(src, dst string) error {
+	// Prefer relative symlinks
+	rel, err := filepath.Rel(filepath.Dir(dst), src)
+	if err != nil {
+		rel = src
+	}
 	// Check if the destination already exists.
 	if _, err := os.Stat(dst); err == nil {
 		// Since `src` is unadvertised, it is safe to remove it. Ideally we want this to succeeds,
@@ -50,14 +56,14 @@ func AdvertiseCachedFile(src, dst string) error {
 		return nil
 	}
 	// Create the symlink.
-	if err := os.Symlink(src, dst); err != nil {
+	if err := os.Symlink(rel, dst); err != nil {
 		// Ignore already exists errors. We don't even want to do clean up here even when
 		// the symlink is pointing somewhere elese, to avoid relying too much on file system
 		// remantics/eventual consistency, etc.
 		if errors.Is(err, os.ErrExist) {
 			return nil
 		}
-		return fmt.Errorf("linking (cached) %s to %s: %w", src, dst, err)
+		return fmt.Errorf("linking (cached) %s to %s: %w", rel, dst, err)
 	}
 	return nil
 }
diff --git a/pkg/tarfs/fs.go b/pkg/tarfs/fs.go
index aa11895..a40dca0 100644
--- a/pkg/tarfs/fs.go
+++ b/pkg/tarfs/fs.go
@@ -120,6 +120,9 @@ func (m *memFS) WriteHeader(hdr tar.Header, tfs fs.FS, pkg *apk.Package) (bool,
 		if err := m.MkdirAll(hdr.Name, hdr.FileInfo().Mode().Perm()); err != nil {
 			return false, fmt.Errorf("error creating directory %s: %w", hdr.Name, err)
 		}
+		if err := m.Chtimes(hdr.Name, hdr.AccessTime, hdr.ModTime); err != nil {
+			return false, fmt.Errorf("error chtime on directory %s: %w", hdr.Name, err)
+		}
 
 		for k, v := range hdr.PAXRecords {
 			if !strings.HasPrefix(k, xattrTarPAXRecordsPrefix) {
@@ -604,6 +607,7 @@ func (m *memFS) Mknod(path string, mode uint32, dev int) error {
 		minor:     unix.Minor(uint64(dev)),
 		xattrs:    map[string][]byte{},
 		hardlinks: map[string]*tar.Header{},
+		modTime:   anode.modTime,
 	}
 
 	return nil
@@ -679,6 +683,7 @@ func (m *memFS) Symlink(oldname, newname string) error {
 		linkTarget: oldname,
 		xattrs:     map[string][]byte{},
 		hardlinks:  map[string]*tar.Header{},
+		modTime:    anode.modTime,
 	}
 	return nil
 }


Test patch:
diff --git a/.github/workflows/go-tests.yaml b/.github/workflows/go-tests.yaml
index bda3d21..c616cbf 100644
--- a/.github/workflows/go-tests.yaml
+++ b/.github/workflows/go-tests.yaml
@@ -16,7 +16,7 @@ jobs:
       contents: read
 
     steps:
-      - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
+      - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
         with:
           egress-policy: audit
 
diff --git a/pkg/paths/paths_test.go b/pkg/paths/paths_test.go
index cf64d23..c0ddd4f 100644
--- a/pkg/paths/paths_test.go
+++ b/pkg/paths/paths_test.go
@@ -15,6 +15,7 @@ package paths
 
 import (
 	"os"
+	"path/filepath"
 	"testing"
 )
 
@@ -48,9 +49,13 @@ func TestAdvertiseCachedFile(t *testing.T) {
 			t.Fatal(err)
 		}
 		// check the symlink
+		rel1, err := filepath.Rel(filepath.Dir(dst), src1)
+		if err != nil {
+			t.Fatal(err)
+		}
 		if l, err := os.Readlink(dst); err != nil {
 			t.Fatal(err)
-		} else if l != src1 {
+		} else if l != rel1 {
 			t.Fatalf("symlink should stay in tact: %s != %s", l, src2)
 		}