fix: validate file type before previewing avatar upload#370
fix: validate file type before previewing avatar upload#370thisismyurl wants to merge 4 commits into
Conversation
Add accept="image/*" to the file input so the OS file picker filters to image files by default. Add a client-side MIME type check in the change handler so non-image files selected via drag-and-drop or by clearing the type filter are silently rejected and the existing avatar preview is preserved. Fixes 10up#233
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds client-side guardrails to reduce non-image avatar uploads and improve the file chooser UX.
Changes:
- Restricts the profile avatar file input to images via
accept="image/*". - Adds a JS MIME-type check to reset the preview if the selected file is not an image.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| includes/class-simple-local-avatars.php | Limits the avatar <input type="file"> chooser to image types. |
| assets/js/simple-local-avatars.js | Prevents non-image selections from updating the avatar preview. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Addresses @thrijith's review on 10up#370: - Replace the `file.type &&` short-circuit with an allowlist check, so an empty or unknown `file.type` (e.g. a renamed binary) is rejected instead of passed to URL.createObjectURL(). - Mirror the server's accepted set (jpeg/gif/png, from the `mimes` array on media_handle_upload()) in both the JS guard and the input `accept` attribute, so the client never previews a type the server rejects on submit (svg/webp previously slipped through `image/*`). - Surface a visible inline rejection notice and announce it to assistive technology via wp.a11y.speak() (add `wp-a11y` as a script dependency). - Add Cypress coverage for the non-image and empty-type rejection paths plus the valid-image happy path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks @thrijith — all three addressed in the latest push. 1. Empty / unknown MIME no longer slips through. The old const avatar_allowed_types = ['image/jpeg', 'image/gif', 'image/png'];
// indexOf('') === -1, so empty/unknown types are rejected, not previewed.
if (-1 === avatar_allowed_types.indexOf(file.type)) { ... }I went with an explicit allowlist rather than your suggested 2. Client now mirrors the server's accepted set. The server only accepts jpeg/gif/png (the 3. Rejections are surfaced, not silent. On reject the input now shows a visible inline notice ( Added One note on verification: I ran (full disclosure: AI helped me identify the issue and verify my work) |
|
Hi @thisismyurl Thanks a lot for the updates, code looks good to me.
The tests seem to be failing because it is logging in as admin who won't see the file input control, can you set up a user with subscriber role in tests see if that helps? |
|
Done, thanks for the review |
…t renders Admins get the media-library uploader; #simple-local-avatar only renders for users without the upload_files capability. Creates the subscriber in the wp-env initialize step. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The deprecated cypress-file-upload attachFile does not reliably trigger the input change handler on CI (Electron 118), so the MIME guard never runs and the reject cases leave the input value populated. Switch to the native cy.selectFile, which dispatches real input/change events. The valid-image case uses an inline PNG buffer to avoid project-root path resolution ambiguity with --config-file.
|
Passing to @peterwilsoncc for final review the last failing test is unrelated to the changes done here, please let me know if that should handled in this PR, thanks! |
Summary
The local-file avatar input accepted any file type — a user could select a PDF, video, or binary file and
URL.createObjectURL()would attempt to render it as a preview image. Two changes close this gap:class-simple-local-avatars.php): Addaccept="image/*"to the<input type="file">. This tells the OS file picker to default to image files and filters non-image files in supporting browsers.assets/js/simple-local-avatars.js): Add a MIME type guard in thechangehandler. If the selected file's reportedtypedoes not start withimage/, the input is cleared and the existing avatar preview is restored. The guard is skipped for browsers that don't populatefile.type(older IE) so behaviour is unchanged in those environments.Changes
includes/class-simple-local-avatars.phpassets/js/simple-local-avatars.jsTesting
.pdfor.txt).Changelog
accept="image/*"attribute to avatar file input for better OS-level file filteringCredits
@thisismyurl
Fixes #233