Atlas / MCP servers / jonradoff / LightCMS

LightCMSCAUTION

mcp/jonradoff/lightcms

Self-hosted CMS that works human or headless: full admin UI plus REST and MCP APIs, built-in semantic search and site chat, and content forking, versioning, diff/merge review, templates, approvals, and static page generation.

Verdict
CAUTION
Grade
C
Trust score
75 /100
Exposed tools
—
Transport
stdio · streamable-http
License
MIT
Stars
31
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://github.com/jonradoff/lightcms/actions/workflows/ci.yml) [](https://codecov.io/gh/jonradoff/lightcms) [](https://goreportcard.com/report/github.com/jonradoff/lightcms) [](https://glama.ai/mcp/servers/jonradoff/lightcms)

LightCMS is a Go-powered content management system built for the AI era. It's simultaneously AI-native (semantic search, built-in Claude-powered chat widget, MCP server for agent control), agentically controllable (Claude Code and any MCP client can read, write, publish, and bulk-import content via 130 MCP tools), and agentically updatable (the codebase is clean, well-structured Go — coding agents can safely extend it). For teams that want a CMS that works with AI rather than around it.

What's New in v7.3 — SEO & AI

Read from source at commit df62bd4fa0a2OBSERVED · 2026-10-08
02

Trust audit

CAUTIONgrade C · trust 75/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (1 observation(s))
Network
declared (6 observation(s))
Shell
none-observed
Dependencies
pinned
Secrets in source
found

Findings (22)

MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
internal/handlers/hardening_742_test.go:303
const token = "cf-secret-token-0123456789"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
internal/services/aicrawlers.go:50
{Token: "cohere-training-data-crawler", Vendor: "Cohere", Purpose: CrawlerPurposeTraining, UAMatch: "cohere-training-data-crawler"},
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
internal/services/aicrawlers.go:63
{Token: "Meta-ExternalFetcher", Vendor: "Meta", Purpose: CrawlerPurposeUserFetch, UAMatch: "meta-externalfetcher"},
LOWInventory / provenance · inv.hidden_file · CWE-1104
.goreleaser.yaml
.goreleaser.yaml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
internal/handlers/admin_authz_fork_guard_test.go:256
src, err := os.ReadFile("../../cmd/server/main.go")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
internal/handlers/admin_routes_guard_test.go:136
src, err := os.ReadFile("../../cmd/server/main.go")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
internal/middleware/security_test.go:265
{"directory traversal", "../../../etc/passwd"},
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
internal/middleware/security_test.go:266
{"embedded traversal", "/images/../../secret"},
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
internal/services/asset_test.go:87
_, err := svc.UploadAsset(ctx, pngData, "test.png", "/../../../etc/test.png", "")
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
internal/handlers/hardening_742_test.go:341
Data: map[string]interface{}{"body": `<a href="` + internal.URL + `/admin">a</a> <a href="http://169.254.169.254/latest/meta-data/">b</a>`}})
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
internal/handlers/hardening_742_test.go:365
if !strings.Contains(body, internal.URL+"/admin") || !strings.Contains(body, "169.254.169.254") || !strings.Contains(body, `"totalBrokenLinks": 2`) {
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
internal/handlers/hardening_742_test.go:341
Data: map[string]interface{}{"body": `<a href="` + internal.URL + `/admin">a</a> <a href="http://169.254.169.254/latest/meta-data/">b</a>`}})
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
internal/services/importer/importer_test.go:180
if _, err := ParseFeed(context.Background(), "http://127.0.0.1:0/nope"); err == nil {
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
internal/services/services_deep_test.go:141
if _, err := ws.Create(ctx, "hook", "https://127.0.0.1:0/unreachable", "secret", []string{"content.published"}, true); err != nil {
LOWPrompt injection · prompt.authority_framing · CWE-94, CWE-1427
CHANGELOG.md:855
- Keys created before v2.0 remain functional as system-level keys with full access
LOWPrompt injection · prompt.authority_framing · CWE-94, CWE-1427
CLAUDE.md:384
- **admin**: Full access — manage users, templates, settings, audit logs, all API keys
LOWPrompt injection · prompt.authority_framing · CWE-94, CWE-1427
README.md:810
| **admin** | Full access: manage users, templates, theme, settings, audit log, all API keys |
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:20
- **`Strict-Transport-Security` follows server configuration** (secure cookies and an `https://` base URL) instead of the `X-Forwarded-Proto` request header, which any client can send.
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:58
- **Admin forms work over plain HTTP in local development.** With `secure_cookies: false`, every admin POST on `http://localhost` failed with "Invalid or missing CSRF token" because the CSRF library a
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:329
- **Agent governance**: API keys accept a `scopes` permission allowlist and a `sandbox_only` flag (server-enforced fork-only writes). Every MCP session gets an agent-session ID; `GET /api/v1/agent-ses
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
README.md:205
5. Visit http://localhost:8082/cm and log in with your email and password
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWInventory / provenance · mcp.no_tools_extracted · CWE-1104
server.json
Why it matters. the tool list is enumerated at runtime by tools/list, not declared in source
Fix. the page says so rather than showing an empty table

Gates applied: no_behavioural_pass.

Audited 2026-10-08 · audit v0.4.1 · source sha df62bd4fa0a2full audit observations/trust-audit/mcp-server/jonradoff__lightcms.json · Report an issue / request a re-scan
03

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-08df62bd4fa0a2CAUTIONC75first audit
04

Questions

What is the LightCMS MCP server?

Self-hosted CMS that works human or headless: full admin UI plus REST and MCP APIs, built-in semantic search and site chat, and content forking, versioning, diff/merge review, templates, approvals, and static page generation.

Is LightCMS safe to connect to an agent?

With care. The audit graded it C (75/100) and found 22 things worth knowing before you trust this server, listed below with the exact line each was found on.

What credentials does LightCMS need?

It reads LIGHTCMS_API_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does LightCMS run?

It speaks stdio and streamable-http, so it runs as a local process your client starts.

How current is this page?

The grade is for one exact copy of the source (df62bd4fa0a2), read on 2026-10-08. The repository is watched and re-audited when it changes.

Advertisement