Comments resolved
This commit is contained in:
parent
15c14ebc79
commit
8068b7dcfd
5 changed files with 32 additions and 9 deletions
|
|
@ -1344,13 +1344,19 @@ func skillsInstallFromRegistry(cfg *config.Config, registryName, slug string) {
|
|||
|
||||
result, err := registry.DownloadAndInstall(ctx, slug, "", targetDir)
|
||||
if err != nil {
|
||||
os.RemoveAll(targetDir)
|
||||
rmErr := os.RemoveAll(targetDir)
|
||||
if rmErr != nil {
|
||||
fmt.Printf("\u2717 Failed to remove partial install: %v\n", rmErr)
|
||||
}
|
||||
fmt.Printf("\u2717 Failed to install skill: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if result.IsMalwareBlocked {
|
||||
os.RemoveAll(targetDir)
|
||||
rmErr := os.RemoveAll(targetDir)
|
||||
if rmErr != nil {
|
||||
fmt.Printf("\u2717 Failed to remove partial install: %v\n", rmErr)
|
||||
}
|
||||
fmt.Printf("\u2717 Skill '%s' is flagged as malicious and cannot be installed.\n", slug)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const (
|
|||
defaultMaxResponseSize = 2 * 1024 * 1024 // 2 MB
|
||||
)
|
||||
|
||||
// ClawHubRegistry implements SkillRegistry for the ClawhHub platform.
|
||||
// ClawHubRegistry implements SkillRegistry for the ClawHub platform.
|
||||
type ClawHubRegistry struct {
|
||||
baseURL string
|
||||
authToken string // Optional - for elevated rate limits
|
||||
|
|
@ -31,7 +31,7 @@ type ClawHubRegistry struct {
|
|||
client *http.Client
|
||||
}
|
||||
|
||||
// NewClawHubRegistry creates a new ClawhHub registry client from config.
|
||||
// NewClawHubRegistry creates a new ClawHub registry client from config.
|
||||
func NewClawHubRegistry(cfg ClawHubConfig) *ClawHubRegistry {
|
||||
baseURL := cfg.BaseURL
|
||||
if baseURL == "" {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ type RegistryConfig struct {
|
|||
MaxConcurrentSearches int
|
||||
}
|
||||
|
||||
// ClawHubConfig configures the ClawhHub registry.
|
||||
// ClawHubConfig configures the ClawHub registry.
|
||||
type ClawHubConfig struct {
|
||||
Enabled bool
|
||||
BaseURL string
|
||||
|
|
|
|||
|
|
@ -116,13 +116,29 @@ func (t *InstallSkillTool) Execute(ctx context.Context, args map[string]interfac
|
|||
result, err := registry.DownloadAndInstall(ctx, slug, version, targetDir)
|
||||
if err != nil {
|
||||
// Clean up partial install.
|
||||
os.RemoveAll(targetDir)
|
||||
rmErr := os.RemoveAll(targetDir)
|
||||
if rmErr != nil {
|
||||
logger.ErrorCF("tool", "Failed to remove partial install",
|
||||
map[string]interface{}{
|
||||
"tool": "install_skill",
|
||||
"target_dir": targetDir,
|
||||
"error": rmErr.Error(),
|
||||
})
|
||||
}
|
||||
return ErrorResult(fmt.Sprintf("failed to install %q: %v", slug, err))
|
||||
}
|
||||
|
||||
// Moderation: block malware.
|
||||
if result.IsMalwareBlocked {
|
||||
os.RemoveAll(targetDir)
|
||||
rmErr := os.RemoveAll(targetDir)
|
||||
if rmErr != nil {
|
||||
logger.ErrorCF("tool", "Failed to remove partial install",
|
||||
map[string]interface{}{
|
||||
"tool": "install_skill",
|
||||
"target_dir": targetDir,
|
||||
"error": rmErr.Error(),
|
||||
})
|
||||
}
|
||||
return ErrorResult(fmt.Sprintf("skill %q is flagged as malicious and cannot be installed", slug))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@ import (
|
|||
// ValidateSkillIdentifier validates that the given skill identifier (slug or registry name) is non-empty
|
||||
// and does not contain path separators ("/", "\\") or ".." for security.
|
||||
func ValidateSkillIdentifier(identifier string) error {
|
||||
if identifier == "" {
|
||||
trimmed := strings.TrimSpace(identifier)
|
||||
if trimmed == "" {
|
||||
return fmt.Errorf("identifier is required and must be a non-empty string")
|
||||
}
|
||||
if strings.ContainsAny(identifier, "/\\") || strings.Contains(identifier, "..") {
|
||||
if strings.ContainsAny(trimmed, "/\\") || strings.Contains(trimmed, "..") {
|
||||
return fmt.Errorf("identifier must not contain path separators or '..' to prevent directory traversal")
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue