diff --git a/include/class.config.php b/include/class.config.php
index 32f5ca702feb2855e52d437ea8d4bbb625354ded..0f046d345ec939b647f68242be329730832b4267 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -429,6 +429,10 @@ class OsticketConfig extends Config {
         return $this->get('enable_richtext');
     }
 
+    function getAllowIframes() {
+        return str_replace(array(', ', ','), array(' ', ' '), $this->get('allow_iframes')) ?: 'self';
+    }
+
     function isAvatarsEnabled() {
         return $this->get('enable_avatars');
     }
@@ -1121,6 +1125,7 @@ class OsticketConfig extends Config {
         $f['helpdesk_title']=array('type'=>'string',   'required'=>1, 'error'=>__('Helpdesk title is required'));
         $f['default_dept_id']=array('type'=>'int',   'required'=>1, 'error'=>__('Default Department is required'));
         $f['autolock_minutes']=array('type'=>'int',   'required'=>1, 'error'=>__('Enter lock time in minutes'));
+        $f['allow_iframes']=array('type'=>'cs-domain',   'required'=>0, 'error'=>__('Enter comma separated list of domains'));
         //Date & Time Options
         $f['time_format']=array('type'=>'string',   'required'=>1, 'error'=>__('Time format is required'));
         $f['date_format']=array('type'=>'string',   'required'=>1, 'error'=>__('Date format is required'));
@@ -1179,6 +1184,7 @@ class OsticketConfig extends Config {
             'enable_avatars' => isset($vars['enable_avatars']) ? 1 : 0,
             'enable_richtext' => isset($vars['enable_richtext']) ? 1 : 0,
             'files_req_auth' => isset($vars['files_req_auth']) ? 1 : 0,
+            'allow_iframes' => Format::sanitize($vars['allow_iframes']),
         ));
     }
 
diff --git a/include/class.validator.php b/include/class.validator.php
index 14be7ccaf005423bf34c395aa375c04227e9671e..388d00ac929ccdc45a78325cae549329db761280 100644
--- a/include/class.validator.php
+++ b/include/class.validator.php
@@ -123,6 +123,14 @@ class Validator {
                 if(!is_numeric($this->input[$k]) || (strlen($this->input[$k])!=5))
                     $this->errors[$k]=$field['error'];
                 break;
+            case 'cs-domain': // Comma separated list of domains
+                if($values=explode(',', $this->input[$k]))
+                    foreach($values as $v)
+                        if(!preg_match_all(
+                                '/^(https?:\/\/)?((\*\.|\w+\.)?[\w-]+(\.[a-zA-Z]+)?(:([0-9]+|\*))?)+$/',
+                                ltrim($v)))
+                            $this->errors[$k]=$field['error'];
+                break;
             default://If param type is not set...or handle..error out...
                 $this->errors[$k]=$field['error'].' '.__('(type not set)');
             endswitch;
diff --git a/include/client/header.inc.php b/include/client/header.inc.php
index 0d66f67537f3b8ac5c7e8cd2336281ad5bcdf82e..8c248b158d2631a577b1bbe4835961fd26228893 100644
--- a/include/client/header.inc.php
+++ b/include/client/header.inc.php
@@ -6,7 +6,7 @@ $signin_url = ROOT_PATH . "login.php"
 $signout_url = ROOT_PATH . "logout.php?auth=".$ost->getLinkToken();
 
 header("Content-Type: text/html; charset=UTF-8");
-header("X-Frame-Options: SAMEORIGIN");
+header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';");
 if (($lang = Internationalization::getCurrentLanguage())) {
     $langs = array_unique(array($lang, $cfg->getPrimaryLanguage()));
     $langs = Internationalization::rfc1766($langs);
diff --git a/include/i18n/en_US/help/tips/settings.system.yaml b/include/i18n/en_US/help/tips/settings.system.yaml
index 28b069775ba6e2a8b8eafc4c93ae94fc96a002e6..56e39e2bf7481257be419dd20ef45b4bf246ef6b 100644
--- a/include/i18n/en_US/help/tips/settings.system.yaml
+++ b/include/i18n/en_US/help/tips/settings.system.yaml
@@ -93,6 +93,20 @@ collision_avoidance:
         <br><br>
         Enter <span class="doc-desc-opt">0</span> to disable the lockout feature.
 
+allow_iframes:
+    title: Allow iFrames
+    content: >
+        Enter comma separated list of domains for the system to be framed
+        in. If left empty, the system will default to 'self'. This accepts
+        domain wildcards, HTTP/HTTPS URL scheme, and port numbers.
+        <br><br>
+        <b>Example:</b>
+        <br>
+        https://domain.tld, sub.domain.tld:443, http://*.domain.tld
+    links:
+      - title: Syntax Information (host-source)
+        href: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors#Sources"
+
 # Date and time options
 date_time_options:
     title: Date &amp; Time Options
diff --git a/include/staff/header.inc.php b/include/staff/header.inc.php
index ebd31bfb05bb1fa216cdd4a60d12cee1fd8c6247..4de7ccd8fadec4164008912e31e336aba89988ba 100644
--- a/include/staff/header.inc.php
+++ b/include/staff/header.inc.php
@@ -1,6 +1,6 @@
 <?php
 header("Content-Type: text/html; charset=UTF-8");
-header("X-Frame-Options: SAMEORIGIN");
+header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';");
 
 $title = ($ost && ($title=$ost->getPageTitle()))
     ? $title : ('osTicket :: '.__('Staff Control Panel'));
diff --git a/include/staff/login.header.php b/include/staff/login.header.php
index 2a4fcdbb6d234d0ffa434b838afcc065ec808e38..e1b1b3a5a242a32e50690713beda7615eae3a039 100644
--- a/include/staff/login.header.php
+++ b/include/staff/login.header.php
@@ -1,6 +1,6 @@
 <?php
 defined('OSTSCPINC') or die('Invalid path');
-header("X-Frame-Options: SAMEORIGIN");
+header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';");
 ?>
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
diff --git a/include/staff/settings-system.inc.php b/include/staff/settings-system.inc.php
index 22502ed5e54dde3ae77d17c0c8aa15f4c7204b4b..37370df97eb22f4c450c41815ce13e2e08baef69 100644
--- a/include/staff/settings-system.inc.php
+++ b/include/staff/settings-system.inc.php
@@ -131,6 +131,13 @@ $gmtime = Misc::gmtime();
                 <i class="help-tip icon-question-sign" href="#enable_richtext"></i>
             </td>
         </tr>
+        <tr>
+            <td><?php echo __('Allow iFrames'); ?>:</td>
+            <td><input type="text" size="40" name="allow_iframes" value="<?php echo $config['allow_iframes']; ?>">
+                &nbsp;<font class="error">&nbsp;<?php echo $errors['allow_iframes']; ?></font>
+                <i class="help-tip icon-question-sign" href="#allow_iframes"></i>
+            </td>
+        </tr>
         <tr>
             <th colspan="2">
                 <em><b><?php echo __('Date and Time Options'); ?></b>&nbsp;
diff --git a/setup/inc/header.inc.php b/setup/inc/header.inc.php
index 57ceade2e12bad159d811881d8f8eea2022c22f7..0bfc0ec85edaa6b44a650a92ca7d00ff3b8d140d 100644
--- a/setup/inc/header.inc.php
+++ b/setup/inc/header.inc.php
@@ -1,4 +1,6 @@
-<?php header("X-Frame-Options: SAMEORIGIN"); ?>
+<?php
+header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';");
+?>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
     "http://www.w3.org/TR/html4/loose.dtd">
 <html <?php