security(skills): validate GitHub repo format and limit download size
Add regex validation for 'owner/repo' format to prevent URL injection in InstallFromGitHub. Add 5 MB LimitReader on skill file downloads to prevent memory exhaustion. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b391e649d2
commit
48b08110de
1 changed files with 10 additions and 1 deletions
|
|
@ -7,12 +7,17 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/fileutil"
|
||||
"github.com/sipeed/picoclaw/pkg/utils"
|
||||
)
|
||||
|
||||
const maxSkillFileSize int64 = 5 << 20 // 5 MB — SKILL.md files should never approach this
|
||||
|
||||
var repoPattern = regexp.MustCompile(`^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$`)
|
||||
|
||||
type SkillInstaller struct {
|
||||
workspace string
|
||||
}
|
||||
|
|
@ -24,6 +29,10 @@ func NewSkillInstaller(workspace string) *SkillInstaller {
|
|||
}
|
||||
|
||||
func (si *SkillInstaller) InstallFromGitHub(ctx context.Context, repo string) error {
|
||||
if !repoPattern.MatchString(repo) {
|
||||
return fmt.Errorf("invalid repository format %q: must be 'owner/repo'", repo)
|
||||
}
|
||||
|
||||
skillDir := filepath.Join(si.workspace, "skills", filepath.Base(repo))
|
||||
|
||||
if _, err := os.Stat(skillDir); err == nil {
|
||||
|
|
@ -48,7 +57,7 @@ func (si *SkillInstaller) InstallFromGitHub(ctx context.Context, repo string) er
|
|||
return fmt.Errorf("failed to fetch skill: HTTP %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(io.LimitReader(resp.Body, maxSkillFileSize))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue