Repository navigation
Conversation
Related: fixes #108032. Heads-up for reviewers: the default-deny write guard reverses the behavior merged in #17512 (which intentionally allowed |
|
Compared this PR against the triage note re #17512 (merged 2026-04-29, closed #4759 / #4381) and the related open PR #51412. Shared product surface is real. The landing shape is not a mechanical duplicate — this PR is an intentional default flip with an explicit opt-in escape hatch.
Why default-deny is the safer landing for #108032#108032 is not "users can't edit external skills." It is: external mounts were misclassified and silently mutated.
Default-deny is fail-closed on the mount the user configured as external input, not on agent-authored skills in Opt-in escape hatch (preserves #4759 / #4381)
Maintainer decision (explicit)
Independent delta that stays on this PR:
No review threads, no CI failures, no conflicts on this head. Focused tests: Verified: owner |
|
Independent verification on the PR head (cfe99337): the new test file passes locally, 10/10 (canonical runner). Security read: the fix is complete in both layers. Server side, _external_dirs_write_guard runs for foreground and background callers inside _locate_for_write, covering every mutating skill_manage action (create always lands in ~/.hermes/skills/ by construction, so its absence from the action set is correct). Client side, editability is gated on provenance === 'agent', so the new external badge automatically loses edit affordances. Paths resolve both sides before comparison, and the opt-in key is documented in cli-config.yaml.example. No findings. |
cfe9933 to
607b908
Compare
…lace writes External-dir skills were flattened to provenance=agent (Desktop "learned") and foreground skill_manage could mutate them with no guard. Keep an explicit external_dirs_allow_mutations opt-in for the NousResearch#4759 in-place escape hatch. Co-authored-by: Cursor <cursoragent@cursor.com>
607b908 to
4db906e
Compare
|
Rebased onto current |
|
Thanks @KoNit-K. The provenance half landed in #128387, which gives |
What does this PR do?
Skills mounted via
skills.external_dirswere flattened toprovenance = "agent", so Desktop badged them learned and treated them as agent-owned sediment. The same path had no foreground write guard: background curator already refusesis_external_skill_pathinside_background_review_write_guard, but that helper returns immediately when_is_background_review()is false, soskill_managepatch/edit/write_file/remove_file/delete mutated the external tree in place.This PR:
externalprovenance (hub > bundled > external > agent). The winning on-disk copy must live underget_external_skills_dirs(). A local~/.hermes/skills/create_dircopy still wins asagent. Trusted project skills are not classified external.skill_managemutations ofskills.external_dirsunlessskills.external_dirs_allow_mutationsis truthy. Detection usesis_under_external_skills_dirs, notis_external_skill_path(the latter also matches project dirs, which user-directed edits may still change).externalbadge + i18n; Edit/Archive stay gated onprovenance === 'agent'.Related Issue
Fixes #108032
Type of Change
Changes Made
agent/skill_utils.py— only, fail-open Falsetools/skill_usage.py— returns for external-only winning copieshermes_cli/web_routers/skills.py— uses the same helpertools/skill_manager_guards.py— + : composed in (not gated on background-review)cli-config.yaml— commentedtests/tools/test_external_dirs_provenance_and_write_guard.py— real tmp +How to Test
scripts/run_tests.shon the files in Changes Made — focused verificationscripts/run_tests.sh tests/tools/test_external_dirs_provenance_and_write_guard.py -qscripts/run_tests.sh \Evidence
scripts/run_tests.shon the files in Changes Made — focused verification — focused command GREENChecklist
Code
Documentation & Housekeeping
cli-config.yaml.example: N/ACONTRIBUTING.mdorAGENTS.md: N/A