Skip to content

Commit 95128d4

Browse files
authored
Fix for 'include' flag with spec file (#3249)
1 parent 749c3f6 commit 95128d4

File tree

4 files changed

+95
-8
lines changed

4 files changed

+95
-8
lines changed

artifactory_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5341,6 +5341,63 @@ func TestArtifactorySearchProps(t *testing.T) {
53415341
cleanArtifactoryTest()
53425342
}
53435343

5344+
// Test that the --include flag works correctly with spec files
5345+
func TestArtifactorySearchIncludeWithSpec(t *testing.T) {
5346+
initArtifactoryTest(t, "")
5347+
5348+
// Upload files
5349+
specFile, err := tests.CreateSpec(tests.SplitUploadSpecA)
5350+
assert.NoError(t, err)
5351+
runRt(t, "upload", "--spec="+specFile, "--recursive", "--flat=false")
5352+
5353+
// Test 1: Search with spec WITHOUT --include flag (should return all fields)
5354+
searchSpecBuilder := spec.NewBuilder().Pattern(tests.RtRepo1 + "/*").Recursive(true)
5355+
searchCmd := generic.NewSearchCommand()
5356+
searchCmd.SetServerDetails(serverDetails).SetSpec(searchSpecBuilder.BuildSpec())
5357+
reader, err := searchCmd.Search()
5358+
assert.NoError(t, err)
5359+
5360+
foundWithAllFields := false
5361+
for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
5362+
// Check that we have all default fields (type, size, sha1, etc.)
5363+
if resultItem.Type != "" && resultItem.Size > 0 && resultItem.Sha1 != "" {
5364+
foundWithAllFields = true
5365+
break
5366+
}
5367+
}
5368+
assert.True(t, foundWithAllFields, "Search without --include should return all fields")
5369+
readerCloseAndAssert(t, reader)
5370+
5371+
// Test 2: Search with spec WITH --include flag using spec builder (simulating CLI flag)
5372+
searchSpecBuilder = spec.NewBuilder().Pattern(tests.RtRepo1 + "/*").Recursive(true).Include([]string{"size", "created"})
5373+
searchCmd = generic.NewSearchCommand()
5374+
searchCmd.SetServerDetails(serverDetails).SetSpec(searchSpecBuilder.BuildSpec())
5375+
reader, err = searchCmd.Search()
5376+
assert.NoError(t, err)
5377+
5378+
// Verify limited fields are returned
5379+
var resultItems []utils.SearchResult
5380+
readerNoDate, err := utils.SearchResultNoDate(reader)
5381+
assert.NoError(t, err)
5382+
for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
5383+
resultItems = append(resultItems, *resultItem)
5384+
// Verify that size and created are present (when include is used)
5385+
// Note: path, name, repo are always included as base fields
5386+
assert.NotEmpty(t, resultItem.Path, "Path should always be present")
5387+
// Check that we have the requested field
5388+
if resultItem.Size > 0 {
5389+
// Size was requested, should be present
5390+
assert.Greater(t, resultItem.Size, int64(0), "Size should be present when included")
5391+
}
5392+
}
5393+
assert.Greater(t, len(resultItems), 0, "Should find at least one artifact")
5394+
readerGetErrorAndAssert(t, readerNoDate)
5395+
readerCloseAndAssert(t, readerNoDate)
5396+
5397+
// Cleanup
5398+
cleanArtifactoryTest()
5399+
}
5400+
53445401
// Remove not to be deleted dirs from delete command from path to delete.
53455402
func TestArtifactoryDeleteExcludeProps(t *testing.T) {
53465403
initArtifactoryTest(t, "")

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ require (
1616
github.com/docker/docker v28.5.2+incompatible
1717
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1
1818
github.com/jfrog/archiver/v3 v3.6.1
19-
github.com/jfrog/build-info-go v1.12.5-0.20251209120002-025bda5ff78b
19+
github.com/jfrog/build-info-go v1.12.5-0.20251209031413-f5f0e93dc8db
2020
github.com/jfrog/gofrog v1.7.6
2121
github.com/jfrog/jfrog-cli-application v1.0.2-0.20251208114900-b3cc968c8e3d
22-
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251209121625-98f7b22a08c1
22+
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251210074251-c15fabe27f7f
2323
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251210085744-f8481d179ac5
2424
github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251204144808-73fa744851c0
2525
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,8 +1175,8 @@ github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP
11751175
github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4=
11761176
github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI=
11771177
github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw=
1178-
github.com/jfrog/build-info-go v1.12.5-0.20251209120002-025bda5ff78b h1:wf8u5g84GW8ZYsM59UGk+1vvcUOCaP75NiGZeOatkC8=
1179-
github.com/jfrog/build-info-go v1.12.5-0.20251209120002-025bda5ff78b/go.mod h1:9W4U440fdTHwW1HiB/R0VQvz/5q8ZHsms9MWcq+JrdY=
1178+
github.com/jfrog/build-info-go v1.12.5-0.20251209031413-f5f0e93dc8db h1:5q4hUqZVl7Xt+R+ono5lDH1/lkvV1spnfDtp0VtJqlo=
1179+
github.com/jfrog/build-info-go v1.12.5-0.20251209031413-f5f0e93dc8db/go.mod h1:9W4U440fdTHwW1HiB/R0VQvz/5q8ZHsms9MWcq+JrdY=
11801180
github.com/jfrog/froggit-go v1.20.6 h1:Xp7+LlEh0m1KGrQstb+u0aGfjRUtv1eh9xQBV3571jQ=
11811181
github.com/jfrog/froggit-go v1.20.6/go.mod h1:obSG1SlsWjktkuqmKtpq7MNTTL63e0ot+ucTnlOMV88=
11821182
github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8=
@@ -1187,8 +1187,8 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL
11871187
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
11881188
github.com/jfrog/jfrog-cli-application v1.0.2-0.20251208114900-b3cc968c8e3d h1:0o6tj4nPP9uCscyfPbKBUcCaIYof42irwii6XsBB8zM=
11891189
github.com/jfrog/jfrog-cli-application v1.0.2-0.20251208114900-b3cc968c8e3d/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw=
1190-
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251209121625-98f7b22a08c1 h1:vT9QWrwW6pJPcHewSVsDWWoCHq+Nt3UqnEaJjyMqFMU=
1191-
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251209121625-98f7b22a08c1/go.mod h1:b/Sf+FOjWwoQOZ00r+fXMbDqpts8L0q1lMNgS5cofAs=
1190+
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251210074251-c15fabe27f7f h1:aoYtLX8ImiaYmStWeTXllidkMy1Hpet/TGOjicf1WhU=
1191+
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251210074251-c15fabe27f7f/go.mod h1:wKTWZqomaLxrHuvVF4iryZ8V4rn6h2y09jbuOBVRQUY=
11921192
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251210085744-f8481d179ac5 h1:GYE67ubwl+ZRw3CcXFUi49EwwQp6k+qS8sX0QuHDHO8=
11931193
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251210085744-f8481d179ac5/go.mod h1:BMoGi2rG0udCCeaghqlNgiW3fTmT+TNnfTnBoWFYgcg=
11941194
github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251204144808-73fa744851c0 h1:8S1vE1PeVtrzWkKL0N39cX6XLLNV0It+f6xjRKjw7Ug=

utils/cliutils/utils.go

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package cliutils
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"errors"
67
"fmt"
78
"io"
89
"net/http"
910
"os"
1011
"path/filepath"
12+
"regexp"
1113
"strconv"
1214
"strings"
1315
"time"
@@ -474,6 +476,13 @@ func OverrideFieldsIfSet(spec *speccore.File, c *cli.Context) {
474476
overrideStringIfSet(&spec.Symlinks, c, "symlinks")
475477
overrideStringIfSet(&spec.Transitive, c, "transitive")
476478
overrideStringIfSet(&spec.PublicGpgKey, c, "gpg-key")
479+
overrideIncludeIfSet(spec, c)
480+
}
481+
482+
func overrideIncludeIfSet(spec *speccore.File, c *cli.Context) {
483+
if c.IsSet("include") {
484+
spec.Include = strings.Split(c.String("include"), ";")
485+
}
477486
}
478487

479488
func CreateConfigCmd(c *cli.Context, confType project.ProjectType) error {
@@ -643,11 +652,21 @@ func getLatestCliVersionFromGithubAPI() (githubVersionInfo githubResponse, err e
643652
if err != nil {
644653
return
645654
}
646-
err = json.Unmarshal(body, &githubVersionInfo)
655+
// Use json.Decoder with DisallowUnknownFields for safer deserialization
656+
decoder := json.NewDecoder(bytes.NewReader(body))
657+
decoder.DisallowUnknownFields()
658+
if err = decoder.Decode(&githubVersionInfo); err != nil {
659+
return
660+
}
661+
// Validate the received version tag format
662+
if !isValidVersionTag(githubVersionInfo.TagName) {
663+
err = errors.New("invalid version tag format received from GitHub API")
664+
}
647665
return
648666
}
649667

650668
func doHttpRequest(client *http.Client, req *http.Request) (resp *http.Response, body []byte, err error) {
669+
const maxResponseSize = 10 * 1024 * 1024 // 10MB limit
651670
req.Close = true
652671
resp, err = client.Do(req)
653672
if errorutils.CheckError(err) != nil {
@@ -658,10 +677,21 @@ func doHttpRequest(client *http.Client, req *http.Request) (resp *http.Response,
658677
err = errors.Join(err, errorutils.CheckError(resp.Body.Close()))
659678
}
660679
}()
661-
body, err = io.ReadAll(resp.Body)
680+
// Limit response body size to prevent potential DoS
681+
body, err = io.ReadAll(io.LimitReader(resp.Body, maxResponseSize))
662682
return resp, body, errorutils.CheckError(err)
663683
}
664684

685+
// isValidVersionTag validates that the version tag follows semantic versioning format
686+
func isValidVersionTag(tag string) bool {
687+
if tag == "" {
688+
return false
689+
}
690+
// Validate semantic versioning format (v1.2.3 or 1.2.3)
691+
matched, _ := regexp.MatchString(`^v?\d+\.\d+\.\d+`, tag)
692+
return matched
693+
}
694+
665695
// Get project key from flag or environment variable
666696
func GetProject(c *cli.Context) string {
667697
projectKey := c.String("project")

0 commit comments

Comments
 (0)