diff --git a/extension/Classes/Core/AbstractBuildForm.php b/extension/Classes/Core/AbstractBuildForm.php
index 7e950bb2941a347a531249d4ee36f19f494a6b92..ecb21a67bd421915b378d1cc3563d8964c627021 100644
--- a/extension/Classes/Core/AbstractBuildForm.php
+++ b/extension/Classes/Core/AbstractBuildForm.php
@@ -9,6 +9,7 @@
 namespace IMATHUZH\Qfq\Core;
 
 use IMATHUZH\Qfq\Core\Database\Database;
+use IMATHUZH\Qfq\Core\Form\Chat;
 use IMATHUZH\Qfq\Core\Form\Checkbox;
 use IMATHUZH\Qfq\Core\Form\FormAsFile;
 use IMATHUZH\Qfq\Core\Form\TypeAhead;
@@ -3135,14 +3136,18 @@ abstract class AbstractBuildForm {
      * @throws \UserReportException
      */
     public function buildChat(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
-        $chatConfig = Support::createChatConfig($formElement, $this->store);
+        $chatConfig = Chat::createChatConfig($formElement, $this->store);
         $chatConfigJson = json_encode($chatConfig, JSON_UNESCAPED_SLASHES);
         $websocketUrl = $this->store::getVar(SYSTEM_WEBSOCKET_URL, STORE_SYSTEM) ?? '';
+        $placeholder = '';
 
         if ($chatConfig['pIdCreator'] == 0 || empty($chatConfig['pIdCreator']) || empty($chatConfig['username'])) {
             throw new \UserFormException("Missing or empty pIdCreator/username parameter.", ERROR_MISSING_CHAT_DATA);
         }
 
+        // Set readonly if grIdGroupList is set but is not found in grIdCreatorGroupList
+        Chat::checkAccess($chatConfig['grIdGroupList'], $chatConfig['grIdCreatorGroupList'], $formElement, $placeholder);
+
         // Part 1: Build fieldset for chat
         $fieldsetAttribute = '';
         $fieldsetAttribute .= Support::doAttribute('id', $formElement[FE_HTML_ID]);
@@ -3152,6 +3157,8 @@ abstract class AbstractBuildForm {
         $fieldsetAttribute .= Support::doAttribute('class', $formElement[F_FE_FIELDSET_CLASS] . ' qfq-chat');
         $fieldsetAttribute .= Support::doAttribute(ATTRIBUTE_DATA_REFERENCE, $formElement[FE_DATA_REFERENCE]);
 
+        $fieldsetAttribute .= HelperFormElement::getAttributeFeMode($formElement[FE_MODE], false);
+
         $chatFieldsetStart = '<fieldset ' . $fieldsetAttribute . '>';
 
         if ($formElement[FE_LABEL] !== '') {
@@ -3176,7 +3183,7 @@ abstract class AbstractBuildForm {
                 }, ['id', 'rId', 'pIdCreator', 'message', 'username', 'created']))
                 . ' FROM ' . $chatConfig['tableName']
                 . ' WHERE ' . $dbColumnNames['rId'] . ' = ? AND ('
-                . '(LENGTH(?) = 0 AND ' . $dbColumnNames['pIdCreator'] . ' = ?) '
+                . '(LENGTH(?) = 0 AND ' . $dbColumnNames['pIdCreator'] . ' = ? AND ' . $dbColumnNames['grIdGroupList'] . ' = "") '
                 . 'OR (LENGTH(?) > 0 AND (find_match_in_lists('. $dbColumnNames['grIdGroupList'] . ', ?) = 1 '
                 . 'AND find_match_in_lists(' . $dbColumnNames['grIdGroupList'] . ', ?)))) '
                 . 'ORDER BY ' . $dbColumnNames['created'];
@@ -3260,7 +3267,17 @@ abstract class AbstractBuildForm {
             $inputAttribute .= Support::doAttribute('maxlength', $formElement[FE_MAX_LENGTH], false);
         }
 
-        $inputHtml = "$inputHtml $inputAttribute>$textarea";
+        if (empty($formElement[F_FE_DATA_MATCH_ERROR])) {
+            $formElement[F_FE_DATA_REQUIRED_ERROR] = F_FE_DATA_REQUIRED_ERROR_DEFAULT;
+        }
+
+        if ($formElement[FE_MODE] == FE_MODE_REQUIRED) {
+            $inputAttribute .= Support::doAttribute(F_FE_DATA_REQUIRED_ERROR, $formElement[F_FE_DATA_REQUIRED_ERROR]);
+        }
+
+        $inputAttribute .= HelperFormElement::getAttributeFeMode($formElement[FE_MODE], false);
+
+        $inputHtml = "$inputHtml $placeholder $inputAttribute>$textarea";
 
         $wrapSetupClass = $this->wrap[WRAP_SETUP_ELEMENT][WRAP_SETUP_CLASS] ?? '';
 
diff --git a/extension/Classes/Core/Constants.php b/extension/Classes/Core/Constants.php
index de0100ab1da04bd5053c6fefecc8844ce95fa62b..f498003662384bfebcd7b9807b3a94000f643ee4 100644
--- a/extension/Classes/Core/Constants.php
+++ b/extension/Classes/Core/Constants.php
@@ -384,6 +384,7 @@ const ERROR_MSG_TOO_BIG = "** Data removed: too big **";
 
 // Chat
 const ERROR_MISSING_CHAT_DATA = 3200;
+const ERROR_INVALID_CHAT_DATA = 3201;
 
 //
 // Store Names: Identifier
diff --git a/extension/Classes/Core/Form/Chat.php b/extension/Classes/Core/Form/Chat.php
index d8552af82f1e1439680119a09f9e9f012d2b4836..b707ee69e1dc31edcb7318725da0e1e1e3b54180 100644
--- a/extension/Classes/Core/Form/Chat.php
+++ b/extension/Classes/Core/Form/Chat.php
@@ -10,7 +10,10 @@ namespace IMATHUZH\Qfq\Core\Form;
 
 
 use IMATHUZH\Qfq\Core\Helper\Logger;
+use IMATHUZH\Qfq\Core\Helper\OnArray;
+use IMATHUZH\Qfq\Core\Helper\OnString;
 use IMATHUZH\Qfq\Core\Helper\Path;
+use IMATHUZH\Qfq\Core\Store\Store;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
@@ -136,6 +139,81 @@ class Chat implements MessageComponentInterface {
         return $chatJson;
     }
 
+    /**
+     * @param array $formElement
+     * @param Store $store
+     * @return array
+     * @throws \CodeException
+     * @throws \DbException
+     * @throws \UserFormException
+     * @throws \UserReportException
+     */
+    public static function createChatConfig(array $formElement, Store $store) {
+        $chatConfig = array();
+
+        // [apId:rId,pId:pIdCreator,grIdStatus:xGrIdStatus,grIdGroup:grIdGroupList,...]
+        $chatConfig['dbColumnNames'] = array (
+            'id' => 'id',
+            'rId' => 'rId',
+            'pIdCreator' => 'pIdCreator',
+            'xGrIdStatus' => 'xGrIdStatus',
+            'grIdGroupList' => 'grIdGroupList',
+            'message' => 'message',
+            'username' => 'username',
+            'created' => 'created'
+
+        );
+
+        $chatConfig['columnMap'] = $formElement['columnMap'] ?? '[]';
+
+        OnArray::mapColumns($chatConfig['dbColumnNames'], $chatConfig['columnMap']);
+        $chatConfig['tableName'] = $formElement['tableName'] ?? 'Chat';
+
+        $chatConfig['recordId'] = $formElement['recordId'] ?? $store::getVar(SIP_RECORD_ID, STORE_SIP . STORE_ZERO);
+        $chatConfig['pIdCreator'] = $formElement['pIdCreator'] ?? 0;
+        $chatConfig['username'] = $formElement['username'] ?? '';
+        $chatConfig['grIdCreatorGroupList'] = $formElement['grIdCreatorGroupList'] ?? '';
+        $chatConfig['grIdGroupList'] = $formElement['grIdGroupList'] ?? '';
+        $chatConfig['xGrIdStatus'] = $formElement['xGrIdStatus'] ?? 0;
+        $chatConfig['disabledFlag'] = $formElement['disabledFlag'] ?? '';
+
+        $chatConfig['formParam'] = $formElement['formParam'] ?? '';
+        $chatConfig['customJson'] = $formElement['customJson'] ?? '';
+        $chatConfig['threadId'] = $formElement['threadId'] ?? 0;
+        $chatConfig['submitReference'] = $formElement['submitReference'] ?? 0;
+
+        return $chatConfig;
+    }
+
+    public static function existsInGroup($groupList1, $groupList2): bool {
+        $bool = false;
+
+        // Convert strings to arrays
+        $groupArray1 = explode(",", $groupList1);
+        $groupArray2 = explode(",", $groupList2);
+
+        $matchingIds = array_intersect($groupArray1, $groupArray2);
+
+        if (!empty($matchingIds)) {
+            $bool = true;
+        }
+
+        return $bool;
+    }
+
+    public static function checkAccess($groupList1, $groupList2, &$fe, &$placeholder = ''): void {
+        if (!empty($groupList1)) {
+            if (!OnString::isValidNumberList($groupList1) || !OnString::isValidNumberList($groupList2)) {
+                throw new \UserFormException("Invalid grIdGroupList or grIdCreatorGroupList parameter.", ERROR_INVALID_CHAT_DATA);
+            }
+
+            if (!Chat::existsInGroup($groupList1, $groupList2)) {
+                $placeholder = 'placeholder="No access for this chat."';
+                $fe[FE_MODE] = $fe[FE_MODE] === FE_MODE_HIDDEN ? $fe[FE_MODE] : FE_MODE_READONLY;
+            }
+        }
+    }
+
     private function refreshRecordId($from, $data): void {
         if ($this->clientInfo[$from->resourceId]['recordId'] == 0 && $data->rId) {
             $this->clientInfo[$from->resourceId]['recordId'] = $data->rId;
diff --git a/extension/Classes/Core/Helper/OnString.php b/extension/Classes/Core/Helper/OnString.php
index 87c099be40a5747bcaa64576a117903e7b74ba97..fcdba5cd5e10e19a696b3f40b9150d940ed96ac2 100644
--- a/extension/Classes/Core/Helper/OnString.php
+++ b/extension/Classes/Core/Helper/OnString.php
@@ -865,5 +865,10 @@ class OnString {
 
         return $arrNew;
     }
+
+    public static function isValidNumberList($string): bool {
+        // Regex pattern: Empty string or numbers, commas, and optional spaces
+        return preg_match('/^[\d,\s]*$/', $string) || $string === "";
+    }
 }
 
diff --git a/extension/Classes/Core/Helper/Support.php b/extension/Classes/Core/Helper/Support.php
index 8cc2b874f349b17b21d7faa2775da15552a87b75..4dbcbc2f731b6f795ba2eef7f436bb0b12ff699d 100644
--- a/extension/Classes/Core/Helper/Support.php
+++ b/extension/Classes/Core/Helper/Support.php
@@ -1714,50 +1714,4 @@ class Support {
             throw new \CodeException("Invalid wget configuration. Maybe wget command is incorrect or not supported.", ERROR_INVALID_WGET_CMD);
         }
     }
-
-    /**
-     * @param array $formElement
-     * @param Store $store
-     * @return array
-     * @throws \CodeException
-     * @throws \DbException
-     * @throws \UserFormException
-     * @throws \UserReportException
-     */
-    public static function createChatConfig(array $formElement, Store $store) {
-        $chatConfig = array();
-
-        // [apId:rId,pId:pIdCreator,grIdStatus:xGrIdStatus,grIdGroup:grIdGroupList,...]
-        $chatConfig['dbColumnNames'] = array (
-            'id' => 'id',
-            'rId' => 'rId',
-            'pIdCreator' => 'pIdCreator',
-            'xGrIdStatus' => 'xGrIdStatus',
-            'grIdGroupList' => 'grIdGroupList',
-            'message' => 'message',
-            'username' => 'username',
-            'created' => 'created'
-
-        );
-
-        $chatConfig['columnMap'] = $formElement['columnMap'] ?? '[]';
-
-        OnArray::mapColumns($chatConfig['dbColumnNames'], $chatConfig['columnMap']);
-        $chatConfig['tableName'] = $formElement['tableName'] ?? 'Chat';
-
-        $chatConfig['recordId'] = $formElement['recordId'] ?? $store::getVar(SIP_RECORD_ID, STORE_SIP . STORE_ZERO);
-        $chatConfig['pIdCreator'] = $formElement['pIdCreator'] ?? 0;
-        $chatConfig['username'] = $formElement['username'] ?? '';
-        $chatConfig['grIdCreatorGroupList'] = $formElement['grIdCreatorGroupList'] ?? '';
-        $chatConfig['grIdGroupList'] = $formElement['grIdGroupList'] ?? '';
-        $chatConfig['xGrIdStatus'] = $formElement['xGrIdStatus'] ?? 0;
-        $chatConfig['disabledFlag'] = $formElement['disabledFlag'] ?? '';
-
-        $chatConfig['formParam'] = $formElement['formParam'] ?? '';
-        $chatConfig['customJson'] = $formElement['customJson'] ?? '';
-        $chatConfig['threadId'] = $formElement['threadId'] ?? 0;
-        $chatConfig['submitReference'] = $formElement['submitReference'] ?? 0;
-
-        return $chatConfig;
-    }
 }
\ No newline at end of file
diff --git a/extension/Classes/Core/Save.php b/extension/Classes/Core/Save.php
index 04ba93cac3fa4bae517fe6694460e07ac45dbf7c..1eaf599fd8778ba7dc4ab496f2ff451a1f1687c7 100644
--- a/extension/Classes/Core/Save.php
+++ b/extension/Classes/Core/Save.php
@@ -11,6 +11,7 @@ namespace IMATHUZH\Qfq\Core;
 use HTMLPurifier;
 use IMATHUZH\Qfq\Core\Database\Database;
 use IMATHUZH\Qfq\Core\Exception\Thrower;
+use IMATHUZH\Qfq\Core\Form\Chat;
 use IMATHUZH\Qfq\Core\Form\FormAction;
 use IMATHUZH\Qfq\Core\Helper\EncryptDecrypt;
 use IMATHUZH\Qfq\Core\Helper\HelperFile;
@@ -417,8 +418,15 @@ class Save {
         $feColumnTypes = array();
         $feColumnTypeChat = array();
         foreach ($this->feSpecNative as $fe) {
-            if ($fe[FE_TYPE] === FE_TYPE_CHAT && $formValues[$fe[FE_NAME]] !== '') {
+            if ($fe[FE_TYPE] === FE_TYPE_CHAT && isset($formValues[$fe[FE_NAME]]) && $formValues[$fe[FE_NAME]] !== '') {
                 $feColumnTypeChat[$fe[FE_NAME]][FE_VALUE] = $formValues[$fe[FE_NAME]];
+
+                // Check for access and change fe mode dynamically
+                $groupList1 = isset($fe['grIdGroupList']) ? $this->evaluate->parse($fe['grIdGroupList'], ROW_REGULAR) : '';
+                $groupList2 = isset($fe['grIdCreatorGroupList']) ? $this->evaluate->parse($fe['grIdCreatorGroupList'], ROW_REGULAR) : '';
+                $fe['grIdGroupList'] = $groupList1;
+                Chat::checkAccess($groupList1, $groupList2, $fe);
+
                 $feColumnTypeChat[$fe[FE_NAME]]['fe'] = $fe;
                 continue;
             }
@@ -537,12 +545,16 @@ class Save {
         // Handle save for FE type chat
         if (!empty($feColumnTypeChat)) {
             foreach ($feColumnTypeChat as $fe => $data) {
-                $chatConfig = Support::createChatConfig($data['fe'], $this->store);
+                if ($data['fe'][FE_MODE] === FE_MODE_HIDDEN || $data['fe'][FE_MODE] === FE_MODE_READONLY) {
+                    continue;
+                }
+
+                $chatConfig = Chat::createChatConfig($data['fe'], $this->store);
                 $chatParams = [
                     'recordId' => $chatConfig['recordId'] != 0 ? $chatConfig['recordId'] : $recordId,
                     'pIdCreator' => $this->evaluate->parse($chatConfig['pIdCreator'], ROW_REGULAR),
                     'xGrIdStatus' => $this->evaluate->parse($chatConfig['xGrIdStatus'], ROW_REGULAR),
-                    'grIdGroupList' => $this->evaluate->parse($chatConfig['grIdGroupList'], ROW_REGULAR),
+                    'grIdGroupList' => $chatConfig['grIdGroupList'],
                     'username' => $this->evaluate->parse($chatConfig['username'], ROW_REGULAR)
                 ];
 
diff --git a/javascript/src/Helper/qfqChat.js b/javascript/src/Helper/qfqChat.js
index a77a056e606e50d09a4413f8e8436ffb75d0d043..64a2187283b5e22614e0fe19a983f80db78b79ca 100644
--- a/javascript/src/Helper/qfqChat.js
+++ b/javascript/src/Helper/qfqChat.js
@@ -292,6 +292,7 @@ QfqNS.Helper = QfqNS.Helper || {};
         var messageIds = Array.from(element.querySelectorAll('.chat-messages div[data-message-id]')).map(el => parseInt(el.getAttribute('data-message-id'), 10));
         var messageIdsSet = new Set(messageIds);
         let messageElement = element.querySelector('.chat-messages');
+        let noMessageBanner = element.querySelector('.chat-no-message');
 
         for (var key in chatItem) {
             if (chatItem.hasOwnProperty(key) && !messageIdsSet.has(parseInt(key, 10))) {
@@ -300,6 +301,11 @@ QfqNS.Helper = QfqNS.Helper || {};
                 // First clean input field
                 element.nextElementSibling.value = '';
 
+                // Check if no message banner exists, clear it
+                if (noMessageBanner !== undefined && noMessageBanner !== null && noMessageBanner.style.display !== 'none') {
+                    noMessageBanner.style.display = 'none';
+                }
+
                 // append new container to existing chat
                 messageElement.appendChild(chatContainerElement);
             }