Security

Lara Dashboard v1.5.0: Claude.ai OAuth MCP and Security Fixes

By Lara Dashboard 20 views
Lara Dashboard v1.5.0: Claude.ai OAuth MCP and Security Fixes
Lara Dashboard v1.5.0 shipped on 4 November 2026. It does two things. It lets Claude.ai and other OAuth-only clients connect to your CMS with nothing but a URL. And it closes a module-install path traversal, on top of the security fixes that landed two days earlier in v1.4.9.
Disclosure: Lara Dashboard is our open-source, MIT-licensed Laravel CMS and admin. This post is our own release write-up. Every claim below comes from the changelog, the MCP docs and the code in the repo.

Quick answer: upgrade now, then decide on OAuth

If you run anything older than v1.5.0, upgrade. The v1.4.9 and v1.5.0 releases fix stored script injection in LaraBuilder content, unsafe social-login account linking, a permission gap on the MCP send-email tool, and a way for a crafted module to write files outside modules/. Those are real fixes, each with a GitHub advisory ID.
OAuth is the new feature, and it is optional. The MCP server is still off by default. If you never turn it on, the OAuth endpoints return 404 and nothing about your site changes. If you do turn it on, Claude.ai custom connectors can now reach your CMS without you pasting a token anywhere.

What changed in v1.4.9 and v1.5.0

Here is the short version of both releases. The changelog has the full wording.
ChangeReleaseWho should care
OAuth 2.1 for the MCP server (PKCE, dynamic client registration, rotating refresh tokens)v1.5.0Anyone who wants Claude.ai or another remote client on their CMS
Module installs can no longer write outside the modules folder (GHSA-75q6-qrv2-96rx)v1.5.0Every site that installs modules by upload or marketplace
Module vendor autoloaders load after core, so bundled framework copies cannot shadow core classesv1.5.0Sites whose migrations failed after installing a module
Retired OpenAI chat models replaced by gpt-6-luna (default) and gpt-6-solv1.5.0Sites using OpenAI for AI content
LaraBuilder content sanitized on save and on load (GHSA-rf5h-55h2-jmf8, GHSA-9gg9-jh9p-fw37)v1.4.9Every site with more than one editor
Social login links accounts only on provider-verified emails; callback rate-limited (GHSA-c5x3-wvxj-7cgr)v1.4.9Sites with Google, GitHub, LinkedIn or X login
MCP send-email requires the email_template.edit permission (GHSA-gjfv-h634-pxpv)v1.4.9Sites that issued MCP tokens to agents
Dependency bumps, including Laravel 13.39 and Livewire 4.4.8v1.4.9Everyone

OAuth removes the token copy-paste step for Claude.ai

Before v1.5.0 there was one way to connect: create an agent token under Settings → MCP → Agent tokens and send it as a bearer header. That still works, and it is still the right choice for Cursor, Claude Code, Claude Desktop and scripts.
The problem is clients that cannot send custom headers. Claude.ai custom connectors are the obvious case. They expect the server to speak OAuth. Now Lara Dashboard does.
The flow, as documented in docs/mcp.md, looks like this:
  1. You add https://your-site.com/mcp as a custom connector in the client.
  2. The client gets a 401 that points it to the protected resource metadata, finds the authorization server and registers itself.
  3. Your browser opens the Lara Dashboard consent screen. You sign in, review the abilities and click Allow.
  4. The client gets a 60-minute access token and a 30-day refresh token, and refreshes on its own.
The connection then shows up in your agent token list as OAuth · <client name>. Revoke it there and the client's next refresh fails. It has to ask you again.
The important design choice: an OAuth access token is a regular MCP agent token. Abilities, permissions and revocation work the same way they already did. There is no second permission system to learn or audit.

The OAuth security model is strict by default

OAuth done loosely is worse than a bearer token. We kept it narrow. These rules come straight from the implementation and docs:
Public clients only, PKCE required. Only the S256 challenge method is accepted. A client that asks for a client secret at registration does not get one; registration returns what was actually registered.
Exact redirect URIs. Redirects must be HTTPS, except http://localhost and loopback addresses for desktop clients, which may use any port.
Single-use, short-lived codes. Authorization codes expire after 10 minutes and work once. Codes and refresh tokens are stored as SHA-256 hashes, not plain text.
Rotation with reuse detection. Refresh tokens rotate on every use. If an old one is replayed, the whole grant for that client and user is revoked.
Permissions are re-checked on every refresh. To approve a client, the user needs the manage settings permission and at least post.view or post.create. Every refresh re-checks this and recalculates abilities from the user's current permissions. Demote a user and their connected client loses access at its next refresh.
No framing. The consent screen sends X-Frame-Options: DENY and frame-ancestors 'none', so it cannot be embedded in a clickjacking page.
The scheduler also prunes expired codes and refresh tokens daily. Revoked refresh tokens are kept for 7 days so reuse can still be detected.

The module install fix matters even if you never use MCP

This is the fix we would push hardest. When you install a module, the install folder name comes from the module's own metadata: providers in module.json, PSR-4 keys in composer.json, or the module name. That metadata is untrusted. A crafted value like ../public/x could place a module's files in the web root.
In v1.5.0, every direct upload, replace and marketplace install goes through one check that only allows a plain namespace segment. The temporary path in replace and cancel requests is resolved with realpath before it is trusted. The advisory is GHSA-75q6-qrv2-96rx.
Module installs were already limited to Superadmins in earlier releases. So the realistic risk is a Superadmin installing a module from an untrusted source. That is still worth closing, because "someone sent me a module zip" is exactly how it would happen. If you build modules, our guide on building modular Laravel applications with Lara Dashboard covers how the module system is meant to work.

v1.4.9 closed stored XSS in LaraBuilder content

LaraBuilder stores page and post content as blocks. Before v1.4.9, an editor could save content with script tags, event handlers, Alpine or Livewire directives, or javascript: links, and that could run in the builder, the admin post view, email template previews or on the public page.
Now content is sanitized before it is stored and again whenever it is loaded. That covers every block type, including module blocks and blocks made with make:block. The code block keeps its escaped source, so code samples still display. Block renderers also escape colors, sizes, gaps and CSS before they reach style attributes.
If more than one person edits content on your site, this is the reason to upgrade today, not next sprint.

v1.4.9 also tightened social login and MCP email

Social login. An existing account is only linked when the provider says the email is verified. Google and LinkedIn report email_verified; GitHub and X only return verified emails. Accounts created from an unverified email are no longer marked verified, and the OAuth callback is rate-limited.
MCP send-email. The tool now requires email_template.edit. A token whose user only has email_template.view can still list and read templates, but cannot send. If you hand agents read-only template access, they can no longer email your contacts by accident.

Trade-offs: when not to turn on OAuth

OAuth is a convenience. It is not mandatory, and there are good reasons to skip it.
  • You only use Cursor, Claude Code or scripts. A scoped agent token is simpler and already works.
  • Your site blocks dot-paths in nginx. The well-known endpoints must be reachable, so you would need a config change first.
  • You run in demo mode. Approving clients is disabled there by design.
  • You cannot give the approving user the manage settings permission. Approval needs it, the same as creating a token by hand.
  • You want no AI client touching the CMS at all. Leave the MCP server off and the endpoints stay 404.
Also be honest about scope. OAuth changes how a client gets a token. It does not make an agent safer than the permissions of the person who approved it. If an admin approves Claude.ai, the connector acts with that admin's abilities. Approve with a least-privilege user where you can.
For the nginx case, the docs give this block: location ^~ /.well-known/ { try_files $uri $uri/ /index.php?$query_string; }. Test it on staging before production.

Upgrade checklist

Run through this list on staging first, then production. Our post on how to secure a self-hosted Laravel CMS covers the wider hardening work.
  1. Take a database and file backup, and check you can restore it.
  2. Upgrade the core from the admin, or on the server with php artisan core:upgrade 1.5.0.
  3. Run php artisan core:verify with the expected version to confirm modules were preserved.
  4. Confirm the /api/health endpoint reports v1.5.0.
  5. Open a few LaraBuilder pages and check they still render as expected after sanitizing.
  6. Review MCP agent tokens and revoke any you no longer use.
  7. If you use OpenAI, check AI settings now show gpt-6-luna or gpt-6-sol.
  8. If you want OAuth, enable MCP, allow well-known paths, then add your /mcp URL in Claude.ai.
  9. After connecting, find the OAuth token in the agent list so you know where to revoke it.
If something goes wrong, php artisan core:rollback --latest --force restores the latest backup made by the upgrade.

Verdict

v1.4.9 and v1.5.0 are the releases to be on. The security fixes are concrete, scoped and documented with advisories. The OAuth work makes Claude.ai a first-class client of your CMS without inventing a new permission model, and it stays off unless you turn on MCP.
If you are choosing a Laravel CMS for a new build and want agents in the loop from day one, try Lara Dashboard. Upgrade, connect one client with a least-privilege user, and watch the token list before you trust it with more.

FAQ

Do I have to use OAuth after upgrading to v1.5.0?

No. Bearer agent tokens still work exactly as before. OAuth is an extra way to connect for clients that cannot send custom headers.

Is the MCP server on by default in Lara Dashboard?

No. You turn it on under Settings → MCP. While it is off, the /mcp route and every OAuth endpoint return 404.

How long do OAuth tokens last?

Access tokens last 60 minutes and refresh tokens last 30 days. Refresh tokens rotate on every use, and reusing an old one revokes the grant.

How do I disconnect Claude.ai from my CMS?

Revoke the token named OAuth · <client name> in the agent token list. That also revokes its refresh token, so the client must ask for approval again.

Which security fixes affect sites that do not use MCP?

The module install path fix, the LaraBuilder sanitizing, and the social login changes apply to every site. Only the send-email and OAuth items are MCP-specific.

Can I skip v1.4.9 and go straight to v1.5.0?

Yes. v1.5.0 includes everything in v1.4.9. Upgrade to the latest version and you get both sets of fixes.
Laravel CMS Open source Module Architecture laravel authorization

Try Lara Dashboard for Free

Explore every feature live — no sign-up required.

Launch Live Demo