Is Web for Telegram safe?

Medium risk

Web for Telegram is medium risk. Web for Telegram asks jitt.wwevents.fun for RemoteMessage entries and renders the first MESSAGE string via toastr before DOMPurify applies. Toastr has HTML escaping disabled, so server HTML can enter the Telegram Web page.

WWEventsv6.4Chrome Web Store
45Risk

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-829
SourceAI SANDBOX

Remote HTML appears in Telegram Web before sanitization

Web for Telegram asks jitt.wwevents.fun for RemoteMessage entries and renders the first MESSAGE string via toastr before DOMPurify applies.

Toastr has HTML escaping disabled, so server HTML can enter the Telegram Web page.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You open Telegram Web while the extension's remote-message flow is enabled.

The content script waits briefly, then asks the service worker for remote message content.

The extension did this

The extension can render the first server-provided message as HTML inside the Telegram Web page.

Later messages use DOMPurify when the next button is clicked, but the first display is passed directly to toastr.info.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://jitt.wwevents.fun/wwevents-remote/api/v1/RemoteMessage?app=ChromeGen2eric
03EvidenceNETWORK CAPTURE
Captured request
GEThttps://jitt.wwevents.fun/wwevents-remote/api/v1/RemoteMessage?app=ChromeNewsGen2eric
04EvidenceFIELD TABLE
Concrete fields and parameters in the remote-message path
FieldValueWhy it matters
Remote message host
jitt.wwevents.funThis is the server your browser contacts before the message is shown in Telegram Web.
Application selector
ChromeGen2ericThis value tells the server which message set the extension is requesting.
Message field
jsonData[0].data[i].MESSAGEThis response field is the content that can become part of the Telegram Web page.
Toast element
#remoteMessageToastr .toast-messageThis is where the first message is placed after it is received.
05EvidenceCODE COMPARE
The code that does this

Remote message fetches flow into an unsanitized first toast render

What it actually does
Service worker fetches RemoteMessage recordseventPage.js
switch (message.remoteMessage) {
        case "remoteMessage":
			chrome.storage.sync.get("remoteMessageDate", async function (data) {
				//console.log("remoteMessageDate", data['remoteMessageDate']);
                var today = new Date();
                var serializedToday = JSON.stringify(today);
                if (data['remoteMessageDate'] == null) {
                    chrome.storage.sync.set({ 'remoteMessageDate': serializedToday }, function () { });
					chrome.storage.sync.set({ 'remoteMessageSID': "" }, function () { });
					sendResponse({ remoteMessage: "" });
                } else {
					var savedDate = new Date(JSON.parse(data['remoteMessageDate']));
                    var datesDiff = Date.dateDiff('d', savedDate, today);
					if (await getObjectFromLocalStorage('showToasterOnStartup1')){
						fetch('https://jitt.wwevents.fun/wwevents-remote/api/v1/RemoteMessage?app=ChromeGen2eric')
						.then(response => response.json()).then((result) => {
							
								var jsonData = result;
								if(jsonData != null && jsonData.length > 0 && jsonData[0].result == "success"){
									var responsestring = [];
									for (var i = 0; i < jsonData[0].data.length; i++)
									{
										responsestring.push(jsonData[0].data[i].MESSAGE);
									}
									chrome.storage.sync.get("remoteMessageSID", function (data) {
										var storedId = data['remoteMessageSID'];

										if((storedId.toUpperCase() != jsonData[0].data[0].SID.toUpperCase() || jsonData[0].data[0].DURATION.toUpperCase() == "Perm".toUpperCase()) && (datesDiff >= 1)){ //Add datesDiff >= 6
											chrome.storage.sync.set({ 'remoteMessageSID': jsonData[0].data[0].SID }, function () { });
											sendResponse({ remoteMessage: responsestring });
										} else {
											sendResponse({ remoteMessage: "" });
										}
										chrome.storage.local.set({ 'showToasterOnStartup1': false }, function () { });
									});
								}
							
						}).catch(error => {
							console.log(error);
						});
					}
				}
			});
			return true; //so i can use sendResponse later
            break;
        default:
            break;
    }

	switch (message.informationNews) {
        case "informationNews":
			fetch('https://jitt.wwevents.fun/wwevents-remote/api/v1/RemoteMessage?app=ChromeNewsGen2eric')
			.then(response => response.json()).then((result) => {
					var jsonData = result;
					if(jsonData != null && jsonData.length > 0 && jsonData[0].result == "success"){
						var responsestring = [];
						for (var i = 0; i < jsonData[0].data.length; i++)
						{
							responsestring.push(jsonData[0].data[i].MESSAGE);
						}
						sendResponse({ informationNews: responsestring });
					}
			}).catch(error => {
				console.log(error);
			});
			return true; //so i can use sendResponse later
            break;
        default:
            break;
    }
Content script renders the first returned messagemyScript.js
/* Show a fixed Toast for remote messages */
			setTimeout(function(){
				if(toastrSemaphoreOnce){
					chrome.runtime.sendMessage({ remoteMessage: "remoteMessage" }, function (response) {
						if(response == undefined || Object.keys(response).length == 0) return;
						if (response.remoteMessage != "") {
							toastrSemaphoreOnce = false;
							remoteMessage = response.remoteMessage;
							toastr.options = { "positionClass": "toast-top-full-width", "timeOut": "0", "progressBar": "true", "closeButton" : "true", "extendedTimeOut": "0", "tapToDismiss" : false };
							var t = toastr.info(remoteMessage[remoteMessageIndex]);
							t.attr('id', 'remoteMessageToastr');
							$('#remoteMessageToastr').append('<span id="remoteMessageSpan" style="font-weight: 600;opacity: 0.75;top: 0.4em;left: 0.4em;position: absolute;">'+ (remoteMessageIndex + 1) + '/'+ remoteMessage.length +'</span>');
							manageRemoteMessage();
						}
					});
				}
			}, 2100);
News menu uses the same first-render pattern, while next uses DOMPurifymyScript.js
function clickInformationNews(){
			chrome.runtime.sendMessage({ informationNews: "informationNews" }, function (response) {
				if(response == undefined || Object.keys(response).length == 0) return;
				if (response.informationNews != null) {
					remoteMessage = response.informationNews;
					toastr.options = { "positionClass": "toast-top-full-width", "timeOut": "0", "progressBar": "true", "closeButton" : "true", "extendedTimeOut": "0", "tapToDismiss" : false };
					var t = toastr.info(remoteMessage[remoteMessageIndex]);
					t.attr('id', 'remoteMessageToastr');
					$('#remoteMessageToastr').append('<span id="remoteMessageSpan" style="font-weight: 600;opacity: 0.75;top: 0.4em;left: 0.4em;position: absolute;">'+ (remoteMessageIndex + 1) + '/'+ remoteMessage.length +'</span>');
					manageRemoteMessage();
				}
			});
		}
		
		function manageRemoteMessage(){
			$('#remoteMessageToastr .toast-message button').css({'background' : '#E5E5E5', 'color':'black'});
			document.querySelector('#remoteMessageToastr #surpriseNextBtn').addEventListener('click', function () { 
				remoteMessageIndex++;
				if(remoteMessageIndex >= remoteMessage.length) remoteMessageIndex = 0;
				$('#remoteMessageToastr .toast-message').html(DOMPurify.sanitize(remoteMessage[remoteMessageIndex], {ADD_ATTR: ['target']}));
				$('#remoteMessageSpan').text((remoteMessageIndex + 1) + '/'+ remoteMessage.length);
				manageRemoteMessage();
			});
			document.querySelector('#remoteMessageToastr #surpriseBtn').addEventListener('click', function () { $('#remoteMessageToastr').fadeOut("slow", function () { $('#remoteMessageToastr').remove(); }); });
		}
Toastr defaults leave message HTML unescapedjs/toastr/toastr.min.js
function p() {
        return {
          tapToDismiss: !0,
          toastClass: "toast",
          containerId: "toast-container",
          debug: !1,
          showMethod: "fadeIn",
          showDuration: 300,
          showEasing: "swing",
          onShown: void 0,
          hideMethod: "fadeOut",
          hideDuration: 1e3,
          hideEasing: "swing",
          onHidden: void 0,
          closeMethod: !1,
          closeDuration: !1,
          closeEasing: !1,
          closeOnHover: !0,
          extendedTimeOut: 1e3,
          iconClasses: {
            error: "toast-error",
            info: "toast-info",
            success: "toast-success",
            warning: "toast-warning"
          },
          iconClass: "toast-info",
          positionClass: "toast-top-right",
          timeOut: 5e3,
          titleClass: "toast-title",
          messageClass: "toast-message",
          escapeHtml: !1,
          target: "body",
          closeHtml: '<button type="button">&times;</button>',
          closeClass: "toast-close-button",
          newestOnTop: !0,
          preventDuplicates: !1,
          progressBar: !1,
          progressClass: "toast-progress",
          rtl: !1
        }
      }

function d() {
          if (t.message) {
            var e = t.message;
            E.escapeHtml && (e = o(t.message)), B.append(e).addClass(E.messageClass), I.append(B)
          }
        }
06EvidenceTHIRD PARTY LIST
Remote host involved in the render path
  • jitt.wwevents.fun

    Receives RemoteMessage GET requests and returns MESSAGE strings that the extension passes into Telegram Web toasts.

Updated 17 September 2026kjnmdomccekpkjomjhapnilfmeiglkid