| name | theme-blog_cms |
| description | Blog / CMS application palette: variants, pages, entities, and flows for building a varied content app. Use when theme_preset is blog_cms.
|
Blog / CMS theme
Domain
Apps that author, publish, and display content with comments and media. The
rich-text rendering, file/media handling, and draft/published ownership are
where injection and access exploits land.
Application variants — pick ONE per lab
Honor any hint in theme_free_text / custom_prompt; otherwise pick one.
- Personal blog — one author, posts, comments, tags.
- Multi-author magazine — editors & writers, sections, editorial workflow.
- Docs / wiki — hierarchical pages, revisions, search.
- Newsletter platform — issues, subscribers, send/schedule.
- Headless CMS admin — content types, entries, media library, API output.
- Recipe site — recipes, ingredients, steps, ratings, saved cookbooks.
- Photography / portfolio — galleries, projects, client proofing, downloads.
Roles — choose the set that fits the variant
- anon — read published content, search, comment (maybe).
- user (reader/commenter) — comment, profile.
- author/editor — create/edit own (or all) posts, upload media.
- admin — manage users, all content, settings.
Most exploits run as author or user.
Candidate pages — select a coherent subset
Size the subset to endpoint_count. Candidates: public home/feed, post/article
detail, category/tag listing, search, comments, author profile, author
dashboard, post editor, media library, drafts, revision history & page tree
(wiki), section/editorial queue (magazine), issues & subscribers (newsletter),
content types & entries (headless CMS), admin users, admin settings.
Candidate entities (seed tables) — select what the variant needs
- users — id, email, password_hash, role, display_name
- posts — id, author_id, title, body_html, status (draft/published), slug, published_at
- comments — id, post_id, user_id?, author_name, body, status, created_at
- media — id, owner_id, filename, path, mime, size
- categories / tags — id, name, slug
- post_tags — post_id, tag_id (taxonomy join)
- sections (magazine) — id, name, slug, lead_editor_id
- editorial_status (magazine) — id, post_id, state (idea/draft/review/approved/published), assigned_to
- revisions (wiki) — id, page_id, editor_id, body, created_at
- page_tree (wiki) — id, page_id, parent_id, position (hierarchy/ordering)
- issues (newsletter) — id, title, body_html, status, scheduled_at, sent_at
- subscribers (newsletter) — id, email, status, confirmed_at, unsubscribe_token
- content_types (headless CMS) — id, name, slug, field_schema_json
- entries (headless CMS) — id, content_type_id, author_id, data_json, status
Seed multiple authors each with a mix of draft & published content (and ≥5
comments) so cross-author and draft-visibility exploits are possible.
Candidate user flows — select the ones matching chosen pages/features
- Visit home → open a post → read → leave a comment.
- Search / filter by tag or category → open a result.
- (author) Write a post → upload an image → publish.
- (author) Edit a draft → preview → publish.
- (admin) Moderate comments → approve/reject → manage users.
- (magazine) Move a post through the editorial queue (draft → review → approved → published).
- (wiki) Edit a page → view revision history → revert to an earlier revision.
- (wiki) Create a child page under a parent → reorder the page tree.
- (newsletter) Compose an issue → schedule/send to subscribers; a reader subscribes/unsubscribes.
- (headless CMS) Define a content type → create an entry → publish it for API output.
Candidate endpoints — a feature may span several
Endpoints are a shared surface, not owned 1:1 by a feature (a single feature
often spans several, and an endpoint can back multiple features). Pick a coherent
subset alongside the pages above. Grouped by area:
- posts —
GET /api/posts, GET /api/posts/{slug}, POST /api/posts, PUT/DELETE /api/posts/{id}
- drafts —
GET /api/posts/{id} (draft, owner-only), POST /api/posts/{id}/publish
- comments —
GET/POST /api/posts/{id}/comments, DELETE /api/comments/{id}
- media / import —
POST /api/media, GET /api/media/{id}, POST /api/import?url= (server fetches a URL)
- taxonomy / search —
GET /api/categories, GET /api/tags, GET /api/search?q=
- editorial (magazine) —
GET /api/sections, POST /api/posts/{id}/transition
- revisions (wiki) —
GET /api/pages/{id}/revisions, POST /api/pages/{id}/revert, GET/POST /api/pages (tree)
- newsletter (newsletter) —
GET/POST /api/issues, POST /api/issues/{id}/send, POST /api/subscribers, GET /api/unsubscribe?token=
- content types / entries (headless CMS) —
GET/POST /api/content-types, GET/POST /api/entries, GET /api/{type}/{id} (API output)
- admin —
/api/admin/users, /api/admin/comments, /api/admin/settings
Where vulnerabilities fit naturally
- xss → comment body and post body_html rendered without sanitization (stored XSS is the canonical blog vuln).
- file_upload → media library accepting an executable/script disguised as an image.
- ssrf → link-preview / "import from URL" / avatar-by-URL fetching an internal address.
- idor → read/edit another author's draft (
/api/posts/{id} while unpublished); view another's subscribers/entries.
- business_logic → publish without review in an editorial-workflow variant; comment as another user; revert another's revision.
- sqli → search query or tag filter parameter.
Diversity guidance
Pick ONE variant and a coherent subset — a wiki and a newsletter platform
diverge sharply. Size to endpoint_count; let theme_free_text /
custom_prompt bias the variant and naming. Vary content types, author counts,
and taxonomy so two CMS labs feel like different sites.