* feat(#52): add agent_skills_security.trusted_global_roots allowlist Opt-in allowlist so a global: agent skill whose SKILL.md realpath resolves outside the default global skills base (e.g. ~/.claude/skills) is accepted when its real target lies under a user-declared trusted root. Default [] is byte-identical to prior behavior; the symlink-escape guard is preserved and simply re-applied against each declared root. - src/security.cts: loadTrustedGlobalRoots — tilde-expand (~ and ~/), reject project-relative and dangerously broad roots (filesystem/UNC root, homedir), realpath-canonicalize each root every run and drop non-existent ones. - src/init.cts: on base-check failure the guard consults the trusted roots (hoisted out of the loop); emits a stderr NOTE when a skill is accepted via a trusted root so the widened boundary is visible. - src/core.cts: thread agent_skills_security through loadConfig. - config-schema.manifest.json: allow the new key path. - docs/CONFIGURATION.md: document the option and its security model. - tests/agent-skills.test.cjs: unit + end-to-end CLI coverage (regression, feature, negative, broad-root hardening, stderr NOTE). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(#52): add changeset fragment for trusted_global_roots (#754) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -536,6 +536,7 @@ function loadConfig(cwd: string, options: Record<string, unknown> = {}): Record<
|
||||
effort: (parsed['effort']) || null,
|
||||
fast_mode: (parsed['fast_mode']) || null,
|
||||
agent_skills: (parsed['agent_skills']) || {},
|
||||
agent_skills_security: (parsed['agent_skills_security']) || null,
|
||||
manager: (parsed['manager']) || {},
|
||||
response_language: get('response_language') || null,
|
||||
claude_md_path: get('claude_md_path') || null,
|
||||
|
||||
Reference in New Issue
Block a user