CVE-2026-59992: Tina: Broken Access Control: arbitrary bucket-key write/delete in `next-tinacms-s3` (and sibling production media adapters)
The production media handler shipped by next-tinacms-s3 (createMediaHandler in packages/next-tinacms-s3/src/handlers.ts) accepts an attacker-chosen ?key= query parameter and returns an AWS-signed PutObject URL whose Key is that value, with no check that the key falls under the operator’s configured mediaRoot. The same handler’s DELETE branch reads objectKey = (req.query.media as string[])[1] and dispatches a DeleteObjectCommand for that exact key, again unbounded by mediaRoot. Any caller that passes the operator-supplied authorized() predicate — i.e. any logged-in CMS editor in a typical TinaCloud / self-hosted deployment — therefore has write and delete authority over the entire S3 bucket the IAM key can reach, even though the package documents mediaRoot as the place where editors are scoped. The same shape is present in next-tinacms-dos, next-tinacms-azure, and next-tinacms-cloudinary, so a single design mistake spans every first-party production media backend.
- Project: TinaCMS — first-party production media adapters (consumed by self-hosted Next.js sites and TinaCloud-backed deployments).
- Source reviewed:
tinacms/tinacms@main(b56dad4). - Deployed artefact validated:
next-tinacms-s3@21.0.3handler logic, exercised against@aws-sdk/client-s3@3.665.xviaaws-sdk-client-mock@4.1.0(the AWS SDK signs the URL identically whether the bucket is real or mocked). - Affected file(s):
packages/next-tinacms-s3/src/handlers.ts:67-90—GET ?key=returns presignedPutObjectCommandURL with attacker-chosenKey.packages/next-tinacms-s3/src/handlers.ts:199-223—DELETEreads[, objectKey] = mediaand issuesDeleteObjectCommandagainst attacker-chosenKey.packages/next-tinacms-dos/src/handlers.ts:79-152and:249-278— same write/delete pattern, plus a server-side upload that builds the key withpath.join(mediaRoot, prefix + filename)over attacker-controlleddirectoryandfilename.packages/next-tinacms-azure/src/handlers.ts:44-95—uploadMediawritespath.join(directory, filename)with both fields attacker-controlled (nomediaRootconfigured at all);deleteAssetdeletes any blob in the container.packages/next-tinacms-cloudinary/src/handlers.ts:193-204—cloudinary.uploader.destroy(public_id)over attacker-chosenpublic_id.- CWE: CWE-639 — Authorization Bypass Through User-Controlled Key. Adjacent: CWE-284 (Improper Access Control), CWE-862 (Missing Authorization on the per-key authority check).
- OWASP 2021: A01:2021 — Broken Access Control (the operator’s intended
mediaRootboundary is enforced only on listing, not on writes or deletes). Secondary: A04:2021 — Insecure Design (every adapter independently re-implements the same broken pattern).
References
- github.com/advisories/GHSA-8mq9-5fw2-5rm4
- github.com/tinacms/tinacms/commit/d44558e9b4502d4f4fc2c970d22985339fe2b6ce
- github.com/tinacms/tinacms/pull/7088
- github.com/tinacms/tinacms/releases/tag/next-tinacms-s3@23.0.4
- github.com/tinacms/tinacms/security/advisories/GHSA-8mq9-5fw2-5rm4
- nvd.nist.gov/vuln/detail/CVE-2026-59992
Code Behaviors & Features
Detect and mitigate CVE-2026-59992 with GitLab Dependency Scanning
Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →