mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-20 02:17:24 +00:00
fix(mcp): unified grant revocation with per-agent tool group isolation
- Add GrantChecker interface with cache + event-bus invalidation for revalidating MCP tool grants at execution time (not just dispatch) - Move toolGroups from package-level global to per-Registry field; Clone() gives each agent Loop isolated tool groups, eliminating cross-agent race condition - BridgeTool.Execute rechecks grant validity before executing MCP methods; uses serverID field for cache key - Wire MCPGrantChecker through ResolverDeps to MCP Manager and LoopConfig - Add integration test for grant revocation scenarios - Update policy functions to accept *Registry parameter
This commit is contained in:
1 parent
8618ed94b2
commit
8b8da3a3dd
20 files changed
+1128
-150
No files matched your search
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/nextlevelbuilder/goclaw/internal/bus"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/config"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/i18n"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/skills"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/store"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/store/pg"
|
||||
)
|
||||
@@ -132,6 +133,19 @@ func (h *SkillsHandler) doSkillsImport(ctx context.Context, r io.Reader, userID
|
||||
continue
|
||||
}
|
||||
|
||||
// Security guard: scan SKILL.md for malicious content BEFORE any disk/DB write
|
||||
if entry.skillMD != nil {
|
||||
violations, safe := skills.GuardSkillContent(string(entry.skillMD))
|
||||
if !safe {
|
||||
slog.Warn("security.skills.import_rejected",
|
||||
"slug", slug,
|
||||
"violations", len(violations),
|
||||
"first_rule", violations[0].Reason)
|
||||
summary.SkillsSkipped++
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var meta struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
|
||||
@@ -106,6 +106,20 @@ func (h *SkillsHandler) handleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Security guard: scan for malicious content BEFORE any disk/DB write
|
||||
violations, safe := skills.GuardSkillContent(skillContent)
|
||||
if !safe {
|
||||
slog.Warn("security.skills.upload_rejected",
|
||||
"user_id", userID,
|
||||
"violations", len(violations),
|
||||
"first_rule", violations[0].Reason)
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{
|
||||
"error": i18n.T(locale, i18n.MsgInvalidRequest, "skill content failed security scan"),
|
||||
"violations": skills.FormatGuardViolations(violations),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
name, description, slug, frontmatter := skills.ParseSkillFrontmatter(skillContent)
|
||||
if name == "" {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": i18n.T(locale, i18n.MsgRequired, "name in SKILL.md frontmatter")})
|
||||
|
||||
Reference in new issue
Block a user