Skip to content

fix(avatar): cap manual avatar file reads - #11

Open
SebTardif wants to merge 1 commit into
openclaw:mainfrom
SebTardif:fix/manual-avatar-read-cap
Open

fix(avatar): cap manual avatar file reads#11
SebTardif wants to merge 1 commit into
openclaw:mainfrom
SebTardif:fix/manual-avatar-read-cap

Conversation

@SebTardif

Copy link
Copy Markdown
Contributor

What Problem This Solves

clawdex person avatar set PERSON FILE reads the source image with
safefile.ReadPath, which used unbounded io.ReadAll. A multi-gigabyte
file is copied into memory for SHA256 and MIME sniffing before any image
decode. The process can run out of memory. --dry-run uses the same read.

Google import already stops avatar downloads at 10 MiB
(maxAvatarBytes in internal/google/gog.go). Manual set did not.

Evidence

Built clawdex from this branch to /tmp/clawdex-f004-bin. Initialized a
fresh contacts repo, added Proof Person, then pointed avatar set at a
10485761-byte file (10 MiB plus 1).

Unpatched ReadPath loaded the whole file (10485761 bytes, no error).
After the patch the public command fails closed:

$ clawdex person avatar set "Proof Person" huge.bin
file too large: 10485761 bytes (max 10485760)
$ clawdex --dry-run person avatar set "Proof Person" huge.bin
file too large: 10485761 bytes (max 10485760)

A 69-byte PNG still sets normally (avatars/avatar.png, image/png, 1x1).

Real behavior proof

  • Behavior or issue addressed: Manual avatar set and dry-run no longer read an oversized source into memory. They reject files above 10 MiB, the same cap as Google import avatars.

  • Real environment tested: macOS Darwin arm64, Go 1.27.0, clawdex built from this branch to /tmp/clawdex-f004-bin, isolated --config at /tmp/clawdex-f004-proof/config.toml.

  • Exact steps or command run after this patch:

    clawdex --config /tmp/clawdex-f004-proof/config.toml init /tmp/clawdex-f004-proof/contacts --remote ""
    clawdex --config /tmp/clawdex-f004-proof/config.toml person add "Proof Person"
    # write 10485761 zero bytes to huge.bin under the contacts repo
    clawdex --config /tmp/clawdex-f004-proof/config.toml person avatar set "Proof Person" huge.bin
    clawdex --config /tmp/clawdex-f004-proof/config.toml --dry-run person avatar set "Proof Person" huge.bin
    clawdex --config /tmp/clawdex-f004-proof/config.toml person avatar set "Proof Person" tiny.png
  • Evidence after fix: terminal output from the patched binary:

    $ clawdex person avatar set "Proof Person" huge.bin
    file too large: 10485761 bytes (max 10485760)
    
    $ clawdex --dry-run person avatar set "Proof Person" huge.bin
    file too large: 10485761 bytes (max 10485760)
    
    $ clawdex person avatar set "Proof Person" tiny.png
    {
      "path": "avatars/avatar.png",
      "source": "manual",
      "mime": "image/png",
      "width": 1,
      "height": 1
    }
  • Observed result after fix: Oversized sources return file too large and exit 1. A valid small PNG still writes avatars/avatar.png.

  • What was not tested: Apple Contacts thumbnail import of a source larger than 10 MiB (thumbnails are small). Windows ReadPath.

ReadPath used unbounded io.ReadAll, so
`clawdex person avatar set PERSON ~/huge.bin` could exhaust memory
before image decode. Cap user-selected reads at 10 MiB, the same
limit as Google import avatars, and reject oversize sources with a
clear error.

Stored avatar inspect uses the same ceiling. Rooted ReadFile stays
uncapped for vcard and other repo files.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@clawsweeper

clawsweeper Bot commented Sep 2, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Sep 2, 2026
@clawsweeper

clawsweeper Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex review: blocked before merge. Reviewed September 4, 2026, 4:56 AM ET / 08:56 UTC.

ClawSweeper review

What this changes

The PR limits manual and stored avatar reads to 10 MiB, adds boundary tests, and documents oversized-source rejection.

Regression provenance

Possible regression — suspected (reviewed change). No predecessor PR is attributed.

Merge readiness

Blocked before merge - 3 items remain

Current main still needs the read limit, but the previously reported Doctor upgrade regression remains on the unchanged PR head.

Priority: P2
Reviewed head: 4140b110ba9f040c0638a17ebe2b72c4b68593dd

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) Direct CLI evidence supports the useful fix, but the persistent-metadata regression prevents merge.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (terminal): The captured macOS CLI transcript exercises manual set and dry-run through the changed ReadPath owner, showing oversized rejection and successful small-PNG storage; legacy Doctor upgrade behavior remains a separate correctness blocker.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): The captured macOS CLI transcript exercises manual set and dry-run through the changed ReadPath owner, showing oversized rejection and successful small-PNG storage; legacy Doctor upgrade behavior remains a separate correctness blocker.
Evidence reviewed 10 items Introduced trigger: The complete pinned merge-base-to-head delta changes stored-avatar inspection from ReadFile to ReadFileMax. The new reader checks file size and limits streamed reads to the ceiling plus one byte.
Current main still lacks the cap: Current main's ReadPath delegates to ReadFile, which calls unbounded io.ReadAll. The existing Google download limit does not cover manual files.
Persistent metadata loss: RepairAvatarMetadata handles every inspection error by clearing the avatar and writing person.md. The newly introduced ErrTooLarge therefore removes metadata for an existing oversized file, although its bytes remain.
Findings 1 actionable finding [P1] Preserve legacy avatar metadata during Doctor repair
Security None None.

How this fits together

Clawdex stores contact avatars beside Markdown records containing their metadata. Manual avatar commands read image files, while Doctor inspects stored images and repairs the corresponding records.

flowchart TD
  A[Manual image selection] --> C[Safe file reader]
  B[Stored avatar checked by Doctor] --> C
  C --> D{Within size limit?}
  D -->|Yes| E[Inspect image metadata]
  D -->|No| F[File too large error]
  E --> G[Contact Markdown record]
  F --> H[Doctor repair error handling]
  H --> G
Loading

Before merge

  • Preserve legacy avatar metadata during Doctor repair (P1) - For an existing avatar larger than 10 MiB, this new capped read returns ErrTooLarge. doctor --repair treats that as a validation problem, and Store.RepairAvatarMetadata handles the error by clearing the avatar and writing person.md. This removes the reference and manual-source protection despite the file still existing. Handle the size-limit error without modifying the record and add an oversized legacy-avatar regression. This is the unresolved finding from the previous review.
  • Resolve merge risk (P1) - After upgrading, doctor --repair can discard persisted metadata and manual-avatar protection for files above 10 MiB; the supplied CLI run does not establish preservation of existing records.
  • Complete next step (P2) - Preserve oversized stored-avatar metadata during Doctor repair, add regression coverage, and verify preservation on an existing repository.

Findings

  • [P1] Preserve legacy avatar metadata during Doctor repair — internal/avatar/avatar.go:202-204
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Net code growth Production +37 lines; tests +59 lines; docs +2 lines The added production code implements size checks and bounded reads, with focused boundary tests.

Merge-risk options

Maintainer options:

  1. Preserve metadata on size-limit errors (recommended)
    Handle ErrTooLarge non-destructively in Doctor repair and verify existing oversized avatars retain their metadata and bytes.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Preserve existing avatar metadata when inspection returns safefile.ErrTooLarge; retain bounded reads and existing missing-file handling, and add store and Doctor regression coverage for oversized legacy avatars.

Technical review

Best possible solution:

Keep reads bounded while reporting oversized stored avatars without clearing their metadata, supported by upgrade-preservation coverage.

Do we have a high-confidence way to reproduce the issue?

Yes, from source: manual reads on current main are unbounded, and this head makes a pre-existing avatar above 10 MiB reach Doctor's metadata-clearing branch. No reviewer-side runtime reproduction was executed.

Is this the best way to solve the issue?

Partly: the bounded reader fits the memory problem, but applying it to stored avatars requires distinguishing size rejection from errors that justify clearing metadata.

Full review comments:

  • [P1] Preserve legacy avatar metadata during Doctor repair — internal/avatar/avatar.go:202-204
    For an existing avatar larger than 10 MiB, this new capped read returns ErrTooLarge. doctor --repair treats that as a validation problem, and Store.RepairAvatarMetadata handles the error by clearing the avatar and writing person.md. This removes the reference and manual-source protection despite the file still existing. Handle the size-limit error without modifying the record and add an oversized legacy-avatar regression. This is the unresolved finding from the previous review.
    Confidence: 0.99

Overall correctness: patch is incorrect
Overall confidence: 0.99

AGENTS.md: not found in the target repository.

Codex review notes: model internal, reasoning high; reviewed against baa945d86da0.

Labels

Label justifications:

  • P2: This addresses a bounded local avatar workflow rather than an established widespread runtime outage.
  • merge-risk: 🚨 compatibility: The new stored-file ceiling causes Doctor to erase metadata for avatars accepted by earlier versions.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The captured macOS CLI transcript exercises manual set and dry-run through the changed ReadPath owner, showing oversized rejection and successful small-PNG storage; legacy Doctor upgrade behavior remains a separate correctness blocker.
  • proof: sufficient: Contributor real behavior proof is sufficient. The captured macOS CLI transcript exercises manual set and dry-run through the changed ReadPath owner, showing oversized rejection and successful small-PNG storage; legacy Doctor upgrade behavior remains a separate correctness blocker.

Evidence

Acceptance criteria:

  • [P1] go test -count=1 ./internal/avatar ./internal/safefile ./internal/index ./internal/cli.
  • [P1] go test -count=1 ./...
  • [P1] go test -count=1 -race ./...
  • [P1] go vet ./...

What I checked:

  • Introduced trigger: The complete pinned merge-base-to-head delta changes stored-avatar inspection from ReadFile to ReadFileMax. The new reader checks file size and limits streamed reads to the ceiling plus one byte. (internal/avatar/avatar.go:202, 4140b110ba9f)
  • Current main still lacks the cap: Current main's ReadPath delegates to ReadFile, which calls unbounded io.ReadAll. The existing Google download limit does not cover manual files. (internal/safefile/safefile.go:78, baa945d86da0)
  • Persistent metadata loss: RepairAvatarMetadata handles every inspection error by clearing the avatar and writing person.md. The newly introduced ErrTooLarge therefore removes metadata for an existing oversized file, although its bytes remain. (internal/index/avatar.go:40, 4140b110ba9f)
  • Reachable Doctor path: Doctor invokes RepairAvatarMetadata whenever avatar validation reports a problem and --repair is active without --dry-run. An oversized stored avatar now satisfies that condition. (internal/cli/cli.go:805, 4140b110ba9f)
  • Existing repair contract: Doctor documentation distinguishes missing files, whose metadata is dropped, from present files, whose metadata is recomputed. The new size rejection is neither file disappearance nor permission to discard the reference. (docs/doctor.md:57, 4140b110ba9f)
  • Real CLI proof: The complete captured PR body, context sourceRevision 6b5f8f4b372417a3bc39bbed3ef155d2353986d3b61cd273ae916e2e234104c2, reports a branch-built CLI on macOS arm64 rejecting a 10,485,761-byte source in normal and dry-run commands, while successfully storing a small PNG. This exercises ReadPath through the actual CLI; it does not exercise legacy stored-avatar repair. (4140b110ba9f)

Likely related people:

  • Peter Steinberger: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Preserve metadata on ErrTooLarge and add store/Doctor regression coverage.
  • Record an upgrade check showing an existing oversized avatar retains its metadata and file after Doctor repair.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (4 earlier review cycles)
  • reviewed 2026-09-02T20:41:57.529Z sha 4140b11 :: needs changes before merge. :: [P1] Preserve legacy avatar metadata during Doctor repair
  • reviewed 2026-09-03T01:17:12.157Z sha 4140b11 :: blocked before merge. :: [P1] Preserve legacy avatar metadata during Doctor repair
  • reviewed 2026-09-03T11:57:11.505Z sha 4140b11 :: blocked before merge. :: [P1] Preserve legacy avatar metadata during Doctor repair
  • reviewed 2026-09-04T00:27:00.314Z sha 4140b11 :: blocked before merge. :: [P1] Preserve legacy avatar metadata during Doctor repair

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant