duncanmcclean/guest-entries
Statamic addon that lets anonymous visitors submit guest entries to your collections from the front end, with no user account required. Configure which collections accept submissions, apply validation rules, and protect forms from spam.
Upgrade first. v5.2.1 is a security-hardening release (upload handling, entry lookups, asset paths, unvalidated form params, invalid input, reserved fields, SVG sanitization). If you are on any 5.x version, pin ^5.2.1 before doing anything else — several of these fixes close paths that are reachable from ordinary public endpoints, not exotic edge cases.
Minimal setup:
composer require <vendor>/<package>^5.2.1 and confirm composer.lock resolves to 5.2.1 or later.php artisan vendor:publish --tag=...), then read the config file top to bottom — it is the fastest map of what the package actually exposes (route prefix, middleware, allowed models/collections, upload disk, validation toggle).auth/sanctum. The reserved-field fix in #125 only matters if guests can hit write endpoints, so nail this down before writing tests.php artisan route:list --path=<prefix>) to see the actual surface: index/show/store/update/destroy for entries, plus whatever asset upload/destroy endpoints exist.First use case: wire a single read endpoint (list entries for a collection/model) and assert it returns what you expect. Then do a single write — POST an asset upload and a PATCH on an entry — because that is where every fix in this release lives. Doing write paths early surfaces middleware, disk, and validation assumptions before they are buried under feature work.
Where to look first when something misbehaves: the package's request/form-request classes (they encode the lookup and validation rules), then the config, then your route middleware.
Treat the package as a thin transport layer, not your domain layer. Keep authorization, business rules, and derived-field computation in your own policies/actions and let the package handle request parsing and persistence. This matters more after 5.2.1, because the package now enforces its own guards (reserved fields, path handling) and you do not want two competing sources of truth.
Entry lookups in update/destroy. #120 hardens how the target entry is resolved. In practice: always address entries by a stable identifier your routes already constrain (ID or slug with an explicit route constraint), and add a feature test that hits PUT/DELETE with a bogus ID and with a foreign/unauthorized ID, asserting 404 and 403 respectively rather than a 500. If you have custom route-model binding or a repository override, re-verify it still works — hardened lookups are the classic place where an overridden find starts returning null where it used to throw.
Asset uploads and existing paths. #121 and #122 harden uploads and the handling of pre-existing asset paths. Pattern: dedicate a disk (local or S3) to package uploads, set it in config, and never accept a client-supplied absolute path or full URL. If you support "reuse an existing asset" flows, pass a container-relative path resolved through the package's own lookup rather than concatenating strings in your controller. After upgrading, run an integration test that uploads a file whose name collides with an existing asset and confirm the package's overwrite/rename behaviour still matches your expectations.
Validation disabled is a real mode. #123 hardens form parameters when validation is off. If you use that mode (common when a separate form or front-end validator owns the rules), treat every parameter as untrusted: whitelist the keys you forward, cast types explicitly, and never splat the request array into a model. Prefer keeping package validation enabled and extending it with your own rules — you get the hardened path for free.
Reserved entry fields. #125 stops guests setting reserved fields (typically things like id, slug, published, date, author, ownership columns). Pattern: run a guest-reachable write endpoint through a test that attempts to set each reserved field and asserts it is ignored or rejected. For authenticated flows where privileged users should set them, gate that on a policy ability rather than on "is logged in".
SVG sanitization. #126 improves sanitization but is not a licence to skip defence in depth. Serve user-uploaded SVGs from a separate origin or via a Content-Disposition: attachment / Content-Security-Policy wrapper, and disallow image/svg+xml on any disk that is publicly served without that wrapper. Keep a regression fixture set of known-nasty SVGs (script tags, onload, external <use href>, entity tricks) and assert your sanitized output.
Invalid input. #124 hardens rejection of malformed input. Lean into it: let the package return its error responses, and in your test suite assert status codes for malformed payloads, wrong content types, and non-array JSON bodies. If you wrap responses in your own resource classes, make sure you are not accidentally swallowing the package's 4xx into a 500.
visibility/permissions first, then storage/logs/laravel.log, then the package's upload handler. Path-hardening fixes are the usual culprit when a path that "obviously exists" is refused.dependabot/composer outdated noise on. Seven hardening PRs in a patch release signals an active security review; adopt patch releases quickly and read the changelog rather than assuming semver patch = cosmetic.How can I help you explore Laravel packages today?