Skip to content

Harden skills-get against hostile SKILL.md frontmatter and unverified JSON output - #408

Merged
jancurn merged 1 commit into
mainfrom
claude/gallant-bardeen-vf72rn
Sep 19, 2026
Merged

jancurn merged 1 commit into
mainfrom
claude/gallant-bardeen-vf72rn

Conversation

@jancurn

@jancurn jancurn commented Sep 19, 2026

Copy link
Copy Markdown
Member

Fixes two server-triggerable issues found in the v0.7.0-beta.0 release review of the skills extension (#401): a SKILL.md line with a long run of spaces inside a field name made the frontmatter parser backtrack quadratically and hang skills-get for hours, and skills-get --json printed every contents[] item the server returned while verifying only one.

  • Frontmatter key split is now a single pass; nesting is capped at 32 levels (parse error instead of stack overflow); lines indented left of their block's first field are refused instead of silently dropped
  • skills-get --json emits one content item rebuilt from the verified bytes
  • Unit tests for each case; docs/security-review-2026-09.md gets the release-review status updates and a v0.7.0-beta.0 addendum

Refs #401

🤖 Generated with Claude Code

https://claude.ai/code/session_018UEz9rKjGcS6PmcKgNvT85


Generated by Claude Code

… JSON output

Two findings from the v0.7.0-beta.0 release review of the new skills
extension code, both triggerable by a remote MCP server:

- The frontmatter key parser matched `[^:#]+?\s*:\s`, which backtracks
  quadratically on a long run of spaces inside a field name: 0.5 s at
  20k spaces, hours within the 10 MB IPC cap, hanging the CLI in every
  output mode. Replaced by a single-pass split. A nesting-depth cap (32)
  turns a stack overflow on deeply nested collections into a parse error,
  and lines indented left of their block's first field are refused
  instead of silently dropped from the compared frontmatter.
- `skills-get --json` verified only the `contents[]` item matching the
  target URI but emitted the whole array the server returned, so an
  extra item at `contents[0]` reached the caller unverified. JSON mode
  now emits a single item rebuilt from the verified bytes.

Also records the release review in docs/security-review-2026-09.md:
H5 and M9 fixed, M3 partly fixed, plus an addendum for v0.7.0-beta.0.

Refs #401

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018UEz9rKjGcS6PmcKgNvT85
@jancurn
jancurn merged commit c8e9d1f into main Sep 19, 2026
7 checks passed
@jancurn
jancurn deleted the claude/gallant-bardeen-vf72rn branch September 19, 2026 21:28
jancurn added a commit that referenced this pull request Sep 20, 2026
…s in hints (#410)

Two small fixes from the v0.7.0-beta.1 release security review, plus the
review write-up. A hostile `SKILL.md` could crash the CLI with a stack
overflow despite the 32-level nesting cap, and the copy-paste hints
after `skills-get`, `resources-directory-read` and `resources-read`
interpolated server-supplied names unquoted, so a skill named `pdf; curl
… | sh #` produced a hint that ran the injected command.

- Check the nesting depth at the top of `parseMapping` and
`parseSequence`, which recurse into each other directly and bypassed the
check in `parseBlock`; an 8.6 MB alternating frontmatter now fails with
a parse error instead of a `RangeError`.
- Route the four hint sites through `quoteShellArg()` (`formatPath()`
now delegates to it); unit tests cover hostile names and URIs.
- Add the beta.1 addendum to `docs/security-review-2026-09.md` and
correct H5 to "partially fixed": profiles created before 0.7 still
refresh at whatever authorization server the MCP server points to.
Everything else in the addendum is left for follow-ups.

Refs #401, #408

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01J7TdVXNthTXXbmDtGJ7sYm

---
_Generated by [Claude
Code](https://claude.ai/code/session_01J7TdVXNthTXXbmDtGJ7sYm)_

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants