From 1db538c549f51dda9e7c0fb594b8312a6f84d0ac Mon Sep 17 00:00:00 2001 From: Fraenkiman Date: Sat, 1 Aug 2026 01:29:07 +0200 Subject: [PATCH] Prevent drafts from being listed and disclosed - A security vulnerability that listed and disclosed unpublished drafts has been fixed. Many thanks to @NomanProdhan for reporting this vulnerability --- admin/panels/static/admin.static.delete.php | 4 ++-- admin/panels/static/admin.static.write.php | 7 ++++++- fp-includes/core/core.static.php | 10 +++++++++- .../validate_criteria.isValidEntryId.php | 3 ++- fp-plugins/prettyurls/plugin.prettyurls.php | 18 ++++++++++++++++-- sitemap.php | 4 ++++ 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/admin/panels/static/admin.static.delete.php b/admin/panels/static/admin.static.delete.php index 03dc9421c..7d25d876a 100755 --- a/admin/panels/static/admin.static.delete.php +++ b/admin/panels/static/admin.static.delete.php @@ -48,8 +48,8 @@ function ondelete() { // Clean up input $id = sanitize_text_field($this->page); - // Validate static pages directly here - if (empty($id) || !preg_match('/^[a-zA-Z0-9-_]+$/', $id)) { + // Keep the existing ASCII admin policy, but share the Core safety check. + if (empty($id) || !static_isvalid($id) || !preg_match('/^[a-zA-Z0-9-_]+$/', $id)) { // Error status $this->smarty->assign('success', -1); return 1; diff --git a/admin/panels/static/admin.static.write.php b/admin/panels/static/admin.static.write.php index 94929ab68..1109e38cd 100644 --- a/admin/panels/static/admin.static.write.php +++ b/admin/panels/static/admin.static.write.php @@ -125,7 +125,12 @@ function sanitizePageId($id) { '/[^\p{L}\p{N}_-]/u' ], '', $id); - return trim(str_replace(' ', '', $id)); + if (!is_string($id)) { + return ''; + } + + $id = trim(str_replace(' ', '', $id)); + return static_isvalid($id) ? $id : ''; } function makePageTitle($title, $sep) { diff --git a/fp-includes/core/core.static.php b/fp-includes/core/core.static.php index 4cf457cca..f805be637 100755 --- a/fp-includes/core/core.static.php +++ b/fp-includes/core/core.static.php @@ -76,7 +76,15 @@ function static_parse($id) { } function static_isvalid($id) { - return preg_match('![^./\\\\]+!', $id); + if (!is_string($id) || $id === '') { + return false; + } + + if (strpos($id, "\0") !== false) { + return false; + } + + return preg_match('/\A[\p{L}\p{N}_-]+\z/u', $id) === 1; } function static_save($entry, $id, $oldid = null) { diff --git a/fp-includes/fp-smartyplugins/validate_criteria.isValidEntryId.php b/fp-includes/fp-smartyplugins/validate_criteria.isValidEntryId.php index c03e2ca5b..fe55e1764 100644 --- a/fp-includes/fp-smartyplugins/validate_criteria.isValidEntryId.php +++ b/fp-includes/fp-smartyplugins/validate_criteria.isValidEntryId.php @@ -39,6 +39,7 @@ function smarty_validate_criteria_isValidEntryId($value, $empty, &$params, &$for return false; } - return !preg_match('/[^a-z0-9\-_]/i',$value); + // Keep the existing ASCII editor policy, but share the Core safety check. + return static_isvalid($value) && !preg_match('/[^a-z0-9\-_]/i', $value); } ?> diff --git a/fp-plugins/prettyurls/plugin.prettyurls.php b/fp-plugins/prettyurls/plugin.prettyurls.php index c3550ca16..eedb168a3 100644 --- a/fp-plugins/prettyurls/plugin.prettyurls.php +++ b/fp-plugins/prettyurls/plugin.prettyurls.php @@ -137,6 +137,10 @@ function lastcomments_feed_link_atom($str) { } function staticlink($str, $id) { + if (!static_isvalid($id)) { + return $str; + } + return $this->baseurl . $id . "/"; } @@ -226,8 +230,13 @@ function handle_date($matches) { } function handle_static($matches) { + if (!isset($matches [1]) || !static_isvalid($matches [1])) { + return isset($matches [0]) ? $matches [0] : ''; + } + $this->fp_params ['page'] = $matches [1]; $this->status = 2; + return ''; } function handle_entry($matches) { @@ -1160,8 +1169,13 @@ function prettyurls_redirect_canonical() { } $target = $base . 'page/' . $pn . '/'; } elseif ($has_page) { - $id = preg_replace('/[^A-Za-z0-9_-]/', '', (string) $_GET ['page']); - if ($id === '') { + $rawId = (string) $_GET ['page']; + if (!static_isvalid($rawId)) { + return; + } + + $id = preg_replace('/[^A-Za-z0-9_-]/', '', $rawId); + if ($id === '' || !static_isvalid($id)) { return; } // Build via staticlink() to respect all modes diff --git a/sitemap.php b/sitemap.php index ac97880bb..25b1654aa 100644 --- a/sitemap.php +++ b/sitemap.php @@ -61,6 +61,10 @@ $statics = static_getlist(); foreach ($statics as $currentstatic) { $currentStaticData = static_parse($currentstatic); + if (!is_array($currentStaticData)) { + continue; + } + $loc = BLOG_BASEURL . '?page=' . $currentstatic; // If current static has no date, use timestamp of now