Skip to content

Commit 3c025a2

Browse files
committed
Fixed SAST vulnerabilities
1 parent ce05ac3 commit 3c025a2

File tree

6 files changed

+76
-8
lines changed

6 files changed

+76
-8
lines changed

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ require (
7171
github.com/gfleury/go-bitbucket-v1 v0.0.0-20240917142304-df385efaac68 // indirect
7272
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
7373
github.com/go-git/go-billy/v5 v5.7.0 // indirect
74-
github.com/go-git/go-git/v5 v5.16.4 // indirect
74+
github.com/go-git/go-git/v5 v5.16.5 // indirect
7575
github.com/go-logr/logr v1.4.3 // indirect
7676
github.com/go-logr/stdr v1.2.2 // indirect
7777
github.com/go-openapi/analysis v0.24.2 // indirect
@@ -161,7 +161,7 @@ require (
161161
github.com/spf13/pflag v1.0.10 // indirect
162162
github.com/stretchr/objx v0.5.3 // indirect
163163
github.com/subosito/gotenv v1.6.0 // indirect
164-
github.com/theupdateframework/go-tuf/v2 v2.4.0 // indirect
164+
github.com/theupdateframework/go-tuf/v2 v2.4.1 // indirect
165165
github.com/transparency-dev/formats v0.0.0-20260119090622-e70c80e9488a // indirect
166166
github.com/transparency-dev/merkle v0.0.2 // indirect
167167
github.com/ulikunitz/xz v0.5.15 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9n
219219
github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E=
220220
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
221221
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
222-
github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y=
223-
github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
222+
github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
223+
github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
224224
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
225225
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
226226
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -596,8 +596,8 @@ github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slH
596596
github.com/terminalstatic/go-xsd-validate v0.1.6/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
597597
github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI=
598598
github.com/theupdateframework/go-tuf v0.7.0/go.mod h1:uEB7WSY+7ZIugK6R1hiBMBjQftaFzn7ZCDJcp1tCUug=
599-
github.com/theupdateframework/go-tuf/v2 v2.4.0 h1:3HGxV0lq91/RJ7YycqCKuKBuLfo4rLRut4lh9XqIEP4=
600-
github.com/theupdateframework/go-tuf/v2 v2.4.0/go.mod h1:9S0Srkf3c13FelsOyt5OyG3ZZDq9OJDA4IILavrt72Y=
599+
github.com/theupdateframework/go-tuf/v2 v2.4.1 h1:K6ewW064rKZCPkRo1W/CTbTtm/+IB4+coG1iNURAGCw=
600+
github.com/theupdateframework/go-tuf/v2 v2.4.1/go.mod h1:Nex2enPVYDFCklrnbTzl3OVwD7fgIAj0J5++z/rvCj8=
601601
github.com/tink-crypto/tink-go-awskms/v2 v2.1.0 h1:N9UxlsOzu5mttdjhxkDLbzwtEecuXmlxZVo/ds7JKJI=
602602
github.com/tink-crypto/tink-go-awskms/v2 v2.1.0/go.mod h1:PxSp9GlOkKL9rlybW804uspnHuO9nbD98V/fDX4uSis=
603603
github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0 h1:3B9i6XBXNTRspfkTC0asN5W0K6GhOSgcujNiECNRNb0=

skills/commands/install/install.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,11 @@ func unzipFile(src, dest string) error {
240240
}
241241

242242
func extractFile(f *zip.File, dest string) error {
243+
// Reject paths containing traversal sequences as defense-in-depth
244+
if strings.Contains(dest, "..") {
245+
return fmt.Errorf("illegal file path: %s", dest)
246+
}
247+
243248
rc, err := f.Open()
244249
if err != nil {
245250
return err
@@ -248,8 +253,9 @@ func extractFile(f *zip.File, dest string) error {
248253
_ = rc.Close()
249254
}()
250255

251-
// #nosec G304 -- dest is validated above to be under the extraction directory
252-
outFile, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
256+
cleanDest := filepath.Clean(dest)
257+
// #nosec G304 -- dest is validated in unzipFile and above to be under the extraction directory
258+
outFile, err := os.OpenFile(cleanDest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
253259
if err != nil {
254260
return err
255261
}

skills/commands/publish/publish.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ func (pc *PublishCommand) Run() error {
109109
}
110110
}
111111

112+
if err := ValidateVersion(version); err != nil {
113+
return err
114+
}
115+
112116
version, err = pc.resolveVersionCollision(slug, version)
113117
if err != nil {
114118
return err
@@ -235,6 +239,9 @@ func (pc *PublishCommand) resolveVersionCollision(slug, version string) (string,
235239
if newVersion == "" {
236240
return "", fmt.Errorf("no version provided, aborting")
237241
}
242+
if err := ValidateVersion(newVersion); err != nil {
243+
return "", err
244+
}
238245
return pc.resolveVersionCollision(slug, newVersion)
239246
default:
240247
return "", fmt.Errorf("publish aborted by user")

skills/commands/publish/publish_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,42 @@ func TestValidateSlug(t *testing.T) {
225225
assert.Error(t, ValidateSlug(""))
226226
}
227227

228+
func TestValidateVersion(t *testing.T) {
229+
tests := []struct {
230+
version string
231+
wantErr bool
232+
}{
233+
{"1.0.0", false},
234+
{"0.1.0", false},
235+
{"2.3.4-beta", false},
236+
{"1.0.0-rc.1", false},
237+
{"1.0.0+build.123", false},
238+
{"v1.0.0", false},
239+
240+
{"", true},
241+
{"../etc/passwd", true},
242+
{"1.0.0/../../etc", true},
243+
{"1.0.0\\..\\etc", true},
244+
{"..", true},
245+
{"valid..version", true},
246+
{"has space", true},
247+
{"has\x00null", true},
248+
{"/leading-slash", true},
249+
{"-leading-hyphen", true},
250+
}
251+
252+
for _, tt := range tests {
253+
t.Run(tt.version, func(t *testing.T) {
254+
err := ValidateVersion(tt.version)
255+
if tt.wantErr {
256+
assert.Error(t, err, "expected error for version %q", tt.version)
257+
} else {
258+
assert.NoError(t, err, "expected no error for version %q", tt.version)
259+
}
260+
})
261+
}
262+
}
263+
228264
func TestGeneratePredicateFile(t *testing.T) {
229265
dir := t.TempDir()
230266
path, err := GeneratePredicateFile(dir, "test-skill", "1.0.0")

skills/commands/publish/skillmeta.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import (
1010

1111
var slugRegex = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
1212

13+
// versionSafeRegex permits semver-like strings: digits, dots, hyphens, plus, and alphanumerics.
14+
// It rejects path separators, "..", null bytes, and other characters that could cause path traversal.
15+
var versionSafeRegex = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9.\-+]*$`)
16+
1317
type SkillMeta struct {
1418
Name string
1519
Description string
@@ -142,3 +146,18 @@ func ValidateSlug(slug string) error {
142146
}
143147
return nil
144148
}
149+
150+
// ValidateVersion checks that a version string is safe for use in file paths.
151+
// It rejects path traversal sequences and characters that could escape the intended directory.
152+
func ValidateVersion(version string) error {
153+
if version == "" {
154+
return fmt.Errorf("version must not be empty")
155+
}
156+
if strings.Contains(version, "..") {
157+
return fmt.Errorf("invalid version '%s': must not contain '..'", version)
158+
}
159+
if !versionSafeRegex.MatchString(version) {
160+
return fmt.Errorf("invalid version '%s': must contain only alphanumeric characters, dots, hyphens, and plus signs", version)
161+
}
162+
return nil
163+
}

0 commit comments

Comments
 (0)