Radek Krejci

AI and security

I wanted to use AI to manage real content without opening the database to it or handing it an unrestricted administrator account. I therefore integrated AI into LydiaCMS as a dedicated user: it accesses the system through MCP, may perform only permitted operations, and every change goes through the same authorization and audit process as a human action.

Why AI does not access the database directly

Direct database access would be simple, but it would bypass validation, permissions and auditing in the application layer. AI could write technically valid data that violates system rules or modify a record without sufficient information about who made the change and why.

An unrestricted administrator account would preserve the application layer but provide unnecessarily broad permissions. I therefore chose a dedicated service user for whom I can allow only the operations required for each use case.

How I use MCP

I also edit this website in this way: I change page copy and SEO properties, upload images or prepare translations. Instead of manually navigating forms, I can enter a task in a conversation and inspect the specific result before or after saving it.

MCP tools are generated from registered administration API endpoints. Their names reflect the operation, for example core_pages_update or core_translations_set. Other packages can add their own tools in the same way.

The source code for the HTTP interface is available in the lydiacms-api repository.

MCP is not the security boundary

MCP is a way to expose specific operations to AI, not a security boundary. In LydiaCMS, that boundary consists of the user identity, their permissions, ACL checks, validation in the application layer and the audit trail.

The same tool can therefore produce a different result for two users: an operation is performed only if the specific user is permitted to apply it to the given record.

What happens during a call

  1. ChatGPT, Codex or another MCP client selects a tool and prepares its input data.
  2. The MCP server determines the user under whom the request will be executed. For remote HTTP access, the user is identified by a Bearer token.
  3. The token limits the available permissions, and every operation also passes the same ACL check as the administration.
  4. A successful change is saved through the standard application layer and recorded in the audit log with its original and new value.

Limiting permissions

For AI, I use a dedicated user to whom I assign only the permissions required for a specific task. This user cannot manage users or roles. A system rule also ensures that a user cannot grant more permissions than they have themselves. I describe the context tree and rule inheritance in the Architecture section.

For remote access over HTTP, the Bearer token is tied to a specific user and a set of permitted permissions. The server rejects requests without a valid token. The remote MCP endpoint must also be explicitly enabled.

Auditing and reverting changes

For content records, the audit stores the original and new value. In the administration, I can therefore see who made a change and which fields they edited. I can revert a selected change; the revert itself is recorded as another audit event.

Changes window in the LydiaCMS audit log showing a page-title difference and a Revert this change button
The audit log shows the difference between values and offers the option to revert a supported change.

A change can be reverted only if the affected fields have not changed again since the original change. If there is a conflict, the system rejects the operation to avoid overwriting newer work. This feature is intended for supported content records; I do not offer it for users and roles.

Filtering HTML content

Text received through MCP goes through the same processing as content saved from the administration. HTMLPurifier keeps only permitted tags and attributes and removes scripts or disallowed attributes. It is not general protection against every type of attack, but an additional layer for HTML content fields.

One protocol, two transports

  • Local STDIO in lydiacms/core. The MCP client starts the lydiacms:mcp command through Docker, CLI or SSH. No public HTTP endpoint is required.
  • Streamable HTTP in lydiacms/api. The same tools can be exposed at /api/mcp, with requests authenticated using a Bearer token.

The cost of the chosen approach

Controlled access through MCP is safer than writing directly to the database, but it requires additional work and continuous oversight.

  • I must design each new operation securely, assign permissions to it and maintain its implementation.
  • A compromised token allows the assigned permissions to be used until the token is revoked.
  • Auditing and reverting cover supported content records, not every type of data and operation.
  • I still review the AI's output; automation does not replace responsibility for the saved change.

The result is not a special security mode for AI. AI uses the same application layer as a human user, while auditing and reverting remain safeguards rather than substitutes for authorization.

← LydiaCMS

Contact

Looking to strengthen your PHP team?

If you're working on a new backend project, an integration, or need help developing an existing system, get in touch.