Skip to content

fix: skill shell hardening (docx DOCTYPE, quoted values, Canvas push checks) - #197

Merged
savvides merged 3 commits into
mainfrom
claude/bugs-skills
Nov 13, 2026
Merged

savvides merged 3 commits into
mainfrom
claude/bugs-skills

Conversation

@savvides

Copy link
Copy Markdown
Owner

Fixes

  • course-import .docx parsing: reject DOCTYPE before ElementTree #182 course-import .docx block: refuses <!DOCTYPE or <!ENTITY with DOCX_READ_FAILED before ElementTree parses.
  • Model-filled values in double-quoted shell strings #183 Quoted-heredoc pattern for --mode (assessment-design, course-builder, course-import, course-quality-review, needs-analysis, red-team), the /idstack:start experience level (now an enum check, LEVEL_BAD), and the Canvas module <position> and assignment <points> (numeric check, PUSH_VALUE_BAD).
  • course-export Canvas push: unchecked HTTP codes, no timeout, duplicates on re-run #180 Canvas push (B4 to B7) of course-export: every call has --max-time 60 and -w "\n%{http_code}". A non-2xx code, a timeout (curl 28) or another curl error stops the block with PUSH_FAILED: <item>: <reason>. Each block first looks the item up by title (module, page, assignment, discussion, module item) and reuses it, so a re-run makes no second POST. Create and add-to-module are now one block per item type (and module create+publish), which removes the model-filled PAGE_URL, ASSIGN_ID and TOPIC_ID. B8 is rewritten to match (stop at the first failure, re-run is safe).
  • Two sessions in one course folder can lose manifest updates #179 (template half) course-import and assessment-design print MANIFEST_UPDATED: before they read shared sections and pass --expect-updated "<value>" (quoted heredoc, no flag when empty) to the merge. On exit 8 the skill re-reads, merges into the changed sections and tries once more.

Tests

  • test/test-skill-shell-zsh.sh: 161 to 249 assertions (bash and zsh): billion-laughs .docx refused, normal .docx still passes; hostile text in the changed blocks (quote, $(touch X), backtick, newline); fake curl extended with 500, timeout (exit 28) and an existing-item listing; asserts orphan-free stop, timeout message, no second POST on re-run, --max-time on every call; stub merge for --expect-updated.
  • test/mutation-test.sh: new cases 66a to 66l. All 12 GUARDED from a frozen copy (the stale-anchor check is built in: expect_fail exits on an unchanged copy).
  • Failing tests were run first and failed before each fix.

Not verified

  • Canvas push was tested only against the fake curl, not a live Canvas. The list lookup reads the first 100 matches of search_term (no pagination), and the real search_term and module-item filters were not checked against the Canvas API.
  • --expect-updated does not exist in scripts/idstack-manifest-merge yet; it arrives with the scripts PR (claude/bugs-scripts). Tests use a stub merge. Until then the real script would reject the flag, so merge this PR with or after the scripts PR.
  • The four Canvas helper copies in course-export are identical by hand, with no drift check.
  • The full 2.5 h mutation suite was not run.

Closes #182
Closes #183
Closes #180
Refs #179 (the scripts PR closes it)

🤖 Generated with Claude Code

savvides and others added 2 commits November 13, 2026 10:00
…checks)

- course-import refuses a .docx with a DOCTYPE or ENTITY (#182)
- model-filled values use a quoted heredoc: --mode, start level, Canvas position and points (#183)
- Canvas push: --max-time 60, HTTP code check, stop on error, reuse items by title (#180)
- course-import and assessment-design pass --expect-updated to the merge (#179, skill side)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h notes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r cases 68a-68l

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@savvides
savvides merged commit 5552a10 into main Nov 13, 2026
6 checks passed
@savvides
savvides deleted the claude/bugs-skills branch November 13, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant