Releases: getkirby/kirby
Release list
5.5.0
🎉 Features
Local development licenses
A Kirby site can now be activated as development site when you confirm to comply with the license terms for free development licenses. When the site is not set up locally, Kirby will regularly check that your development site is not publicly accessible. #7832
Frontmatter Data Handler
New Frontmatter Data handler, which can be used to import or export frontmatter into Kirby. #8019
Decoding
use Kirby\Data\Frontmatter;
$md = <<<MD
---
title: My new article
date: '2026-03-12'
---
# Hello world
This is my brand new article written in **Frontmatter/Markdown**
MD;
$result = Frontmatter::decode($md);
// [
// 'title' => 'My new article',
// 'date' => '2026-03-12',
// 'text' => '# Hello world ...'
// ]Encoding
use Kirby\Data\Frontmatter;
$result = Frontmatter::encode([
'title' => 'My new article',
'date' => '2026-03-12',
'text' => '# Hello world …'
]);
// ---
// title: My new article
// date: 2026-03-12
// ---
// # Hello world …New translations
- Japanese (thanks to Kosuke Okahara)
- Ukranian
✨ Enhancements
- SmartyPants is directly using UTF-8 characters instead of HTML entities
- A page/site/user/file will now automatically be unlocked, as soon as the editor leaves the view or closes the tab/window. This will make sure that content-editing is not unnecessarily blocked for other editors. #7975
- New
Kirby\Content\Version::unlock()method - New
panel.content.unlock()method - New
/api/(:all)/changes/unlockroute
- New
- License dialog: Show registered domain and link to license terms #7832
- You can now use
this.$helper.string.sanitizeHTML()in the Panel to create a clean HTML string with configurable marks and nodes. By default, the sanitizer will only keep inline marks (bold, code, italic, link, strike, sub, sup, underline) #7922To set custom writer marks and nodes, you can pass an options object:this.$helper.string.sanitizeHTML('<p><marquee><strong onclick="alert(\'boo\')">Foo</strong></marquee></p>') // returns: <strong>Foo</strong>
this.$helper.string.sanitizeHTML(unsanitizedHTML, { marks: ["bold"], nodes: ["doc", "praagraph", "text")] });
- It's now possible to define any extension directly in your config, to be able to set site-specific extensions without creating a helper plugin. #8005
// /site/config/config.php return [ 'extensions' => [ 'pageModels' => [ // ... ], 'blueprints' => [ // ... ] ] ];
- Link field: reduced the amount of backend request fired directly when mounted (thx @tobimori) #8072
- Added some missing common/modern extensions to
Kirby\Filesystem\F::$typesandKirby\Filesystem\Mime::$types. #8134 - New
Kirby\Toolkit\A::flip()method #8132 - Increased length of randomly generated chunk IDs for chunked uploads to reduce risk of filename collisions #8182
- New
Kirby\Filesystem\F::update($file, $callback)method that reads and updates a file under lock #8187 - Improved error handling for block snippet errors rendered via
Kirby\Cms\Block::toHtml()by logging suppressed errors and escalating exceptions in debug mode #8085. - Added a translatable default placeholder for the tags field input #6114
🏎️ Performance
- Improved performance of several system methods:
Kirby\Filesystem\Dir::size()#8131Kirby\Filesystem\Mime::fromSvg()#8130Kirby\Filesystem\Mime::toExtension()andKirby\Filesystem\Mime::toExtensions()#8133Kirby\Toolkit\Controller#8143Kirby\Toolkit\Html::attr()andKirby|Toolkit\Xml::encode()#8144Kirby\Toolkit\Str::similarity(),Kirby\Toolkit\Str::startsWith(),Kirby\Toolkit\Str::endsWith(),Kirby\Toolkit\Str::encode(),Kirby\Toolkit\Str::ascii()#8138 #8147 #8145 #8158- Excluded keys lookup set in
Kirby\Toolkit\A::without()#8146
🐛 Bug fixes
- Structure field previews: fields with HTML content (e.g. list, writer) do not expand the table with all their content anymore #7918
- Fixed URL validation for URLs with multiple hyphens #7942
- Redis cache driver: Fixed flushing all databases even when using a prefix. Now only the Reds database for the cache with its prefix gets flushed. #8148
- Fixed
minWords/maxWordsvalidators for non-single whitespace #8141 - Handle
Dir::remove()with atomic rename #6266 panel.request.body(null)does not send"null"to the backend as the request body anymore #8016- Unset request headers aren't sent as
"false"to the backend anymore but instead omitted from the request. #8016 - Fixed handling of partial step config arrays in
Kirby\Toolkit\Date Kirby\Toolkit\LayzValue: fixed passing variadic arguments #8139Kirby\Toolkit\A::implode(): preserve falsy values when imploding array #8140- Fixed fractional support for
Kirby\Toolkit|Str::toBytes()#8159 - Blocks field: Fixed batch delete #8206
- Panel system view: The warning for the default cookie key is no longer displayed if a custom cookie key was set via the
cookie.keyoption - Panel: Fixed failing to load when a stricter Content-Security-Policy with nonce-based script-src is used. #8208
I18n::template(): Prevent TypeError when$replaceis null #8199- Kirby queries: Fixed tokenizer position desync on multibyte characters (@thx @LaurentTacco) #8203
- Fixed a content lock deadlock in multilingual setups where saving a secondary language while another user holds the lock on the primary language would cause both users to see the page as locked by the other. #8099
- Fixed file sorting when a secondary language is active #8212
- Fixed Cmd/Ctrl+S in textarea toolbar dialogs inserting
[object Object]instead of the formatted link/email text. #7934 - Disabled unselected model picker options once the field’s
maxlimit is reached #8232 - Localize license hub link #8239
☠️ Deprecated
- Using arbitrary custom permissions without registering them first via the
permissionsextension has been deprecated. Those will be ignored in a future release, so make sure to define your custom permissions via thepermissionsextension. #8070 Kirby\Text\KirbyTag::option()andKirby\Text\KirbyTag::$options: Use$tag->kirby()->option()instead. #8196Kirby\Text\KirbyTags::parse():$optionsparameter. Use new$debugparameter instead. #8196
♻️ Refactored
- New
Kirby\Cms\LicenseStatus::AcknowledgedandKirby\Cms\LicenseType::Freecases #7832 $helper.string.hasEmoji(): simplified regular expression #7966- Started refactoring some of our JavaScript code as TypeScript for increased type-safety #7973
- Migrated helpers to Typescript:
$helper.array#7977,$helper.regex#7976 $helper.debounce/throttle#7980,$helper.isComponent#7982,$helper.embed#7983,$helper.keyboard#7984,$helper.isUploadEvent#7985,$helper.queue#7981,$helper.file#7990,$helper.field#7989,$helper.string#7979,$helper.link#7994,$helper.focus#7991,$helper.url#7992,$helper.page#7995,$library.colors#7997,$helper.clipboard#7988,$helper.upload#7996,dayjsplugins #8009,$helper.sort#7993- Migrated
HistoryandTimeras helper class to TypeScript #8010 #8011 - Migrated first Panel state modules to TypeScript #8012 #8020 #8015, #8016, #8028, #8027, #8033, #8030, #8031, #8032, #8029, #8034, #8039, #8038, #8041, #8043, #8042
- Types on
this.$library,this.$helperandthis.$escare exposed in Vue SFC #8017
- Migrated helpers to Typescript:
- New
RedirectErrorerror class with support inpanel.error()#8016 - Refactored Permissions (thanks to @lukaskleinschmidt) #8004
- Renamed
Permissions::$actionsproperty to$defaults; added separate protected array$actionspopulated by the constructor - Replaced 6 old methods (
Permissions::setAll,Permissions::setCategory,Permissions::setCategories,Permissions::setAction,Permissions::hasAction,Permissions::hasCategory) with 4 cleaner ones:Permissions::normalize(),Permissions::expand(),Permissions::get(),Permissions::has() Permissions::normalize()andPermissions::expand()handle all four input shapes:null,bool,['cat' => bool],['cat' => ['action' => bool]], including wildcard at both levels.Permissions::for()now deprecates$category = nullviaHelpers::deprecated()and throwsLogicExceptionif a stored value is somehow not a bool- Slightly refactored the Blueprint class:
array_fill_keys(array_keys($defaults), false)instead ofarray_map(fn () => false, $defaults).
- Renamed
- Ensure not wrapping
<div>tags with<span>tags in<k-input>#8018 - New
Kirby\Template\Snippet::hasSlots()method #8178 - Guard Slots in Snippets from being double-opened #8179
- New
$debugparameter inKirby\Text\KirbyTags::parse()#8196 - Clarify
Html::rel()use #8142
🚨 Breaking changes
Kirby\Cms\Block::toHtml()now throws block snippet exceptions in debug mode instead of returning an inlineBlock errormessage. While this is technically a breaking change, we see this as a debugging enhancement which can clearly go into a minor release without negative impact for real-world projects.
🧹 Housekeeping
5.4.4
Note
This release is part of our monthly security release series. Find out more about those releases and their background on our website: https://getkirby.com/buzz/security-update
🚨 Security
🛎️ Recommendation to secure your content salt and cookie key values
Kirby internally relies on the following values:
- The
content.saltoption is used to generate secure preview and media URLs that should not be guessable by external visitors. - The
Kirby\Http\Cookie::$keyproperty, to sign (or authenticate) cookie values to prevent easy tampering with cookie values that have been set from the backend.
We recommend to set the content.salt and Kirby\Http\Cookie::$key values to long random strings for all of your sites.
We have updated the security guide with a section on this topic and added warnings to the Panel system view if Kirby detects the unchanged defaults.
Thanks to @adrgs and Peter Levashov (@petersevera) for their responsible disclosure and suggestion.
External Initialization of the Panel on reverse proxy setups with the Forwarded, X-Client-IP or X-Real-IP header
This vulnerability affects Kirby sites that have no configured user accounts and are running on publicly accessible servers behind a reverse proxy that sets the Forwarded: for=..., X-Client-IP, or X-Real-IP request header.
It was possible to install the Panel (= create the first admin user) in these setups even from remote IP addresses.
This vulnerability is of critical severity for affected sites.
Your site is not affected if any of the following apply:
- An admin account has already been configured
- The Panel and API are disabled
- The site is not running behind a reverse proxy
- The reverse proxy sets the
X-Forwarded-FororClient-IPheader instead of the affected ones.
Advisory Details:
- CVE ID: CVE-2026-54003
- Severity: critical (CVSS score 9.1)
- Advisory: GHSA-whxw-24jc-cwmv
Thanks to Peter Levashov (@petersevera) for responsibly reporting the identified issue.
Cross-site scripting (XSS) from incomplete HTML/XML sanitization in Dom::sanitize()
This vulnerability affects Kirby sites and plugins that use the writer or list fields or that use $dom->sanitize(), Sane::sanitize(), Sane\Html::sanitize(), Sane\Svg::sanitize(), Sane\Xml::sanitize(), Sane::sanitizeFile() or $file->sanitizeContents() with untrusted input.
It was possible to inject malicious markup as children of an unknown HTML/XML tag, which would then be passed through Dom::sanitize() without being correctly sanitized according to the provided sanitization rules, causing a cross-site scripting (XSS) risk.
This vulnerability is of high severity for affected sites.
The default file upload protection is not affected, so sites that only validate uploaded files are not exposed to this vulnerability. The vulnerability can only be exploited by authenticated users.
- CVE ID: CVE-2026-54002
- Severity: high (CVSS score 8.5)
- Advisory: GHSA-wr9h-4r83-f4v6
Thanks to Shafiq Aiman (@shafiqaimanx) for responsibly reporting the identified issue.
Self cross-site scripting (self-XSS) in the writer field
This vulnerability affects Kirby sites that use the writer field in any blueprint.
It was possible to include a scripting link as the target of a link (or email link). This link target would then be clickable by the user who entered it.
A successful attack commonly requires knowledge of the content structure by the attacker as well as social engineering of a user with access to the Panel. The attack cannot be automated.
In Kirby's default configuration, the vulnerability is limited to self-XSS and cannot directly affect other users or visitors of the site. Panel plugins that are directly using the <k-writer> component may also be affected by stored XSS if they don't sanitize the resulting HTML before saving it to the content.
This vulnerability is of high severity for affected sites.
- CVE ID: CVE-2026-49276
- Severity: high (CVSS score 7.4)
- Advisory: GHSA-rhj6-r49h-5932
pages.access permission is not checked in the site/find REST API route
This vulnerability affects all Kirby sites where users of a particular role have no permission to access pages (pages.access permission is disabled). This can be due to configuration in the user blueprint(s), options in the model blueprint(s), or a combination of both settings.
It was possible to retrieve page information (including full content and metadata) for arbitrary pages via the /api/site/find route without being authorized to access the respective pages.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you intend all users of your site to be able to access all pages of the site. The vulnerability can only be exploited by authenticated users that know or guess the IDs or UUIDs of pages. Write actions as well as access to draft pages are not affected by this vulnerability.
- CVE ID: CVE-2026-54005
- Severity: high (CVSS score 7.1)
- Advisory: GHSA-r3w8-2c5r-h9j9
Thanks to Rizky Muhammad (@EvidentObscurity) for responsibly reporting the identified issue.
Request header injection in Http\Remote
This vulnerability affects Kirby sites and plugins that use the Kirby\Http\Remote class (including Remote::request(), Remote::get(), Remote::post(), and similar helpers) to send outgoing HTTP requests and that pass untrusted, user-controlled data into the headers option of such a request.
By including newline characters in the value of the header, it was possible to inject a separate, independent header that was not intended to be set.
A successful attack requires that an application or plugin forwards attacker-influenced input into a request header value. Sites that only send static, developer-defined headers are not affected. The attack does not target Panel users or site visitors directly; it targets the remote service that Kirby connects to.
In Kirby's default configuration, the Remote class is not exposed to untrusted input, so a default installation is not affected. The vulnerability becomes relevant for custom code, plugins, or integrations that build request headers from user input.
- CVE ID: CVE-2026-50188
- Severity: moderate (CVSS score 6.9)
- Advisory: GHSA-4v4h-m2qq-ppgw
Access to files of top-level drafts is not protected by permissions
This vulnerability affects Kirby 5 sites that have the content.fileRedirects option enabled (set to true or a custom closure) as well as all Kirby 4 sites that haven't explicitly disabled this option.
It was possible to access clean file URLs of top-level drafts (e.g. /about-us/team.jpg) without providing authentication, without being authorized to access the top-level draft page, and without providing a valid preview token.
Sites on Kirby 5 using the default configuration are not affected by this vulnerability (the content.fileRedirects option is disabled by default since Kirby 5.0.0). It was also not possible to maliciously access clean file URLs for files stored in page drafts that are not on the top-level (such as /blog/article/resource.pdf).
- CVE ID: CVE-2026-54004
- Severity: moderate (CVSS score 6.3)
- Advisory: GHSA-89cp-7p28-jffg
Thanks to @adamyordan for responsibly reporting the identified issue.
pages.access permission is not checked in the pages picker for parent pages
This vulnerability affects all Kirby sites that use the pages field and where users of a particular role have no permission to access pages (pages.access permission is disabled). This can be due to configuration in the user blueprint(s), options in the model blueprint(s), or a combination of both settings.
It was possible to confirm the existence of arbitrary pages and to retrieve the value of the title field of the pages found.
The vulnerability can only be exploited by authenticated users. Write actions are not affected by this vulnerability.
- CVE ID: CVE-2026-49274
- Severity: moderate (CVSS score 5.3)
- Advisory: GHSA-23q2-54qv-rq5x
🚨 Security fixes
- The
linkandemailmarks of thewriterfield are now protected against self-cross site scripting (self-XSS) from inserted scripting links - The page picker in the
pagesfield now consistently checks thepages.accesspermission for the provided parent page - Results of the
site/findAPI route are now filtered to only return pages that are accessible to the current user. - Files on draft pages are no longer exposed through clean file URLs when
content.fileRedirectsis enabled. - Kirby no longer allows to install the Panel with the first user account if a
Forwarded: for=...,X-Client-IPorX-Real-IPrequest header with external IP address was provided by a reverse proxy. - Show warnings in the system view when the
content.saltoption andCookie::$keydefault values have not been changed.
✨ Enhancements
- Harden TO...
4.9.4
Note
This release is part of our monthly security release series. Find out more about those releases and their background on our website: https://getkirby.com/buzz/security-update
🚨 Security
This is a backport of our security release for Kirby 5. For all details and vulnerabilities see: https://github.com/getkirby/kirby/releases/tag/5.4.4
We recommend all users upgrade to Kirby 5. If an upgrade is not possible, this security release is the alternative solution.
5.4.3
🐛 Bug fixes
- Throw exceptions for UUID cache misses when
content.uuid.index = falseis set only indebugmode #8150
🚨 Security
- Updated PHP and JS dependencies
4.9.3
🚨 Security
- Updated PHP and JS dependencies
5.4.2
🚨 Security
After our 5.4.1 release yesterday, the symfony/yaml package had a security release today. This is a patched version with the updated yaml dependency.
4.9.2
🚨 Security
After our 4.9.1 release yesterday, the symfony/yaml package had a security release today. This is a patched version with the updated yaml dependency.
5.4.1
Update: After our 5.4.1 release yesterday, the symfony/yaml package had a security release today. There is a patched version with the updated yaml dependency: https://github.com/getkirby/kirby/releases/tag/5.4.2
Note
This release is part of our new monthly security release series. Find out more about those releases and their background on our website: https://getkirby.com/buzz/security-update
🚨 Security
Pre-authentication path traversal and PHP file inclusion during user lookup
This vulnerability affects all Kirby sites on Kirby 5.3.0-5.4.0 and is independent from setup conditions and authentication.
This vulnerability is of high severity for all Kirby sites.
- CVE ID: CVE-2026-44177
- Severity: high (CVSS score 8.8)
- Advisory: GHSA-9hx7-c53c-v6x8
Thanks to @offset for responsibly reporting the identified issue.
Arbitrary Method Call via REST API search and collection query endpoints
This vulnerability affects all Kirby sites that might have potential attackers in the group of authenticated Panel users.
This vulnerability is of high severity for affected sites and has a high real-world impact.
- CVE ID: CVE-2026-44174
- Severity: high (CVSS score 8.7)
- Advisory: GHSA-86rh-h242-j8xp
Thanks to @mojamojam for responsibly reporting the identified issue.
Cross-site scripting (XSS) from list field content in the site frontend
This vulnerability affects all Kirby sites that use the list field or list block, when content is authored by users who may not be fully trusted. The attack requires an authenticated Panel user with update permission to any list field or list block.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you don't use the list field (or blocks field with the list block) in any of your blueprints, or if every user who can edit content is fully trusted. The attack only surfaces in the site frontend (i.e. in your templates). The Panel itself is unaffected and will not execute JavaScript that was injected into list field content.
- CVE ID: CVE-2026-44175
- Severity: high (CVSS score 8.5)
- Advisory: GHSA-5fhx-9q32-q257
Thanks to @offset for responsibly reporting the identified issue.
Cross-site scripting (XSS) from links in KirbyTags, image blocks and imported blocks HTML in the site frontend
This vulnerability affects all Kirby sites that allow the use of the (link: …) KirbyTag, the link: parameter of the (image: …) KirbyTag, the built-in image block with a link or the HTML importer for blocks, when content is authored by users who may not be fully trusted. The attack requires an authenticated Panel user with update permission to any textarea or blocks field, or write access to content files through another vector (e.g. a frontend form or content sync pipeline). Another attack vector is the use of Html::a() or Html::link() with untrusted user input.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if none of the mentioned KirbyTags or block types are used, or if every user who can edit content is fully trusted. The attack only surfaces in the site frontend (i.e. in your templates). The Panel itself is unaffected and will not execute JavaScript that was injected into the textarea or blocks field content.
- CVE ID: CVE-2026-45368
- Severity: high (CVSS score 8.4)
- Advisory: GHSA-qvjf-922g-pj44
Thanks to @offset for responsibly reporting the identified issue.
pages.access permission is not checked during rendering of page drafts
This vulnerability affects all Kirby sites where users of a particular role have no permission to access pages (pages.access permission is disabled). This can be due to configuration in the user blueprint(s), via options in the model blueprint(s) or via a combination of both settings.
Your Kirby sites are not affected if you intend all users of your site to be able to access all page drafts of the site. The vulnerability can only be exploited by authenticated users. Write actions are not affected by this vulnerability.
- CVE ID: CVE-2026-44176
- Severity: moderate (CVSS score 6.0)
- Advisory: GHSA-2xw4-v2wx-hqq9
Thanks to @adrgs for responsibly reporting the identified issue.
Content locks disclose IDs and emails of inaccessible users from users.access/list permissions
This vulnerability affects all Kirby sites that restrict the visibility of users for certain roles via the users.access or users.list permissions. A site is affected if users of a particular role are not allowed to see other users in the Panel, for example because the role's blueprint sets users.access: false or users.list: false as permission for the authenticated user role and/or as option for the target user role.
Your Kirby site is not affected if all authenticated Panel users are permitted to access and list other users. The vulnerability can only be exploited by authenticated users.
- CVE ID: CVE-2026-45334
- Severity: moderate (CVSS score 5.3)
- Advisory: GHSA-39vq-49qm-r2mc
Thanks to Matteo Panzeri (@matte1782) for responsibly reporting the identified issue.
✨ Enhancements
- New
Kirby\Sane\Sane::sanitizeProseMirrorFields()method which sanitizes the value and converts non-breaking spaces to HTML entity to match ProseMirrors internal handling - New
Kirby\Http\Url::hasDangerousScheme()
🚨 Security fixes
- Validate user ID format and path containment in the
accountsdirectory during user lookup with$users->find() - Respect page access permissions when accessing/rendering drafts in frontend
- Remove insecure search options (sort and filter) in API routes
- New
Kirby\Toolkit\BlockAccessAttributefor model methods that must not be used by filterBy or sortBy in Collections. - List field values now are sanitized to protect it from XSS attacks
- Fix information disclosure in content lock data: the locking user's email and ID now hidden from users who do not have permission to list that user
- Ensure
Kirby\Toolkit\Html::link()andKirby\Http\Url::isAbsolute()do not allow dangerous schemes - The blocks HTML importer no longer imports link URLs with dangerous schemes
🐛 Bug fixes
- Fixed using
::filter()/::filterBy()with non-default separators #8062 - Fixed picker dialogs to respect the
search: falseoption #8054 - Fixed multiselect field search (thanks @lauriii) #8067
- Fixed JSON response error showing up on throttled Panel API calls #7351
- Imagick thumb driver: fixed preserving profiles listed in
profilesoption #8066 - Improve thumbnail generation reliability by writing thumbs #4632
- Panel file view: refresh view after replacing the file #8073
- Prevents ghost duplicate page folders caused by stale concurrent writes after page reordering #7964
- Fixed return type docs for
Collection::first()andCollection::last()to includenullfor empty collections #8094 - Pagination is now visible in the file-browser dialog #8080
- Fixed chunked uploads using the wrong file blueprint #8086
- Fixed first toggles option in blocks is selectable again #8093
- Time field: Fixed min/max validation message #8128
🚨 Breaking changes
Html::link()does no longer acceptjavascript:URLs. This is a dangerous anti-pattern with many better frontend alternatives and leaves too much space for potential attacks.
🧹 Housekeeping
- Upgrade npm dependencies #8060
4.9.1
Update: After our 4.9.1 release yesterday, the symfony/yaml package had a security release today. There is a patched version with the updated yaml dependency: https://github.com/getkirby/kirby/releases/tag/4.9.2
🚨 Security
This is a backport of our security release for Kirby 5. For all details and vulnerabilities see: https://github.com/getkirby/kirby/releases/tag/5.4.1
We recommend all users upgrade to Kirby 5. If an upgrade is not possible, this security release is the alternative solution.
5.4.0
🚨 Security
Server-Side Template Injection (SSTI) via double template resolution in option rendering
This vulnerability affects all Kirby sites that use option fields (checkboxes, color, multiselect, select, radio, tags or toggles) with options from a query or API whose values may not be fully trusted. It also affects direct uses of the OptionsApi or OptionsQuery classes of Kirby's Options package from plugin or site code. The attack requires either an
attacker in the group of authenticated Panel users or user interaction of another authenticated user.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you are not using any of the mentioned fields or the Options package, if all options are defined statically in the blueprints or if all dynamically gathered options are to be trusted.
- CVE ID: CVE-2026-34587
- Severity: high (CVSS score 7.6)
- Advisory: GHSA-jcjw-58rv-c452
Thanks to @offset for responsibly reporting the identified issue.
Page, file and user creation APIs bypass create permission check via unfiltered blueprint parameter
This vulnerability affects all Kirby sites where users of a particular role have no permission to create pages, files or users (pages.create, files.create or users.create permission is disabled). This can be due to configuration in the user blueprint(s), via options in the model blueprint(s) or via a combination of both settings.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you intend all users of your site to be able to create pages, files and users. The vulnerability can only be exploited by authenticated users.
- CVE ID: CVE-2026-41325
- Severity: high (CVSS score 7.1)
- Advisory: GHSA-6gqr-mx34-wh8r
Thanks to @offset for responsibly reporting the identified issue.
pages.access/list and files.access/list permissions are not consistently checked in the Panel and REST API
This vulnerability affects all Kirby sites where users of a particular role have no permission to access or list pages or files (pages.access, pages.list, files.access or files.list permission is disabled). This can be due to configuration in the user blueprint(s), via options in the model blueprint(s) or via a combination of both settings.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you intend all users of your site to be able to access all pages and files of the site. The vulnerability can only be exploited by authenticated users.
Write actions are not affected by this vulnerability.
- CVE ID: CVE-2026-42137
- Severity: high (CVSS score 7.1)
- Advisory: GHSA-85x2-r8xv-ww8c
Read access to site, user and role information is not gated by permissions
This vulnerability affects all Kirby sites that might have potential attackers in the group of authenticated Panel users.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you intend all users of your site to be able to list and access the site model and all users and roles, including the content stored within these models.
Write actions are not affected by this vulnerability as they were gated by permissions before.
- CVE ID: CVE-2026-42069
- Severity: high (CVSS score 7.1)
- Advisory: GHSA-2h7v-4372-f6x2
Thanks to @HuajiHD for responsibly reporting the identified issue.
XML Injection in the XML creator toolkit
This vulnerability only affects Kirby sites that use the Xml data handler (e.g. Data::encode($string, 'xml')) or the Xml::create(), Xml::tag() or Xml::value() method(s) in site or plugin code. The Kirby core does not use any of the affected methods.
If you use an affected method and cannot rule out input to these methods controlled by an attacker, we strongly recommend to update to a patch release.
- CVE ID: CVE-2026-32870
- Severity: medium (CVSS score 6.9)
- Advisory: GHSA-9wfj-c55w-j9qr
Thanks to Patrick Falb (@dapatrese) at FORMER 03 for responsibly reporting the identified issue.
User avatar creation, replacement and deletion are not gated by user update permissions
This vulnerability affects all Kirby sites where users of a particular role have no permission to update user information (user.update or users.update permission is disabled). This can be due to configuration in the blueprint(s) of the acting users, via options in the blueprint(s) of the target users or via a combination of both settings.
Your Kirby sites are not affected if you intend all users of your site to be able to upload, replace or delete user avatars. The vulnerability can only be exploited by authenticated users.
- CVE ID: CVE-2026-42174
- Severity: moderate (CVSS score 5.3)
- Advisory: GHSA-39cp-6679-8xv2
Page creation API bypasses changeStatus permission check via unfiltered isDraft parameter
This vulnerability affects all Kirby sites where users have the permission to create pages (pages.create permission is enabled) but not the permission to change the status of pages (pages.changeStatus permission is disabled). This can be due to configuration in the user blueprint(s), via options in the page blueprint(s) or via a combination of both settings.
Your Kirby sites are not affected if your use case does not consider the creation of published pages a malicious action. The vulnerability can only be exploited by authenticated users.
- CVE ID: CVE-2026-40099
- Severity: moderate (CVSS score 5.3)
- Advisory: GHSA-w942-j9r6-hr6r
Thanks to @offset for responsibly reporting the identified issue.
System API endpoint leaks installed version and license data to authenticated users
This vulnerability affects all Kirby sites that might have potential attackers in the group of authenticated Panel users.
- CVE ID: CVE-2026-42051
- Severity: moderate (CVSS score 5.3)
- Advisory: GHSA-x68m-c7jf-2572
Thanks to @HuajiHD and @0x-bala for responsibly reporting the identified issue.
✨ Enhancements
- Site permissions
- New
accesspermission for thesite - New
Kirby\Cms\Site::isAccessible()method checking if the current user hasaccesspermission for the site - New static
Kirby\Cms\Find::site()method returning the site object or throwingKirby\Exception\NotFoundExceptionif the site is not accessible - New i18n string
error.site.notAccessibleadded toi18n/translations/en.json
- New
- User permissions
- New
accessandlistpermissions for users and the current user. - New
Kirby\Cms\User::isAccessible()method checking if the current user hasaccesspermission for a given user - New
Kirby\Cms\User::isListable()method checking if a user is both accessible and haslistpermission. Inaccessible users are implicitly not listable - New static
Kirby\Cms\Find::users()method returning only users filtered byisListable()
- New
- Role permissions
- New
Kirby\Cms\Role::isAccessible()method checking if the current user hasusers.accessoruser.accesspermission. If the role is the same role as the user's, theuser.accesspermissions are checked. Otherwiseusers.access. - New static
Kirby\Cms\Find::role()andKirby\Cms\Find::roles()methods returning only roles filtered byisAccessible() - Added a new
error.role.notFoundtranslation key.
- New
- Avatar permissions
- New avatar hooks
user.createAvatar,user.replaceAvatar,user.deleteAvatar(including:beforeand:after) - New User class methods:
User::createAvatar(),User::replaceAvatar(),User::deleteAvatar() - New User rules:
UserRules::createAvatar(),UserRules::replaceAvatar(),UserRules::deleteAvatar(),UserRules::validAvatar()
- New avatar hooks
🚨 Security fixes
- The
GET /systemAPI route now consistently filters the relevant set of information by current system state Kirby\Cms\Find::parent()now usesKirby\Cms\Find::site()instead of$kirby->site()for the site model lookupKirby\Cms\Api::site()now delegates toKirby\Cms\Find::site()instead of$this->kirby->site()config/api/models/System.phpthetitlefield now reads directly from$this->kirby()->site()to bypass thesite.accesspermission check, ensuring the title is always available- The
page.movedialog now usesKirby\Cms\Find::site()in the submit handler, when a page gets moved to the top-level Kirby\Cms\Find::user()now enforcesisAccessible()on the resolved user, throwingKirby\Exception\NotFoundExceptionif the user exists but is inaccessible- API routes (
config/api/routes/users.php): all `$this->user()...