feat(engine): M8 cleanup — Wave B skill enforcement

- Add tool.PathSensitiveTool interface (ExtractPaths); implement on all 6 fs tools
- Add engine.TurnOptions.AllowedPaths: restricts tool filesystem access per skill invocation
- Bash is denied outright when AllowedPaths is active (unparseable command args)
- fs tools with empty path (cwd default) resolved via os.Getwd() and validated
- Add engine.TurnOptions.AllowedTools + AllowedPaths wiring in pipe mode (main.go) and TUI skill dispatch (tui/app.go)
- Remove TODO(M8.3) from skill.Frontmatter — enforcement is now complete
This commit is contained in:
2026-05-07 15:29:33 +02:00
parent 9fb520fba6
commit 176926924c
15 changed files with 462 additions and 4 deletions
+5
View File
@@ -505,6 +505,11 @@ func (e *Engine) executeSingleTool(ctx context.Context, call message.ToolCall, t
}
}
// Path restriction: deny bash and validate fs tool paths against AllowedPaths.
if denied, blocked := checkPathRestriction(call, t, args, e.turnOpts.AllowedPaths); blocked {
return denied
}
e.logger.Debug("executing tool", "name", call.Name, "id", call.ID)
result, err := t.Execute(ctx, args)