Is All-Inclusive CRM safe?
All-Inclusive CRM executes JavaScript returned by allinclusivecrm.com on supported operator login pages.
When its CRM login button is used on supported travel-operator login pages, the extension asks www.allinclusivecrm.com for a login method. If the server response includes a method, the extension runs that returned JavaScript in the page context, where it can interact with login forms and page content.
Who publishes itAll-Inclusive CRM - no other listings under this identity, 27 shared hostnames
All-Inclusive CRM - no other listings under this identity, 27 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 27 hostnames
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
CRM login helper runs returned code on login pages
When you click the All-Inclusive CRM login button on a travel-operator page, the extension posts to www.allinclusivecrm.com for instructions.
A returned method value runs inline, with username, password, and page contents present.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-829
- Source
- Dynamic sandbox
You click the All-Inclusive CRM login button on a supported operator login page.
For the Coral online login page, the script appends the button to the login form and binds it to the username and password fields.
The extension asks www.allinclusivecrm.com for a login method and runs the returned method in that page.
The handler passes res.data.method into runCustomMethod, which creates an inline onreset handler and dispatches it.
- Operator slugcoral
This tells the CRM service which operator login flow you are using.
- Username fieldctl00$ContentPlaceHolder1$UserName
The returned page code runs where the username field is present and can interact with it.
- Password fieldctl00$ContentPlaceHolder1$UserPassword
The returned page code runs where the password field is present and can interact with it.
- Returned methodres.data.method
This value is treated as code that runs inside the login page after the service responds.
Successful object responses are checked for res.data.method before execution; no request or response body was recorded in the evidence.
The shipped code requests a method and executes it through an inline handler
CRM host builder
data/crm-helpers.jsfunction crmUrl(action) { if (chrome && (chrome.runtime.id === 'mjocllgmhfjfepihoipjobjijpicfmkj')) { return 'https://loc.allinclusivecrm.com' + action; } else { return (crmDomain || 'https://www.allinclusivecrm.com') + action; }}Coral online login script wires the CRM login button to the login form
data/operators_login/coral/coral-online.login.aicrm.jsAICRM_EXPORT_CONTRACT_OPERATOR_NAME = 'coral';(function() { const $form = $('#form1'); const $login = $('[name="ctl00$ContentPlaceHolder1$UserName"]', $form); const $password = $('[name="ctl00$ContentPlaceHolder1$UserPassword"]', $form); $('#tdforgatPass', $form).append( crmLoginButton($form, $login, $password, '#ctl00_ContentPlaceHolder1_GirisBtn_CD') .css({ display : 'block', marginTop: '20px', }) );})();Clicking the CRM button posts to the login endpoint and runs res.data.method
data/crm-helpers.jsfunction crmLoginButton($form, $login, $password, clickSubmit) { const disabled = !$login.length || !$password.length; if (disabled) { console.log('CRM login failed: empty login or password field'); } $(document).on('aicrmlogin', function(e) { $login.prop('type', 'hidden').val(e.detail.login); $password.prop('type', 'hidden').val(e.detail.password); $form.css('visibility', 'hidden'); if (clickSubmit === true) { $(':submit', $form).click(); } else if (typeof clickSubmit === 'string') { $(clickSubmit, $form).click(); } else { $form.submit(); } }); return $('<button>') .prop('type', 'button') .prop('disabled', disabled) .html(_t('login_button') + ' <span style="white-space: nowrap; display: inline;">All-Inclusive CRM</span>') .on('click', function() { const $btn = $(this); $btn.prop('disabled', true).text(_t('login_button_inprogress')); $.ajax({ method: 'POST', url: crmUrl('/integration/operator-contract/login?' + $.param({ operatorSlug: typeof AICRM_EXPORT_CONTRACT_OPERATOR_NAME !== 'undefined' ? AICRM_EXPORT_CONTRACT_OPERATOR_NAME : OPERATOR_NAME , })), headers: {pluginVersionOld: pluginVersionOld}, success: function (res, textStatus) { if ((typeof res === 'object') && !res.error) { runCustomMethod(res.data.method); } else { $btn.text(_t('login_button_failed')); if (res.error && res.alertError) { alert(res.error); } } }, error: function (res) { $btn.text(_t('login_button_failed')); if (res.error && res.alertError) { alert(res.error); } } }); return false; }) ;}runCustomMethod places the supplied function into an inline page handler
data/crm-helpers.jsfunction runCustomMethod(fn, params) { const body = document.querySelector('body'); if (!body) { setTimeout(function () { runCustomMethod(fn, params); }, 10); return; } const element = document.createElement('aicrmvar') const actualCode = '(' + fn + ')(' + JSON.stringify(params) + ')'; body.appendChild(element); element.setAttribute('onreset', actualCode); element.dispatchEvent(new CustomEvent('reset')); element.removeAttribute('onreset'); element.remove(); // Old approach which not working with V2 // const script = document.createElement('script'); // script.textContent = actualCode; // (document.head||document.documentElement).appendChild(script); // script.parentNode.removeChild(script);}- www.allinclusivecrm.com
Receives the operator-contract login POST and can return the method value that the extension executes on the operator login page.
- loc.allinclusivecrm.com
Alternate CRM host selected only when the extension runtime ID matches the development ID in crmUrl().
Where it sends data
Destinations our analysis observed All-Inclusive CRM contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- www.allinclusivecrm.com
All-Inclusive CRM sends data to www.allinclusivecrm.com. No other extension we have analysed sends data here.