Skip to content

feat: verify safetensors integrity after Civitai/HF LoRA download#2206

Merged
atomantic merged 3 commits into
mainfrom
next/issue-2199
Jul 6, 2026
Merged

feat: verify safetensors integrity after Civitai/HF LoRA download#2206
atomantic merged 3 commits into
mainfrom
next/issue-2199

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

A truncated or right-size-but-wrong-bytes LoRA download from Civitai or HuggingFace previously installed silently and then rendered garbage ("mosaic") output at generate time — the leading non-Metal cause of corrupt output. PortOS already verified HF-cached weights (hfCache.js, #1324) but the direct Civitai/HF LoRA install path was not covered.

What changed

  • Exported verifySafetensorsStructure from server/lib/hfCache.js (reachable through the export * barrel; added a README row per the module-organization rule) instead of re-implementing the safetensors header parse.
  • installFromCivitai / installFromHuggingface now run a new verifyDownloadedLora helper after downloadToFile(...) and before writing the sidecar:
    • Always runs the cheap structural header/size check (reads only the header region, never the multi-GB payload).
    • For Civitai, additionally compares the on-disk sha256File(...) against file.hashes.SHA256 (from pickPrimaryFile), case-insensitively (Civitai reports uppercase; sha256File returns lowercase), and only when the digest is a well-formed sha256.
    • On truncation or SHA mismatch, deletes the file and throws a ServerError (CIVITAI_LORA_CORRUPT / HF_LORA_CORRUPT) so the user re-downloads instead of training/rendering against corrupt weights.
  • HuggingFace's metadata doesn't expose a per-file digest through pickHfLoraFile, so the structural check is its integrity guard (no deep sha256 compare available there).

Tests

  • New: corrupt/truncated download → deletes file + throws (CIVITAI_LORA_CORRUPT and HF_LORA_CORRUPT); SHA-256 mismatch → deletes + throws; SHA-256 match (case-insensitive) → installs.
  • Updated existing download fixtures to emit structurally-valid safetensors bytes (a shared validSafetensors() helper) now that downloads are verified.
  • All 43 loras + 22 hfCache/barrel tests pass. codex review: clean.

Closes #2199

https://claude.ai/code/session_012wmkuPi75gYu6rrfhG8jxA

atomantic added 3 commits July 4, 2026 20:53
…A download

Truncated or right-size-but-wrong-bytes LoRA downloads previously installed
silently and rendered garbage ("mosaic") output at generate time — the leading
non-Metal cause of corrupt output. PortOS already verified HF-cached weights
(hfCache.js, #1324) but the direct Civitai/HF LoRA install path was uncovered.

- Export verifySafetensorsStructure from hfCache.js (barrel via export *; README row added)
- installFromCivitai/installFromHuggingface now run a structural header/size
  check after download and, for Civitai, a deep sha256 compare against
  file.hashes.SHA256; on truncation/mismatch the file is deleted and a
  ServerError (CIVITAI_LORA_CORRUPT / HF_LORA_CORRUPT) is thrown so the user
  re-downloads instead of training/rendering against corrupt weights
- Tests: corrupt-download deletion, sha256 mismatch/match (case-insensitive),
  plus updated existing fixtures to emit structurally-valid safetensors bytes

Closes #2199

Claude-Session: https://claude.ai/code/session_012wmkuPi75gYu6rrfhG8jxA
@atomantic atomantic merged commit cfd1061 into main Jul 6, 2026
2 checks passed
@atomantic atomantic deleted the next/issue-2199 branch July 6, 2026 23:54
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.

[ref-watch-phosphene-lora-download-integrity-verify] Verify safetensors integrity after Civitai/HF LoRA download

1 participant