Skip to content

Commit b5ad7fd

Browse files
committed
Sanitize skill directory paths at use site to satisfy CodeQL
Apply filepath.Clean at every point where a path is retrieved from the clientDirs/allDirs map before a filesystem operation (os.Stat, Extract, WriteFiles, Remove). CodeQL's taint tracker loses the sanitization done at storage time once the value flows through a map; cleaning at retrieval makes the guard visible to the analyzer at each individual sink. Signed-off-by: Samuele Verzi <samu@stacklok.com> Made-with: Cursor
1 parent cccfacf commit b5ad7fd

1 file changed

Lines changed: 13 additions & 13 deletions

File tree

pkg/skills/skillsvc/skillsvc.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ func (s *service) applyGitInstallExisting(
805805
return &skills.InstallResult{Skill: existing}, nil
806806
}
807807
for _, ct := range toWrite {
808-
dir := clientDirs[ct]
808+
dir := filepath.Clean(clientDirs[ct])
809809
if _, statErr := os.Stat(dir); statErr == nil && !opts.Force {
810810
return nil, httperr.WithCode(
811811
fmt.Errorf("directory %q exists but is not managed by ToolHive; use force to overwrite", dir),
@@ -836,7 +836,7 @@ func (s *service) applyGitInstallFresh(
836836
files []gitresolver.FileEntry,
837837
) (*skills.InstallResult, error) {
838838
for _, ct := range clientTypes {
839-
dir := clientDirs[ct]
839+
dir := filepath.Clean(clientDirs[ct])
840840
if _, statErr := os.Stat(dir); statErr == nil && !opts.Force {
841841
return nil, httperr.WithCode(
842842
fmt.Errorf("directory %q exists but is not managed by ToolHive; use force to overwrite", dir),
@@ -864,21 +864,21 @@ func (s *service) gitWriteMultiAndPersist(
864864
) (*skills.InstallResult, error) {
865865
var written []string
866866
for _, ct := range dirsToWrite {
867-
dir := clientDirs[ct]
867+
dir := filepath.Clean(clientDirs[ct])
868868
writeMode := opts.Force
869869
if writeAggressive {
870870
writeMode = true
871871
}
872872
if writeErr := gitresolver.WriteFiles(files, dir, writeMode); writeErr != nil {
873873
for _, wct := range written {
874-
_ = s.installer.Remove(clientDirs[wct])
874+
_ = s.installer.Remove(filepath.Clean(clientDirs[wct]))
875875
}
876876
return nil, fmt.Errorf("writing git skill: %w", writeErr)
877877
}
878878
if checkErr := skills.CheckFilesystem(dir); checkErr != nil {
879879
_ = s.installer.Remove(dir)
880880
for _, wct := range written {
881-
_ = s.installer.Remove(clientDirs[wct])
881+
_ = s.installer.Remove(filepath.Clean(clientDirs[wct]))
882882
}
883883
return nil, fmt.Errorf("post-extraction verification failed: %w", checkErr)
884884
}
@@ -889,14 +889,14 @@ func (s *service) gitWriteMultiAndPersist(
889889
if isUpgrade {
890890
if err := s.store.Update(ctx, sk); err != nil {
891891
for _, wct := range written {
892-
_ = s.installer.Remove(clientDirs[wct])
892+
_ = s.installer.Remove(filepath.Clean(clientDirs[wct]))
893893
}
894894
return nil, err
895895
}
896896
} else {
897897
if err := s.store.Create(ctx, sk); err != nil {
898898
for _, wct := range written {
899-
_ = s.installer.Remove(clientDirs[wct])
899+
_ = s.installer.Remove(filepath.Clean(clientDirs[wct]))
900900
}
901901
return nil, err
902902
}
@@ -1404,7 +1404,7 @@ func (s *service) installExtractionSameDigestNewClients(
14041404
}
14051405
var written []string
14061406
for _, ct := range toWrite {
1407-
dir := clientDirs[ct]
1407+
dir := filepath.Clean(clientDirs[ct])
14081408
if _, statErr := os.Stat(dir); statErr == nil && !opts.Force {
14091409
removeSkillDirs(s.installer, clientDirs, written)
14101410
return nil, httperr.WithCode(
@@ -1428,7 +1428,7 @@ func (s *service) installExtractionSameDigestNewClients(
14281428

14291429
func removeSkillDirs(inst skills.Installer, clientDirs map[string]string, clients []string) {
14301430
for _, ct := range clients {
1431-
_ = inst.Remove(clientDirs[ct])
1431+
_ = inst.Remove(filepath.Clean(clientDirs[ct]))
14321432
}
14331433
}
14341434

@@ -1447,7 +1447,7 @@ func (s *service) installExtractionUpgradeDigest(
14471447
}
14481448
var written []string
14491449
for _, ct := range allClients {
1450-
dir := allDirs[ct]
1450+
dir := filepath.Clean(allDirs[ct])
14511451
if _, exErr := s.installer.Extract(opts.LayerData, dir, true); exErr != nil {
14521452
removeSkillDirs(s.installer, allDirs, written)
14531453
return nil, fmt.Errorf("extracting skill upgrade: %w", exErr)
@@ -1470,7 +1470,7 @@ func (s *service) installExtractionFresh(
14701470
clientDirs map[string]string,
14711471
) (*skills.InstallResult, error) {
14721472
for _, ct := range clientTypes {
1473-
dir := clientDirs[ct]
1473+
dir := filepath.Clean(clientDirs[ct])
14741474
if _, statErr := os.Stat(dir); statErr == nil && !opts.Force {
14751475
return nil, httperr.WithCode(
14761476
fmt.Errorf("directory %q exists but is not managed by ToolHive; use force to overwrite", dir),
@@ -1480,7 +1480,7 @@ func (s *service) installExtractionFresh(
14801480
}
14811481
var written []string
14821482
for _, ct := range clientTypes {
1483-
dir := clientDirs[ct]
1483+
dir := filepath.Clean(clientDirs[ct])
14841484
if _, exErr := s.installer.Extract(opts.LayerData, dir, opts.Force); exErr != nil {
14851485
removeSkillDirs(s.installer, clientDirs, written)
14861486
return nil, fmt.Errorf("extracting skill: %w", exErr)
@@ -1490,7 +1490,7 @@ func (s *service) installExtractionFresh(
14901490
sk := buildInstalledSkill(opts, scope, clientTypes, nil)
14911491
if err := s.store.Create(ctx, sk); err != nil {
14921492
for _, ct := range clientTypes {
1493-
_ = s.installer.Remove(clientDirs[ct])
1493+
_ = s.installer.Remove(filepath.Clean(clientDirs[ct]))
14941494
}
14951495
return nil, err
14961496
}

0 commit comments

Comments
 (0)