Skip to content

fix(skills): persist skill files with atomic replace - #77

Draft
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/high-severity-issues-726e
Draft

fix(skills): persist skill files with atomic replace#77
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/high-severity-issues-726e

Conversation

@cursor

@cursor cursor Bot commented Aug 31, 2026

Copy link
Copy Markdown

Bug and impact

skill_update (authenticated PUT /api/skills/:name) opened the live skill .md with fopen("w"), which truncates before any bytes are written. On ENOSPC/EFBIG/crash after truncate, the existing skill was wiped. With stdio buffering, fwrite could even report a full write while fclose flushed only a partial file — returning success after destroying the skill.

Trigger: Dashboard or API updates an existing skill while the filesystem cannot complete the new write (disk full, or RLIMIT_FSIZE in the regression test). The prior skill body is gone; agents that depend on that skill lose behavior.

Distinct from open PR #71 (auth_pair token store) — same truncate-then-write class, different file (skills/*.md via gateway skills CRUD).

Root cause

In-place truncate-then-write with unchecked fclose, same anti-pattern as #71 / config save (which already use temp+rename).

Fix

Write skill content to path.tmp, fsync, then rename over the live file. Used by both skill_update and skill_create.

Validation

  • ./build/test_skill — all tests passed, including test_skill_update_write_failure_preserves_existing (RLIMIT_FSIZE=8)
  • Minimized old-path repro under the same limit: live file became 8 As with return success
  • Same suite under gcc ASan/UBSan: passed
Open in Web View Automation 

skill_update opened the live .md with fopen("w"), truncating before
fwrite. Under ENOSPC/EFBIG the original skill was wiped (and stdio could
even report success after a partial flush). Write via temp+fsync+rename
so a failed PUT /api/skills/:name leaves the prior skill intact.

Co-authored-by: esadrianno <esadrianno@gmail.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.

1 participant