Commit Graph
4 Commits
Author SHA1 Message Date
Anandan 96859c9bd1 feat(sandbox): unify command execution and enforcement (#781)
* feat(sandbox): unify command execution and enforcement

* test(sandbox): make platform contracts portable

* fix(sandbox): close execution lifecycle races

Bound retained interactive output, preserve interruption state, and start workspace observation before process launch.

Protect active runtime roots with cross-platform leases, capture transient protected-path creation events, and restore process attributes after PTY fallback.

* fix(sandbox): restore strict macOS isolation

Remove Seatbelt host-local network allowances after native validation showed localhost filters can reach host interfaces.

Track process reap completion so retained sessions cannot signal a stale numeric PID.
2026-07-21 18:55:13 +05:30
Leonardo Faoro 7d579996b4 feat(skills): discover shared ~/.agents/skills with multi-root skill loading (#696)
* feat(skills): discover shared ~/.agents/skills with multi-root skill loading

Add ~/.agents/skills as a read-only global discovery root after the
primary
Zero skills dir and before plugin roots. Unify runtime and CLI discovery
on
one multi-root path (DiscoveryRoots / LoadFromRoots / GlobalRoots) and
always
register the multi-root skill tool so bare runs and plugin runs share
the
same load surface.
Install/remove/lock still target only the primary Zero skills directory.
Fixes #610

* docs(skills): note lock stays on the primary write root

Document that install/remove/lock target only the primary Zero skills
directory, matching multi-root discovery write-root isolation.

* fix(skills): bubble primary root load errors from LoadFromRoots

Return non-missing failures from the first non-empty skills root so a
broken primary dir is not reported as an empty skill list. Keep fail-open
behavior for optional roots (~/.agents/skills, plugins).

* fix(skills): treat non-directory skills root as error on Windows

Windows maps ENOTDIR to ErrNotExist, so ReadDir on a regular file looked
like a missing skills dir. Reclassify existing non-directories and assert
the portable load behavior in tests.
2026-07-16 21:59:20 +08:00
euxaristia 2efe6d539e fix(plugins): resolve relative executable paths against plugin root (#627)
* fix(plugins): resolve relative executable paths against plugin root

When a plugin registers a tool or a hook command as a relative path (e.g. ./tools/helper.sh), running it in the caller's workspace CWD allows local execution hijacking by placing a malicious script at that path in the untrusted workspace. Update expandPluginRootPath to resolve relative executable paths containing path separators to absolute paths inside the plugin's install directory.

* fix(plugins): remove ineffectual permission initializer in toolSafety

The initial assignment to permission was always overwritten by one of
the switch arms below it, including a case that just reassigned the
same PermissionPrompt value the initializer already held. Flagged by
ineffassign in CI.
2026-07-12 22:34:34 +08:00
KRATOS 6beb0b0908 wedge stage 09: finish plugin wiring (tools/hooks/skills) (#185)
* stage 09: finish plugin wiring (tools/hooks/skills)

Activate resolved plugin manifests so their declared tools, hooks, and
skills take effect at runtime instead of being parsed-but-unconsumed.

- internal/plugins/activate.go: Activate() registers each plugin tool into
  the tools.Registry via a command-runner adapter (JSON args on stdin,
  stdout/exit -> tools.Result, ${AGENT_PLUGIN_ROOT} expansion + env),
  builds hooks.Definition values for plugin hooks, and exposes plugin
  skill search roots. Permission maps allow/prompt/deny -> tools.Safety;
  allow only survives load-time clamping when manifest auto-approval is
  enabled, so mutating plugin tools are not auto-approved by default. A
  plugin-aware skill tool merges the default skills dir with plugin roots
  (recording duplicate names, never crashing). Malformed plugins/extensions
  are skipped with a warning; activation order is deterministic.
- internal/cli: activatePlugins() invokes activation in both bootstrap
  paths (interactive TUI in app.go and one-shot exec in exec.go), after
  core/specialist/MCP registration. newHookDispatcherWithExtra folds plugin
  hooks into the dispatcher's hook set. Fails open: a bad plugin warns and
  is skipped, never wedging startup.
- internal/plugins/plugins.go: update the stale 'not yet registered' note.

* stage 09: normalize plugin command path separators for Windows

expandPluginRoot kept the manifest's forward slashes, so a ${AGENT_PLUGIN_ROOT}/bin/x command became a mixed-separator path on Windows (C:\...\001/bin/x), failing the path tests. Added expandPluginRootPath (filepath.FromSlash on the placeholder-expanded executable path only; args keep their slashes since they may be URLs/flags) and used it for the tool and hook command paths.

* stage 09: address plugin wiring review

- surface per-plugin load diagnostics on stderr (not just top-level errors)
- skip plugin tools whose name collides with an already-registered tool
- resolve manifest-relative plugin skill paths against the plugin dir

* stage 09: fall back to plugin path/id when manifest path unknown in load diagnostic
2026-06-13 10:21:14 +05:30