Release cut for the Aug adopt/webui hardening + 2 residual staging gaps
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 42/100
Direzione di ricerca
Read skillopt_sleep/staging.py, especially _live_target_within_roots, the legacy-pair block around L3058-L3130, and _planned_live_directories; reproduce the documented adopt command against the staging layout. Review pyproject.toml for the release version. Done means the legacy path is constrained like the per-skill path, unprovenance staging is rejected, and the released artifact includes the hardened tree.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Two asks: a release cut, and two residual staging gaps the August hardening left open.
Ask 1 — cut a release
PyPI skillopt latest is 0.2.0, released 2026-07-02, with no release since (checked today; pyproject.toml at main still says 0.2.0). Since that wheel was built, main merged:
- #212 (2026-08-20) — safe subset adoption machinery,
- #241 (2026-08-20) — the staging-adopt hardening:
_safe_live_path, sha256 pins, realpath identity, symlink/junction rejection, per-skill roots containment, - #249 (2026-08-29) — webui security hardening (loopback default bind among it).
So pip install skillopt today installs an adopt() with none of #241's checks and a webui that binds 0.0.0.0 by default — while the fixes have been merged for a month. #117 (closed) already showed the practical cost of this exact lag: a wheel-content bug fixed at HEAD that kept biting every fresh install. A 0.2.1 / 0.3.0 cut would make the installable artifact match the hardened tree.
Ask 2 — two residual gaps at HEAD (main @ 79124b37, skillopt_sleep/staging.py blob 615c5ac8cf4c70ccb93e0283e8f7b1439890b6e2)
(a) the legacy SKILL/CLAUDE pair adopt still has no roots containment
_live_target_within_roots (L368 — its own docstring: "the manifest is not a trust boundary") is called on exactly one path: the per-skill adoption (L1508). The legacy-pair block at the bottom of the file (L~3058-3130) validates pins, symlinks/hardlinks, and realpath identity — but never checks the live target against the roots recorded when the night was staged, and _planned_live_directories (L3069) will create parent directories for an absent target at any absolute *.md path the manifest names. The per-skill path gained exactly this containment in #241; the legacy pair didn't. Suggested: re-derive legacy live targets from current config the way the per-skill path does, and run the same _live_target_within_roots check there.
(b) staging has no provenance marker — a staging tree that arrives with a cloned repo is indistinguishable from engine output
Staging lives at <project>/.skillopt-sleep/staging (L829) — project-relative. Nothing about a staging night records that the local engine produced it: the manifest format, file layout, and sha256 pins are all self-consistent and documented, and adopt verifies self-consistency only. #241's threat model (from the PR body) was locally generated, then tampered — "it needs local write access to the staging manifest". The repo-shipped vector needs no local tampering: a cloned project can carry a ready-made .skillopt-sleep/staging/<night>/ and a README/CONTRIBUTING line like "run skillopt-sleep adopt to apply our pre-staged tuned skills". On the current 0.2.0 wheel that is an arbitrary-destination write of repo-authored bytes (verified below); at HEAD the per-skill path confines it to the skills roots, but the legacy pair (gap a) does not.
Suggested: a provenance marker the repo cannot forge — a state-side registry of staged nights (outside the project, e.g. under the sleep state dir), or an HMAC of the manifest keyed by a sleep-state secret — so adopt rejects staging that did not originate from the local engine.
Reproduction on the current wheel (0.2.0)
A scratch clone containing only .skillopt-sleep/staging/20260920-120000/{manifest.json, proposed_SKILL.md, proposed_CLAUDE.md}, with the manifest's live_skill_path set to ../../../../../staged-outside-repo.md, then the product's own documented apply command in that directory:
$ skillopt-sleep adopt
[sleep] adopted from <clone>\.skillopt-sleep\staging\20260920-120000
-> ../../../../../staged-outside-repo.md
-> ./CLAUDE.md
Result: the repo-authored bytes land at the drive root (the overlong ../ chain clamps there on Windows — destination independent of clone depth and username), plus the clone's own CLAUDE.md is overwritten. With an absolute live_skill_path under <home>\.claude\skills\<name>\SKILL.md, the bytes land in the user-global skills root that Claude Code auto-loads in every future session, every project. The wheel's adopt() core (staging.py L137-161 in 0.2.0) is makedirs + shutil.copy2 on the manifest value — no path safety, no pins, no authorship check. At HEAD these specific writes are contained by #241 on the per-skill path (which is why the release cut matters first); the residual is gaps (a) and (b) above.
Happy to help with either a release checklist or a PR for the legacy containment + provenance marker.
- Lingua principale
- Python
- Stelle
- 17.3k
- Fork
- 1.6k
- Merge medio
- 2g 23h
- PR unite (30g)
- 9
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di microsoft/SkillOpt
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
-
项目还在迭代嘛? Aperta
Difficoltà 5/5 Più di una settimana Idoneità per principianti 10/100
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 72/100
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 28/100
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
Tutte le issue di microsoft/SkillOpt
Issue simili
-
area: harness bug status: needs-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
Human-Agent-Society/reef#625 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 80/100
learningequality/kolibri#15351 · 2 commenti ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
-
Name consistency Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
eellak/triplestore#65 · 1 commento ·