Conversation
## Summary Adds Playwright integration tests for #6646's three acceptance criteria at the HTTP boundary: 1. Path-traversal rejection on GraphQL mutations and `/media` routes 2. `/media` upload → list → delete round-trip 3. Concurrent mutation consistency under contention All tests run against the real TinaCMS dev server via the existing `api` Playwright project — no mocks, no stubs. **Closes #6646 — part of epic #6464.** ## At a glance | | | |---|---| | New tests | 23 | | New files | 5 | | Modified files | 7 | | Files deleted | 1 | | Local run (all platforms) | 37 passed · 1 fixme | | CI runtime | ~12s | ## Tests added ### `tests/api/security.spec.ts` — 21 tests (20 passing + 1 fixme) Every vector runs against all three GraphQL mutations (create/update/delete) and the three `/media` routes (upload/list/delete), except `backslash traversal` which is `graphqlOnly` (its media-side behaviour depends on Win32 path semantics). Each rejection must: 1. Error on the wire (GraphQL `errors` or HTTP 4xx/5xx) 2. Not leak server-side filesystem paths in the response 3. Not have written a file — `assertNoEscapeWrite` guards plausible landing targets | Vector | createDocument | updateDocument | deleteDocument | media upload | media list | media delete | |---|:-:|:-:|:-:|:-:|:-:|:-:| | relative `../` traversal | ✅ | ✅ | ✅ | 403 | 403 | 403 | | URL-encoded traversal | ✅ | ✅ | ✅ | 403 | 403 | 403 | | null byte | ✅ | ✅ | ✅ | 500 | 200 no-op | 🟡 fixme | | backslash traversal | ✅ | ✅ | ✅ | — | — | — | 🟡 `test.fixme` — one combination marked as expected-fail pending a follow-up change. A finding reported privately to the TinaCMS team per [SECURITY.md](../SECURITY.md); details intentionally omitted here. `—` backslash × media is skipped entirely — `\` is only a path separator on Win32, so media tests would be platform-specific. GraphQL tests for backslash run on every platform via the character-allowlist regex. ### `tests/api/media.spec.ts` — 1 test | Test | Covers | |---|---| | `media — upload → list → delete round-trip` | AC2 lifecycle chained in one test; each phase verifies the previous phase's side effect | ### `tests/api/concurrency.spec.ts` — 1 test | Test | Covers | |---|---| | `concurrent updates on the same document all resolve without data loss` | 8 parallel `updateDocument` calls on the same doc. Asserts (1) all resolve without errors, (2) final read matches one of the sent titles, (3) the `title` index has exactly one edge across all 8 titles — catches stale-index regressions an `eq: finalTitle` query would miss. Directly satisfies the AC's "concurrent mutation test demonstrates correct locking behaviour". | ## Supporting changes | File | | Purpose | |---|:-:|---| | `playwright/tina-playwright/utils/graphql.ts` | 🆕 | Mutation strings + helpers + `CollectionName` union | | `playwright/tina-playwright/utils/media.ts` | 🆕 | `uploadMedia` / `listMedia` / `deleteMedia` / `encodeMediaPath` | | `playwright/tina-playwright/utils/deleteDocument.ts` | 🗑️ | Subsumed by `utils/graphql.ts` | | `playwright/tina-playwright/fixtures/test-content.ts` | ✏️ | `mediaCleanup` fixture; both cleanups check-before-delete | | `playwright/tina-playwright/fixtures/api-context.ts` | ✏️ | Removed hard-coded `Content-Type` (was clobbering multipart boundaries) | | `playwright/tina-playwright/tina/config.js` | ✏️ | Added `media.tina` config — uploads were 500'ing without it | | `playwright/tina-playwright/tests/api/pagination.spec.ts` | ✏️ | Filter queries to seed titles — fixes pre-existing flakiness exposed by any parallel content-creating test | | `playwright/tina-playwright/.gitignore` | ✏️ | Defensive rule — transient `playwright-*` artefacts in `content/*/` and `public/uploads/` can't be accidentally staged if a test process is killed mid-run | | `playwright/tina-playwright/README.md` | ✏️ | New `Projects` / `API test suite` / `Shared infrastructure` sections | | `AGENTS.md` (repo root) | ✏️ | New `Security & Disclosure` section so future AI agents automatically adhere to SECURITY.md |
…om MediaStore (#6682) ## Summary - Fixes a crash (React Error #31: "Objects are not valid as React children") when inserting an image from the Media Library into an image field or MDX rich-text editor, when using a custom `MediaStore` that doesn't implement a `parse()` method (e.g., `GitHubMediaStore` for self-hosted setups) - The image field plugin's `onChange` fallback now extracts `media.src` instead of passing the full Media object as the field value - The MDX image toolbar button now normalizes `media.src` via `parse()` or falls back to `media.src` before calling `insertImg()` ## Root Cause The `parse()` method is **not part of the `MediaStore` interface** (`packages/tinacms/src/toolkit/core/media.ts:65-100`), so custom stores don't implement it. When `cms.media.store.parse` is `undefined`, the fallback in `image-field-plugin.tsx` was passing the entire `Media` object `{id, src, filename, directory, type, thumbnails}` as the field value. React then tried to render this object as a child, causing Error #31. ## Test plan - [x] Unit tests added covering both buggy (regression) and fixed code paths (12 vitest tests) - [x] Integration test script verifying all scenarios (16 assertions) - [x] Manual browser test: unpatched = white screen crash, patched = image inserts correctly - [ ] Verify existing tests still pass (`pnpm test` in `packages/tinacms`) - [ ] Test with default `TinaMediaStore` (should work as before since `parse()` is still called when available) Closes #6679 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )