[TikiWiki-commits] [Git][tikiwiki/tiki][29.x] [BP][FIX] Implement centralized security headers management

"Rodriguez Nyiringabo \(@rodriguezny\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <6a22d3f43af10_381945ec780f2@gitlab-sidekiq-low-urgency-cpu-bound-v2-679d75d87c-2l5lw.mail>

Rodriguez Nyiringabo pushed to branch 29.x at Tiki Wiki CMS Groupware / Tiki


Commits:
4f1a215d by Rodriguez Nyiringabo at 2026-06-05T13:42:50+00:00
[BP][FIX] Implement centralized security headers management
---
* [BP][FIX] Implement centralized security headers management
---
* [FIX] Headelib: Rename method  `add_security_headers` to `addSecurityHeaders` for consistency.
---
* [FIX] Headelib: Rename method  addSecurityHeaders` to `add_security_headers` for consistency.

See merge request tikiwiki/tiki!10445

* [FIX] Implement centralized security headers management
---
* [FIX] Implement centralized security headers management

See merge request tikiwiki/tiki!10437

See merge request tikiwiki/tiki!10444

See merge request tikiwiki/tiki!10446

- - - - -


3 changed files:

- lib/core/Tiki/Smarty/SmartyTiki.php
- lib/headerlib.php
- tiki-login.php


Changes:

=====================================
lib/core/Tiki/Smarty/SmartyTiki.php
=====================================
@@ -257,6 +257,7 @@ class SmartyTiki extends Smarty
     ): void {
 
         global $prefs;
+        $headerlib = TikiLib::lib('header');
         $this->activateCustomErrorHandler();
 
         if (! empty($prefs['feature_htmlpurifier_output']) and $prefs['feature_htmlpurifier_output'] == 'y') {
@@ -270,173 +271,7 @@ class SmartyTiki extends Smarty
             }
         }
 
-        /**
-         * Add security headers. By default there headers are not sent.
-         * To change go to admin > security > site access
-         */
-        if (! headers_sent()) {
-            if (! isset($prefs['http_header_frame_options'])) {
-                $frame = false;
-            } else {
-                $frame = $prefs['http_header_frame_options'];
-            }
-            if (! isset($prefs['http_header_xss_protection'])) {
-                $xss = false;  // prevent smarty E_NOTICE
-            } else {
-                $xss = $prefs['http_header_xss_protection'];
-            }
-
-            if (! isset($prefs['http_header_content_type_options'])) {
-                $content_type_options = false;  // prevent smarty E_NOTICE
-            } else {
-                $content_type_options = $prefs['http_header_content_type_options'];
-            }
-
-            if (! isset($prefs['http_header_content_security_policy'])) {
-                $content_security_policy = false;  // prevent smarty E_NOTICE
-            } else {
-                $content_security_policy = $prefs['http_header_content_security_policy'];
-            }
-
-            if (! isset($prefs['http_header_strict_transport_security'])) {
-                $strict_transport_security = false;  // prevent smarty E_NOTICE
-            } else {
-                $strict_transport_security = $prefs['http_header_strict_transport_security'];
-            }
-
-            if (! isset($prefs['http_header_public_key_pins'])) {
-                $public_key_pins = false;  // prevent smarty E_NOTICE
-            } else {
-                $public_key_pins = $prefs['http_header_public_key_pins'];
-            }
-
-            if (! isset($prefs['http_header_referrer_policy'])) {
-                $referrer_policy = false;
-            } else {
-                $referrer_policy = $prefs['http_header_referrer_policy'];
-            }
-
-            if (! isset($prefs['http_header_permitted_cross_domain_policies'])) {
-                $permitted_cross_domain_policies = false;
-            } else {
-                $permitted_cross_domain_policies = $prefs['http_header_permitted_cross_domain_policies'];
-            }
-
-            if ($frame == 'y') {
-                    $header_value = $prefs['http_header_frame_options_value'];
-                    header('X-Frame-Options: ' . $header_value);
-            }
-            if ($xss == 'y') {
-                    $header_value = $prefs['http_header_xss_protection_value'];
-                    header('X-XSS-Protection: ' . $header_value);
-            }
-            if ($content_type_options == 'y') {
-                header('X-Content-Type-Options: nosniff');
-            }
-            if ($access_control_allow_credentials === 'y') {
-                header('Access-Control-Allow-Credentials: true');
-            }
-            if ($access_control_allow_methods === 'y') {
-                $header_value = trim($prefs['http_header_access_control_allow_methods_value']);
-                if ($access_control_allow_credentials === 'y' && $header_value === '*') {
-                    Feedback::error(tr("CORS configuration error: Wildcard (*) is not allowed for Access-Control-Allow-Methods when http_header_access_control_allow_credential is enabled"));
-                    header_remove('Access-Control-Allow-Methods');
-                } else {
-                    header('Access-Control-Allow-Methods: ' . $header_value);
-                }
-            }
-            if ($access_control_allow_headers === 'y') {
-                $headers_value = trim($prefs['http_header_access_control_allow_headers_value']);
-                if ($access_control_allow_credentials === 'y' && $headers_value === '*') {
-                    Feedback::error(tr("CORS configuration error: Wildcard (*) is not allowed for Access-Control-Allow-Headers when Access-Control-Allow-Credentials is enabled."));
-                    header_remove('Access-Control-Allow-Headers');
-                } else {
-                    header('Access-Control-Allow-Headers: ' . $headers_value);
-                }
-            }
-            if ($cross_origin_embedder_policy === 'y') {
-                switch (trim($prefs['http_header_cross_origin_embedder_policy_value'])) {
-                    case 'require-corp':
-                        header('Cross-Origin-Embedder-Policy: require-corp');
-                        break;
-                    case 'credentialless':
-                        header('Cross-Origin-Embedder-Policy: credentialless');
-                        break;
-                    case 'unsafe-none':
-                        header('Cross-Origin-Embedder-Policy: unsafe-none');
-                        break;
-                    default:
-                        break;
-                }
-            }
-            if ($cross_origin_resource_policy === 'y') {
-                switch (trim($prefs['http_header_cross_origin_resource_policy_value'])) {
-                    case 'same-origin':
-                        header('Cross-Origin-Resource-Policy: same-origin');
-                        break;
-                    case 'same-site':
-                        header('Cross-Origin-Resource-Policy: same-site');
-                        break;
-                    case 'cross-origin':
-                        header('Cross-Origin-Resource-Policy: cross-origin');
-                        break;
-                    default:
-                        break;
-                }
-            }
-            if ($cross_origin_opener_policy === 'y') {
-                switch (trim($prefs['http_header_cross_origin_opener_policy_value'])) {
-                    case 'same-origin':
-                        header('Cross-Origin-Opener-Policy: same-origin');
-                        break;
-                    case 'same-origin-allow-popups':
-                        header('Cross-Origin-Opener-Policy: same-origin-allow-popups');
-                        break;
-                    case 'same-origin-plus-coep':
-                        header('Cross-Origin-Opener-Policy: same-origin-plus-coep');
-                        break;
-                    case 'unsafe-none':
-                        header('Cross-Origin-Opener-Policy: unsafe-none');
-                        break;
-                    default:
-                        break;
-                }
-            }
-            if ($content_security_policy == 'y') {
-                $header_value = trim($prefs['http_header_content_security_policy_value']);
-                if ($header_value !== '') {
-                    header('Content-Security-Policy: ' . $header_value);
-                }
-            }
-
-            if ($strict_transport_security == 'y') {
-                $header_value = trim($prefs['http_header_strict_transport_security_value']);
-                if ($header_value !== '') {
-                    header('Strict-Transport-Security: ' . $header_value);
-                }
-            }
-
-            if ($public_key_pins == 'y') {
-                $header_value = trim($prefs['http_header_public_key_pins_value']);
-                if ($header_value !== '') {
-                    header('Public-Key-Pins: ' . $header_value);
-                }
-            }
-
-            if ($referrer_policy === 'y') {
-                $header_value = trim($prefs['http_header_referrer_policy_value']);
-                if ($header_value !== '') {
-                    header('Referrer-Policy: ' . $header_value);
-                }
-            }
-
-            if ($permitted_cross_domain_policies === 'y') {
-                $header_value = trim($prefs['http_header_permitted_cross_domain_policies_value']);
-                if ($header_value !== '') {
-                    header('X-Permitted-Cross-Domain-Policies: ' . $header_value);
-                }
-            }
-        }
+        $headerlib->addSecurityHeaders();
 
         /**
          * By default, display is used with text/html content in UTF-8 encoding


=====================================
lib/headerlib.php
=====================================
@@ -222,6 +222,208 @@ class HeaderLib
         $this->title = urlencode($string);
     }
 
+    /**
+     * Add security headers. By default these headers are not sent.
+     * To change go to admin > security > site access
+     */
+    public function addSecurityHeaders()
+    {
+        global $prefs;
+
+        if (! headers_sent()) {
+            if (! isset($prefs['http_header_frame_options'])) {
+                $frame = false;
+            } else {
+                $frame = $prefs['http_header_frame_options'];
+            }
+            if (! isset($prefs['http_header_xss_protection'])) {
+                $xss = false;  // prevent smarty E_NOTICE
+            } else {
+                $xss = $prefs['http_header_xss_protection'];
+            }
+
+            if (! isset($prefs['http_header_content_type_options'])) {
+                $content_type_options = false;  // prevent smarty E_NOTICE
+            } else {
+                $content_type_options = $prefs['http_header_content_type_options'];
+            }
+            if (! isset($prefs['http_header_access_control_allow_credentials'])) {
+                $access_control_allow_credentials = false;
+            } else {
+                $access_control_allow_credentials = $prefs['http_header_access_control_allow_credentials'];
+            }
+            if (! isset($prefs['http_header_access_control_allow_methods'])) {
+                $access_control_allow_methods = false;
+            } else {
+                $access_control_allow_methods = $prefs['http_header_access_control_allow_methods'];
+            }
+            if (! isset($prefs['http_header_access_control_allow_headers'])) {
+                $access_control_allow_headers = false;
+            } else {
+                $access_control_allow_headers = $prefs['http_header_access_control_allow_headers'];
+            }
+            if (! isset($prefs['http_header_cross_origin_embedder_policy'])) {
+                $cross_origin_embedder_policy = false;
+            } else {
+                $cross_origin_embedder_policy = $prefs['http_header_cross_origin_embedder_policy'];
+            }
+            if (! isset($prefs['http_header_cross_origin_resource_policy'])) {
+                $cross_origin_resource_policy = false;
+            } else {
+                $cross_origin_resource_policy = $prefs['http_header_cross_origin_resource_policy'];
+            }
+            if (! isset($prefs['http_header_cross_origin_opener_policy'])) {
+                $cross_origin_opener_policy = false;
+            } else {
+                $cross_origin_opener_policy = $prefs['http_header_cross_origin_opener_policy'];
+            }
+            if (! isset($prefs['http_header_content_security_policy'])) {
+                $content_security_policy = false;  // prevent smarty E_NOTICE
+            } else {
+                $content_security_policy = $prefs['http_header_content_security_policy'];
+            }
+
+            if (! isset($prefs['http_header_strict_transport_security'])) {
+                $strict_transport_security = false;  // prevent smarty E_NOTICE
+            } else {
+                $strict_transport_security = $prefs['http_header_strict_transport_security'];
+            }
+
+            if (! isset($prefs['http_header_public_key_pins'])) {
+                $public_key_pins = false;  // prevent smarty E_NOTICE
+            } else {
+                $public_key_pins = $prefs['http_header_public_key_pins'];
+            }
+
+            if (! isset($prefs['http_header_referrer_policy'])) {
+                $referrer_policy = false;
+            } else {
+                $referrer_policy = $prefs['http_header_referrer_policy'];
+            }
+
+            if (! isset($prefs['http_header_permitted_cross_domain_policies'])) {
+                $permitted_cross_domain_policies = false;
+            } else {
+                $permitted_cross_domain_policies = $prefs['http_header_permitted_cross_domain_policies'];
+            }
+
+            if ($frame == 'y') {
+                    $header_value = $prefs['http_header_frame_options_value'];
+                    header('X-Frame-Options: ' . $header_value);
+            }
+            if ($xss == 'y') {
+                    $header_value = $prefs['http_header_xss_protection_value'];
+                    header('X-XSS-Protection: ' . $header_value);
+            }
+            if ($content_type_options == 'y') {
+                header('X-Content-Type-Options: nosniff');
+            }
+            if ($access_control_allow_credentials === 'y') {
+                header('Access-Control-Allow-Credentials: true');
+            }
+            if ($access_control_allow_methods === 'y') {
+                $header_value = trim($prefs['http_header_access_control_allow_methods_value']);
+                if ($access_control_allow_credentials === 'y' && $header_value === '*') {
+                    Feedback::error(tr("CORS configuration error: Wildcard (*) is not allowed for Access-Control-Allow-Methods when http_header_access_control_allow_credential is enabled"));
+                    header_remove('Access-Control-Allow-Methods');
+                } else {
+                    header('Access-Control-Allow-Methods: ' . $header_value);
+                }
+            }
+            if ($access_control_allow_headers === 'y') {
+                $headers_value = trim($prefs['http_header_access_control_allow_headers_value']);
+                if ($access_control_allow_credentials === 'y' && $headers_value === '*') {
+                    Feedback::error(tr("CORS configuration error: Wildcard (*) is not allowed for Access-Control-Allow-Headers when Access-Control-Allow-Credentials is enabled."));
+                    header_remove('Access-Control-Allow-Headers');
+                } else {
+                    header('Access-Control-Allow-Headers: ' . $headers_value);
+                }
+            }
+            if ($cross_origin_embedder_policy === 'y') {
+                switch (trim($prefs['http_header_cross_origin_embedder_policy_value'])) {
+                    case 'require-corp':
+                        header('Cross-Origin-Embedder-Policy: require-corp');
+                        break;
+                    case 'credentialless':
+                        header('Cross-Origin-Embedder-Policy: credentialless');
+                        break;
+                    case 'unsafe-none':
+                        header('Cross-Origin-Embedder-Policy: unsafe-none');
+                        break;
+                    default:
+                        break;
+                }
+            }
+            if ($cross_origin_resource_policy === 'y') {
+                switch (trim($prefs['http_header_cross_origin_resource_policy_value'])) {
+                    case 'same-origin':
+                        header('Cross-Origin-Resource-Policy: same-origin');
+                        break;
+                    case 'same-site':
+                        header('Cross-Origin-Resource-Policy: same-site');
+                        break;
+                    case 'cross-origin':
+                        header('Cross-Origin-Resource-Policy: cross-origin');
+                        break;
+                    default:
+                        break;
+                }
+            }
+            if ($cross_origin_opener_policy === 'y') {
+                switch (trim($prefs['http_header_cross_origin_opener_policy_value'])) {
+                    case 'same-origin':
+                        header('Cross-Origin-Opener-Policy: same-origin');
+                        break;
+                    case 'same-origin-allow-popups':
+                        header('Cross-Origin-Opener-Policy: same-origin-allow-popups');
+                        break;
+                    case 'same-origin-plus-coep':
+                        header('Cross-Origin-Opener-Policy: same-origin-plus-coep');
+                        break;
+                    case 'unsafe-none':
+                        header('Cross-Origin-Opener-Policy: unsafe-none');
+                        break;
+                    default:
+                        break;
+                }
+            }
+            if ($content_security_policy == 'y') {
+                $header_value = trim($prefs['http_header_content_security_policy_value']);
+                if ($header_value !== '') {
+                    header('Content-Security-Policy: ' . $header_value);
+                }
+            }
+
+            if ($strict_transport_security == 'y') {
+                $header_value = trim($prefs['http_header_strict_transport_security_value']);
+                if ($header_value !== '') {
+                    header('Strict-Transport-Security: ' . $header_value);
+                }
+            }
+
+            if ($public_key_pins == 'y') {
+                $header_value = trim($prefs['http_header_public_key_pins_value']);
+                if ($header_value !== '') {
+                    header('Public-Key-Pins: ' . $header_value);
+                }
+            }
+
+            if ($referrer_policy === 'y') {
+                $header_value = trim($prefs['http_header_referrer_policy_value']);
+                if ($header_value !== '') {
+                    header('Referrer-Policy: ' . $header_value);
+                }
+            }
+
+            if ($permitted_cross_domain_policies === 'y') {
+                $header_value = trim($prefs['http_header_permitted_cross_domain_policies_value']);
+                if ($header_value !== '') {
+                    header('X-Permitted-Cross-Domain-Policies: ' . $header_value);
+                }
+            }
+        }
+    }
+
     /**
      * Add a js url from this tiki instance to top priority load order.
      * These are usually dynamic created js scripts for configuration, module settings etc.


=====================================
tiki-login.php
=====================================
@@ -40,6 +40,9 @@ if (empty($_POST['user'])) {
 require_once('tiki-setup.php');
 global $prefs;
 
+$headerlib = TikiLib::lib('header');
+$headerlib->addSecurityHeaders();
+
 // Refresh not logged in since 30 days user's accounts list
 $userlib = TikiLib::lib('user');
 $userlib->refresh_locked_users_list();



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/4f1a215dff4e5a85180c4ffcce5962461d49767a

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/4f1a215dff4e5a85180c4ffcce5962461d49767a
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.