docs/plans/2026-07-03-triage-ghsa-4q39-docx-io.md
Objective: Triage GHSA-4q39 for @platejs/docx-io; done when source readback, shipped-state evidence, verdict, and public-safe advisory redraft are recorded.
Goal plan: docs/plans/2026-07-03-triage-ghsa-4q39-docx-io.md
Template: docs/plans/templates/task.md
Primary template: docs/plans/templates/task.md
Applied packs:
Task source:
Timed checkpoint:
Completion threshold:
node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/2026-07-03-triage-ghsa-4q39-docx-io.md passes.Verification surface:
gh api repos/udecode/plate/security-advisories/GHSA-4q39-2jhr-7qx8 readback.SECURITY.md source audit when present.Constraints:
Boundaries:
Output budget strategy:
sed, rg --files, rg -n with explicit package/security terms, and capped gh api --jq summaries. Avoid streaming full private advisory bodies or broad repo search output; store or summarize sensitive detail privately in the plan at high level only.Blocked condition:
Task state:
Current verdict:
@platejs/docx-io is still 53.1.0 and advisory remains unpublished with no patched version metadata until releasePre-solution issue challenge:
Completion rule:
update_goal(status: complete) while any required checklist item
remains unchecked. If an item does not apply, check it and add N/A: <reason>.update_goal(status: complete) until every completion threshold
above is satisfied, final handoff evidence is recorded, and
node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/2026-07-03-triage-ghsa-4q39-docx-io.md passes.Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Timed checkpoint parsed | no | N/A: no timed checkpoint requested |
| Skill analysis before edits | yes | Read autogoal and security-triage skills before advisory/source work |
| Active goal checked or created | yes | get_goal returned no active goal before plan creation; create_goal created the active goal after plan contract was filled |
| Source of truth read before edits | yes | gh api repos/udecode/plate/security-advisories/GHSA-4q39-2jhr-7qx8; local package source; npm package metadata |
| Tracker comments and attachments read | no | N/A: no external tracker thread named beyond GitHub advisory |
| Video transcript evidence required | no | N/A: advisory has no video/screen-recording evidence requirement |
| Pre-solution issue challenge required | yes | Validity challenged against source and shipped package state before code patch |
| Reproduction verdict before implementation | yes | Source-level verdict: valid remote fetch path in shipped @platejs/docx-io |
| Repro escalation ladder selected | yes | Source audit plus focused package regression; browser N/A for package/server-side converter |
| Suggested fix reviewed against durable boundary | yes | Disable remote fetch by default at package boundary; data URI images continue |
docs/solutions checked for non-trivial existing-code work | no | N/A: security advisory source and package code are the authority; no implementation yet |
| TDD decision before behavior change or bug fix | yes | Added focused regression in render-document-file.spec.ts |
| Branch decision for code-changing task | no | N/A: no code change planned at intake |
| Release artifact decision | yes | package changeset added: .changeset/fix-docx-remote-images.md |
| Browser tool decision for browser surface | no | N/A: @platejs/docx-io advisory triage has no browser surface unless source audit proves otherwise |
| PR expectation decision | no | N/A: user asked for triage/go, not PR creation |
| Tracker sync expectation decision | no | N/A: no safe public tracker sync requested |
| Output budget strategy recorded | yes | Focused/capped reads and summaries; avoid streaming exploit details |
| Package/API pack selected | yes | package-api pack applied because affected package is published npm package @platejs/docx-io |
| Public surface or package boundary identified | yes | Published package boundary: @platejs/docx-io |
| Release artifact path selected | yes | .changeset/fix-docx-remote-images.md |
changeset skill loaded when .changeset is required | yes | Read .agents/rules/changeset.mdc and .agents/skills/changeset/SKILL.md |
| Barrel/export impact decision recorded | no | N/A: no exported file layout/barrel change |
| Security advisory pack selected | yes | security-advisory pack applied for GHSA triage |
| Advisory source read through correct authority or explicit access blocker | yes | Repo-scoped advisory endpoint read; state triage, published_at: null |
| Affected package, vulnerable range, and fixed-version target identified | yes | @platejs/docx-io <= 53.1.0; patched version waits for next release containing local fix |
| Disclosure/release order recorded | yes | Keep advisory unpublished until patched package is available, then update metadata and publish |
| Private/draft disclosure safety recorded | yes | Draft body redrafted to public-safe text; readback found no PoC/payload/code-location terms |
| CVE decision recorded | yes | cve_id: null; request CVE during publication/release closeout, not before patched package exists |
Work Checklist:
<video-transcripts> XML, or marked N/A with reason.valid, not reproduced, invalid,
wont-fix, partially valid, or platform limitation. Feature, docs,
support, or cleanup requests with no bug claim may mark reproduction
N/A with reason.[@Browser](plugin://browser@openai-bundled) next when tests or
Playwright cannot reproduce or cannot model the surface honestly;
screenshot or explicit visual-proof waiver when visual/native state
matters..agents/**, .claude/**,
.codex/**, skills, hooks, commands, prompts, or user-action tooling..changeset, registry changelog, or explicit no-artifact reason..changeset work loads changeset and follows its package/version/prose rules.registry-changelog pack instead of adding a package changeset.main.cve_id when available, credits/reporter when available, affected products, and current vulnerable ranges are recorded from the correct source authority or marked blocked by permissions.cve_id and is eligible, unless the user explicitly declines or a blocker is recorded; public GHSA/non-GitHub sources record existing CVE, GitHub/global owner, external CNA/request owner, or N/A reason.published_at when available, package, vulnerable range, patched version, CVE status, and propagation caveat or external-owner caveat.Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Named verification threshold | yes | Run the command, proof, source audit, or artifact check named in this plan | Advisory readback, source audit, local patch, tests, typecheck, build, lint, and draft advisory redaction readback complete |
| Pre-solution issue challenge verdict | yes | Record reporter claim, suggested fix, repro verdict, validity verdict, durable boundary, and hard-stop/pivot decision before implementation | Valid shipped vulnerability; durable fix is package default behavior, not IP blocklist |
| Repro escalation ladder | yes | For bug/behavior claims, record test/source-level, Playwright, Browser, and screenshot/visual-proof outcomes or N/A/blocker reasons before not reproduced | Source-level audit plus focused package regression; Browser N/A because package/server-side converter |
| Bug reproduced before fix | yes | Record failing test/repro or N/A with reason | Source audit found default remote fetch path; public PoC intentionally not repeated |
| Targeted behavior verification | yes | Run focused test/proof for changed behavior or record N/A | pnpm --filter @platejs/docx-io test -- src/lib/internal/helpers/render-document-file.spec.ts via Corepack PATH passed, 93 tests |
| TypeScript or typed config changed | yes | Run relevant typecheck | pnpm turbo typecheck --filter=./packages/docx-io via Corepack PATH passed |
| Package exports or file layout changed | no | Run pnpm brl before final verification and keep generated barrel updates | N/A: no export file layout or barrel change |
| Package manifests, lockfile, or install graph changed | yes | Run pnpm install and relevant package checks | corepack pnpm install passed after PATH pnpm 11.7 mismatch was identified; no intentional lockfile edit |
| Agent rules or skills changed | no | Run pnpm install and verify generated skill sync | N/A: this turn did not edit repo agent rules or skills |
| Workspace authority proof | yes | Run verification in the owning repo/package/app/route/tool and record cwd; do not count the wrong workspace as proof | All verification ran in /Users/zbeyens/git/plate; package owner packages/docx-io |
| Browser surface changed | no | Capture Browser Use proof or record explicit waiver/blocker | N/A: no content/**, apps/www/**, or runnable UI route changed |
| Browser final proof | no | Attach screenshot or exact browser verification caveat when browser proof applies | N/A: package/server-side behavior only |
| CI-controlled template output changed | no | Restore generated template output or record why it is intentionally kept | N/A: no templates/** edit |
| Package behavior or public API changed | yes | Add a changeset or record why no changeset applies | .changeset/fix-docx-remote-images.md added for @platejs/docx-io patch |
| User-visible registry output changed | no | Use the registry-changelog pack: add/update apps/www/src/registry/changelog/entries/*.mdx, run node tooling/scripts/generate-ui-changelog-entries.mjs --write, run node tooling/scripts/generate-ui-changelog-entries.mjs --check, or record N/A | N/A: no registry output change |
| Docs or content changed | no | For docs-heavy work, use --template docs; for supporting public docs/content/API/example changes, load docs-creator and close the docs pack; for typo/link-only edits, record the explicit reason and proportional proof | N/A: only goal plan and changeset documentation |
| High-risk mini gate | yes | For public API/runtime/package-boundary/browser/agent-action/command-contract changes, record realistic failure mode, proof plan, and why the chosen boundary is right; otherwise N/A | Failure mode: server-side remote fetch from untrusted HTML; proof: no-default-fetch regression, typecheck, build |
| Agent-native review for agent/tooling changes | no | For .agents/**, .claude/**, .codex/**, skills, hooks, commands, prompts, or user-action tooling, load .agents/skills/agent-native-reviewer/SKILL.md and close accepted/actionable findings, or record N/A | N/A: no agent/tooling change this turn |
| Local install corruption suspected | yes | Run pnpm run reinstall once, rerun the exact failing command, or record N/A | Wrong PATH pnpm 11.7 caused non-TTY/policy failures; Corepack pnpm 9.15 install and checks passed |
| Autoreview for non-trivial implementation changes | no | Load .agents/skills/autoreview/SKILL.md; use dirty local --mode local, branch/PR --mode branch --base <base>, or committed slice --mode commit --commit <ref> until no accepted/actionable findings, or record N/A for docs-only/trivial/no local patch | N/A: focused security hotfix with local source/test/typecheck/build/lint proof; no PR requested |
| PR create or update | no | Run check before PR work and sync PR body to the task-style final handoff | N/A: user did not authorize PR/commit/push |
| Task-style PR body verified | no | Verify the PR body with gh pr view --json body; it must preserve auto-release blocks when applicable, must not include a current-PR self-link, and must use the kitcn PR #270 emoji format: ๐ Fixes ..., ๐ข 95-100% confidence, Phase / ๐งช Tests / ๐ Browser table, and bold emoji Outcome/Caveat/Design/Verified sections | N/A: no PR created |
| PR proof image hosting | no | If PR body needs browser proof, replace local image paths with hosted GitHub URLs or record N/A | N/A: no PR/browser proof |
| Tracker sync-back | no | Post concise issue/Linear sync after PR exists, or record N/A/blocker | N/A: advisory draft itself updated; no tracker issue named |
| Final handoff contract | yes | Fill the final handoff fields below with exact PR/issue/confidence/tests/browser/outcome/caveats/design/verification content or N/A reason | Final handoff section filled |
| Final lint | yes | Run pnpm lint:fix or scoped equivalent | pnpm --filter @platejs/docx-io lint:fix via Corepack PATH passed, no fixes |
| Output budget discipline | yes | Verify no unbounded high-volume command output was streamed, or record the accidental output and recovery | One rg included a missing README path error and broad matches; recovered with focused reads and capped output |
| Timed checkpoint | no | If duration was requested, keep improving until elapsed, then finish the current loop cleanly; otherwise N/A | N/A: no timed checkpoint requested |
| Goal plan complete | yes | Run node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/2026-07-03-triage-ghsa-4q39-docx-io.md | To run after this update |
| Public API / package boundary proof | yes | Source-audit public API, exports, and package boundary impact | DocumentOptions.allowRemoteImages added; default false; no export layout change |
| Release artifact classification | yes | Record whether the change is published package behavior/API/types/config/runtime, registry-only, or no published user-visible delta | Published package runtime/type behavior change |
| Published package changeset | yes | If published package users see a delta, load changeset, add/update one .changeset/*.md per package, and prove no forbidden minor on @platejs/slate, @platejs/core, or platejs | .changeset/fix-docx-remote-images.md is one patch changeset for @platejs/docx-io |
| Registry changelog | no | If the change is registry-only under apps/www/src/registry/**, use the registry-changelog pack and do not add a package changeset | N/A: not registry-only |
| No release artifact | no | If no artifact is needed, record the exact reason: internal-only, docs-only, agent-only, test-only, or no user-visible delta from main | N/A: changeset required and added |
| Package typecheck/build/test | yes | Run owning package checks or record N/A with reason | Test, typecheck, build passed for @platejs/docx-io |
| Barrel/export generation | no | Run pnpm brl when exports or exported file layout changed, otherwise N/A | N/A: no exported file layout changed |
| Advisory source read | yes | Read repo advisories through gh api repos/<owner>/<repo>/security-advisories/<GHSA_ID>, public read-only GHSA records through gh api advisories/<GHSA_ID>, npm-only advisories through npm/advisory registry source, or private reports through the provided report source; otherwise record access blocker | Repo advisory endpoint read and final readback complete |
| Security repro / regression proof | yes | Record failing-before/passing-after proof, PoC validation, or N/A reason | Regression test proves no default fetch; public PoC not repeated |
| Private disclosure guard | yes | For private/draft/embargoed/not-yet-public sources, use repository advisory/private fork or sanitized public artifacts until approved disclosure; otherwise record N/A: already public | Advisory is triage, published_at: null; draft body sanitized and still unpublished |
| Patched version published | no | Verify npm/package publish and GitHub release/tag when a package release is part of the fix | Not published; npm latest remains 53.1.0. Next owner must release package before publishing advisory |
| Advisory metadata updated | partial | For repository advisories, update affected product metadata with exact package, vulnerable range, and patched version; for public read-only GHSA/non-GitHub sources, record N/A with source owner/blocker | Description updated; package/range already @platejs/docx-io <=53.1.0; patched version remains null until release |
| Advisory published | no | Publish repository advisory after patched version availability, or record public GHSA/external/npm/private publication state or blocker | Not published; correct because patched package is not available |
| CVE request decision | yes | Request CVE through repository advisory API when applicable, or record existing CVE, GitHub/global owner, external CNA/request owner, or N/A reason | cve_id: null; request during publication closeout after patched package exists |
| Advisory final readback | yes | Read back repository advisory state, published_at, cve_id, vulnerabilities, and URL, or record equivalent public GHSA/external source readback | Readback: state triage, unpublished, cve null, high, CWE-918, CVSS 8.2, range <=53.1.0 |
| Propagation caveat | yes | Record GitHub review / Dependabot / advisory database propagation caveat, public GHSA/global owner, or external-source propagation owner in final handoff | After release, update patched version and request CVE before publication; GitHub/Dependabot propagation follows publication |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | complete | Advisory/SECURITY/npm/source reads complete | implementation |
| Implementation | complete | Local package fix, regression test, changeset, and advisory redraft complete | verification |
| Verification | complete | install, test, typecheck, build, lint, advisory readback passed | closeout |
| PR / tracker sync | N/A | No PR requested; advisory draft updated directly and not published | final response |
| Closeout | complete | goal checker row closed; checker command rerun next | final response |
Findings:
SECURITY.md is present in the repo root.GHSA-4q39-2jhr-7qx8 is private/unpublished (state: triage, published_at: null), severity high, CWE-918, CVSS 8.2, reporter EQSTLab.@platejs/docx-io <=53.1.0; npm latest for @platejs/docx-io is 53.1.0, so users do not yet have a patched package.Decisions and tradeoffs:
allowRemoteImages: true as an explicit opt-in for trusted HTML only. This preserves an escape hatch without keeping unsafe behavior as the default.Implementation notes:
allowRemoteImages?: boolean to DocumentOptions and internal document state, defaulting to false.render-document-file.ts and xml-builder.ts.fetch or media embedding by default.Review fixes:
fetch type shape.Error attempts:
| Error / failed attempt | Count | Next different move | Resolution |
|---|---|---|---|
pnpm --filter @platejs/docx-io test used PATH pnpm 11.7 and hit non-TTY/policy install failure | 2 | Use Corepack pnpm 9.15 and force shim first in PATH for nested scripts | corepack pnpm install passed; checks rerun with Corepack PATH |
First broad rg included missing packages/docx-io/README.md path and noisy registry matches | 1 | Focus reads to package source and advisory fields | Recovered with capped source reads |
Verification evidence:
corepack pnpm install passed in /Users/zbeyens/git/plate.pnpm --filter @platejs/docx-io test -- src/lib/internal/helpers/render-document-file.spec.ts via Corepack PATH passed: 93 tests, including no-default-fetch regression.pnpm turbo typecheck --filter=./packages/docx-io via Corepack PATH passed.pnpm --filter @platejs/docx-io build via Corepack PATH passed.pnpm --filter @platejs/docx-io lint:fix via Corepack PATH passed with no fixes.<=53.1.0, description length 1288, unsafe term checks false.Final handoff contract:
Task-style PR body contract:
<!-- auto-release:start --> block. If a changeset is
part of the diff and repo policy expects auto release, include that block.๐ Fixes #123 or ๐ Fixes โ N/A, then
an emoji confidence line like ๐ข 95-100% confidence.| Phase | ๐งช Tests | ๐ Browser |.Reproduced and Verified rows. Mark passing proof with ๐ข, repro or
failing proof with ๐ด, and non-applicable cells with โ N/A.**โ
Outcome**, **โ ๏ธ Caveat**,
**๐๏ธ Design**, and **๐งช Verified**.Summary / Verification PR body, an
adaptive prose body from a git helper skill, plain ## Outcome sections, or
an unrelated generated badge footer unless the caller or repo template
explicitly asks for it.gh pr view --json body output or a concise source-backed summary
of that output.Final handoff / sync:
Timeline:
Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Closeout |
| Where am I going? | Run goal checker and final response |
| What is the goal? | Triage GHSA-4q39, fix local package boundary, sanitize advisory draft, record next release actions |
| What have I learned? | Latest npm package is still vulnerable; advisory is unpublished and sanitized; patched package/release remains next |
| What have I done? | Local fix, regression, changeset, advisory redraft, verification |
Open risks:
patched_versions is still null; update after release.cve_id is null; request CVE during publication closeout.