From 0f32f2ac460a8996967d931ab7804b724fd41679 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Mon, 19 Jan 2026 10:28:42 +0000 Subject: [PATCH] refactor(run download): extract zip extraction func into a separate package Signed-off-by: Babak K. Shandiz Co-authored-by: Kynan Ware Co-authored-by: Devraj Mehta --- internal/zip/fixtures/myproject.zip | Bin 0 -> 1710 bytes {pkg/cmd/run/download => internal/zip}/zip.go | 8 ++++++-- .../run/download => internal/zip}/zip_test.go | 4 ++-- pkg/cmd/run/download/http.go | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 internal/zip/fixtures/myproject.zip rename {pkg/cmd/run/download => internal/zip}/zip.go (80%) rename {pkg/cmd/run/download => internal/zip}/zip_test.go (89%) diff --git a/internal/zip/fixtures/myproject.zip b/internal/zip/fixtures/myproject.zip new file mode 100644 index 0000000000000000000000000000000000000000..2fdf3f90c6e00c9f4b59a47fb84b6fd3486be007 GIT binary patch literal 1710 zcmWIWW@h1H0D(o3?Ll9~jbb@~Y!K#TkYOlFO-#v6)yqu@4dG;9UQnK!0K%me+zgB? zUl|z~SVVvdl@&Zvb8_;z0^mkv1C0VozyS-;sHDt1eXuE3Kogc>nu4lZcJ6Pmvp`M* zIRvCTw=%UN6>bE`7<7jy>Vwo3XCOJH7K>Agi;^Kui3OSwhiMMNDInbqTFZoZfzAM7 zZlF^@x=TwkbM(^l!HxkL0>WsHDM(DtPE1c#04YUsPchI$zH_!Z0zlJ17-nK_VrCx9 zL@%IeAdF^WT4`Rg0!W>Prb4wsE!a>{_;WDaUDg`7NkYZAl!<{shlPQG3+PNeJ$)Zf zXIH;qSFkH5Jv|){!f0m326^Y-HsIO!I$XeVYr{p`yxYE8r$)?(pD;De(rTMfcEOqh zlf=K=?=QJjCM}>KaPqyY)pRMN+p{i8A4@8)ocm@a|Az~9hpwNG-*@m>TZvtR%x(2! zTE=tNe!te6VEZM_s6E`m_pF4E_`yOWwmX8i_RaKDYkIIiGX7zbT0cWMN3ZPLiYB(G zD~T48RZBj;lUR2)rC>+%vFhu$*nTc3ep_RfoWb-`_HBZVP0PIltM(~}^>=%u&uY9W zxZ?Y@rq#TAXEXa8Yd^W|h+w1a?ZkH{4o6pSNUsi8_#t%9SY@uQn!jNS9PPKzm@`gqd!!C3=?lnpPcPyTwCH&gMocvQxY^(TU#-rD_n zzvr6tTFi415Y2X`abRb?8JuVo%%ebg?rD&7phJA&d8rXn^7+>>dU|W&iEcb)+HWeOX8ms;oW(p@9;GjJiFIB% z&TZ?|G5gT7W6=@*h-X2{EA<*#-iHKTahb*~y8OqJ^G1`aLa8Y5g?h+QsSfcPhq<40lr@iSe-Ss)zT87(nC{kqc#@W_4mNt1UIsQ>RJ5o$US&w_|2gyXQ zrS}(FM|N}Um}IJ(vi6is(iT6LDcqcoxC)aOh90&TKPXt0pZ(E~qw|4e(N&gZ9r=g- z-|z=`Gcw6B<0^F|fJvHx0a&;&ENKL>kjfxdNEw8dhLMfKEO{Wtfil}$M{l5Uka7rU z5|#o4-6Ygf2-#tsP?Ml#5@F*o%OPZkT>}~iDV2aGVJS?I9fnyZAv;V27;q>h6k!7~ zizH+N)1U^z3n-w0SPCbI3vm@k$Oi5P8i-st0nNiwFa>zCvH=5yfgK1{fW=w~uvlYY F002;O_<#Ta literal 0 HcmV?d00001 diff --git a/pkg/cmd/run/download/zip.go b/internal/zip/zip.go similarity index 80% rename from pkg/cmd/run/download/zip.go rename to internal/zip/zip.go index bb504dde1..8cef5c30b 100644 --- a/pkg/cmd/run/download/zip.go +++ b/internal/zip/zip.go @@ -1,4 +1,4 @@ -package download +package zip import ( "archive/zip" @@ -17,7 +17,11 @@ const ( execMode os.FileMode = 0755 ) -func extractZip(zr *zip.Reader, destDir safepaths.Absolute) error { +// ExtractZip extracts the contents of a zip archive to destDir. +// Files that would result in path traversal are silently skipped. +// Files that would produce any other error cause the extraction to be aborted, +// and the error is returned. +func ExtractZip(zr *zip.Reader, destDir safepaths.Absolute) error { for _, zf := range zr.File { fpath, err := destDir.Join(zf.Name) if err != nil { diff --git a/pkg/cmd/run/download/zip_test.go b/internal/zip/zip_test.go similarity index 89% rename from pkg/cmd/run/download/zip_test.go rename to internal/zip/zip_test.go index 2584371b4..37e83661c 100644 --- a/pkg/cmd/run/download/zip_test.go +++ b/internal/zip/zip_test.go @@ -1,4 +1,4 @@ -package download +package zip import ( "archive/zip" @@ -19,7 +19,7 @@ func Test_extractZip(t *testing.T) { require.NoError(t, err) defer zipFile.Close() - err = extractZip(&zipFile.Reader, extractPath) + err = ExtractZip(&zipFile.Reader, extractPath) require.NoError(t, err) _, err = os.Stat(filepath.Join(extractPath.String(), "src", "main.go")) diff --git a/pkg/cmd/run/download/http.go b/pkg/cmd/run/download/http.go index 783c8495e..09293b056 100644 --- a/pkg/cmd/run/download/http.go +++ b/pkg/cmd/run/download/http.go @@ -10,6 +10,7 @@ import ( "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/internal/safepaths" + ghzip "github.com/cli/cli/v2/internal/zip" "github.com/cli/cli/v2/pkg/cmd/run/shared" ) @@ -62,7 +63,7 @@ func downloadArtifact(httpClient *http.Client, url string, destDir safepaths.Abs if err != nil { return fmt.Errorf("error extracting zip archive: %w", err) } - if err := extractZip(zipfile, destDir); err != nil { + if err := ghzip.ExtractZip(zipfile, destDir); err != nil { return fmt.Errorf("error extracting zip archive: %w", err) }