VYPR
Moderate severityNVD Advisory· Published Dec 11, 2021· Updated Aug 3, 2024

Cross-Site Request Forgery (CSRF) in yetiforcecompany/yetiforcecrm

CVE-2021-4092

Description

yetiforcecrm is vulnerable to Cross-Site Request Forgery (CSRF)

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
yetiforce/yetiforce-crmPackagist
< 6.3.06.3.0

Affected products

1

Patches

1
585da04bb72d

Added minor improvements

https://github.com/yetiforcecompany/yetiforcecrmMariusz KrzaczkowskiDec 10, 2021via ghsa
10 files changed · +81 73
  • app/Controller/View/Page.php+2 2 modified
    @@ -175,7 +175,7 @@ protected function getMenuHeaderLinks(\App\Request $request): array
     			'linklabel' => 'LBL_SIGN_OUT',
     			'linkurl' => 'index.php?module=Users&parent=Settings&action=Logout',
     			'icon' => 'fas fa-power-off fa-fw',
    -			'linkclass' => 'btn-danger d-md-none',
    +			'linkclass' => 'btn-danger d-md-none js-post-action',
     		];
     		$headerLinkInstances = [];
     		foreach ($headerLinks as $headerLink) {
    @@ -254,7 +254,7 @@ protected function getUserQuickMenuLinks(\App\Request $request): array
     			'linklabel' => 'LBL_SIGN_OUT',
     			'linkurl' => 'index.php?module=Users&parent=Settings&action=Logout',
     			'icon' => 'fas fa-power-off fa-fw',
    -			'linkclass' => 'd-none d-sm-none d-md-block',
    +			'linkclass' => 'd-none d-sm-none d-md-block js-post-action',
     		];
     		$headerLinkInstances = [];
     		foreach ($headerLinks as $headerLink) {
    
  • config/version.php+2 2 modified
    @@ -1,7 +1,7 @@
     <?php
     
     return [
    -	'appVersion' => '6.2.262',
    -	'patchVersion' => '2021.12.09',
    +	'appVersion' => '6.2.263',
    +	'patchVersion' => '2021.12.10',
     	'lib_roundcube' => '0.2.3',
     ];
    
  • layouts/basic/modules/Users/Modals/PasswordModalFooter.tpl+26 26 modified
    @@ -1,29 +1,29 @@
     {*<!-- {[The file is published on the basis of YetiForce Public License 4.0 that can be found in the following directory: licenses/LicenseEN.txt or yetiforce.com]} -->*}
     {strip}
    -<!-- tpl-Users-Modals-PasswordModalFooter -->
    -<div class="modal-footer">
    -	{if ($MODE === 'massReset' || $MODE === 'reset') &&  $ACTIVE_SMTP}
    -		<button class="btn btn-success" type="submit" name="saveButton"
    -				{if App\Config::main('systemMode') === 'demo'}disabled="disabled"{/if}>
    -			<span class="fas fa-redo-alt mr-2"></span><strong>{\App\Language::translate('BTN_RESET_PASSWORD', $MODULE_NAME)}</strong>
    -		</button>
    -	{/if}
    -	{if $MODE === 'change'}
    -		<button class="btn btn-success" type="submit" name="saveButton"
    -				{if App\Config::main('systemMode') === 'demo'}disabled="disabled"{/if}>
    -			<span class="fas fa-redo-alt mr-2"></span><strong>{\App\Language::translate('LBL_CHANGE_PASSWORD', $MODULE_NAME)}</strong>
    -		</button>
    -	{/if}
    -	{if $LOCK_EXIT}
    -		<a class="btn btn-danger" role="button" href="index.php?module=Users&amp;parent=Settings&amp;action=Logout">
    -			<span class="fas fa-power-off mr-2"></span><strong>{\App\Language::translate('LBL_SIGN_OUT', $MODULE_NAME)}</strong>
    -		</a>
    -	{else}
    -		<button class="btn btn-danger" type="reset" data-dismiss="modal">
    -			<span class="fas fa-times mr-2"></span><strong>{\App\Language::translate('LBL_CANCEL', $MODULE_NAME)}</strong>
    -		</button>
    -	{/if}
    -</div>
    -</form>
    -<!-- /tpl-Users-Modals-PasswordModalFooter -->
    +	<!-- tpl-Users-Modals-PasswordModalFooter -->
    +	<div class="modal-footer">
    +		{if ($MODE === 'massReset' || $MODE === 'reset') &&  $ACTIVE_SMTP}
    +			<button class="btn btn-success" type="submit" name="saveButton"
    +				{if App\Config::main('systemMode') === 'demo'}disabled="disabled" {/if}>
    +				<span class="fas fa-redo-alt mr-2"></span><strong>{\App\Language::translate('BTN_RESET_PASSWORD', $MODULE_NAME)}</strong>
    +			</button>
    +		{/if}
    +		{if $MODE === 'change'}
    +			<button class="btn btn-success" type="submit" name="saveButton"
    +				{if App\Config::main('systemMode') === 'demo'}disabled="disabled" {/if}>
    +				<span class="fas fa-redo-alt mr-2"></span><strong>{\App\Language::translate('LBL_CHANGE_PASSWORD', $MODULE_NAME)}</strong>
    +			</button>
    +		{/if}
    +		{if $LOCK_EXIT}
    +			<a class="btn btn-danger js-post-action" role="button" href="index.php?module=Users&amp;parent=Settings&amp;action=Logout">
    +				<span class="fas fa-power-off mr-2"></span><strong>{\App\Language::translate('LBL_SIGN_OUT', $MODULE_NAME)}</strong>
    +			</a>
    +		{else}
    +			<button class="btn btn-danger" type="reset" data-dismiss="modal">
    +				<span class="fas fa-times mr-2"></span><strong>{\App\Language::translate('LBL_CANCEL', $MODULE_NAME)}</strong>
    +			</button>
    +		{/if}
    +	</div>
    +	</form>
    +	<!-- /tpl-Users-Modals-PasswordModalFooter -->
     {/strip}
    
  • layouts/basic/modules/Vtiger/Index.tpl+2 2 modified
    @@ -20,10 +20,10 @@
     						<a class="btn btn-success mr-2" role="button" href="javascript:window.history.back();">
     							<span class="fas fa-chevron-left mr-2"></span>{\App\Language::translate('LBL_GO_BACK')}
     						</a>
    -						<a class="btn btn-warning mr-2" role="button" href="?module=Users&action=Logout">
    +						<a class="btn btn-warning mr-2 js-post-action" role="button" href="index.php?module=Users&action=Logout">
     							<span class="fas fa-power-off fa-fw mr-2"></span>{\App\Language::translate('LBL_SIGN_OUT')}
     						</a>
    -						<a class="btn btn-primary" role="button" href="?module=Users&action=Logout">
    +						<a class="btn btn-primary" role="button" href="index.php">
     							<i class="fas fa-home mr-2"></i>{\App\Language::translate('LBL_MAIN_PAGE')}
     						</a>
     					</p>
    
  • modules/Users/actions/Logout.php+0 8 modified
    @@ -38,12 +38,4 @@ public function process(App\Request $request)
     		//End
     		header('location: index.php');
     	}
    -
    -	/**
    -	 * {@inheritdoc}
    -	 */
    -	public function validateRequest(App\Request $request)
    -	{
    -		$request->validateReadAccess();
    -	}
     }
    
  • public_html/layouts/basic/modules/Vtiger/resources/List.js+5 5 modified
    @@ -195,7 +195,7 @@ $.Class(
     					let formData = container.find('.js-modal-form').serializeFormData();
     					const listInstance = Vtiger_List_Js.getInstance();
     					$.extend(formData, listInstance.getSearchParams());
    -					app.openUrlMethodPost('index.php', formData);
    +					AppConnector.requestForm('index.php', formData);
     					Vtiger_Helper_Js.showMessage({
     						text: app.vtranslate('JS_STARTED_GENERATING_FILE'),
     						type: 'info'
    @@ -355,7 +355,7 @@ $.Class(
     			}
     			let params = Vtiger_List_Js.getInstance().getSearchParams();
     			delete params.view;
    -			app.openUrlMethodPost(exportActionUrl, params, formAttr);
    +			AppConnector.requestForm(exportActionUrl, params, formAttr);
     		},
     		/**
     		 * Function to reload list
    @@ -1488,7 +1488,7 @@ $.Class(
     					Vtiger_Helper_Js.showConfirmationBox({
     						message: app.vtranslate('JS_LBL_ARE_YOU_SURE_YOU_WANT_TO_DELETE_FILTER')
     					}).done((e) => {
    -						app.openUrlMethodPost(thisInstance.getSelectOptionFromChosenOption(liElement).data('deleteurl'));
    +						AppConnector.requestForm(thisInstance.getSelectOptionFromChosenOption(liElement).data('deleteurl'));
     					});
     					event.stopPropagation();
     				});
    @@ -1505,7 +1505,7 @@ $.Class(
     					//to close the dropdown
     					thisInstance.getFilterSelectElement().data('select2').close();
     					const liElement = $(event.currentTarget).closest('.select2-results__option');
    -					app.openUrlMethodPost(thisInstance.getSelectOptionFromChosenOption(liElement).data('approveurl'));
    +					AppConnector.requestForm(thisInstance.getSelectOptionFromChosenOption(liElement).data('approveurl'));
     					event.stopPropagation();
     				});
     			}
    @@ -1521,7 +1521,7 @@ $.Class(
     					//to close the dropdown
     					thisInstance.getFilterSelectElement().data('select2').close();
     					const liElement = $(event.currentTarget).closest('.select2-results__option');
    -					app.openUrlMethodPost(thisInstance.getSelectOptionFromChosenOption(liElement).data('denyurl'));
    +					AppConnector.requestForm(thisInstance.getSelectOptionFromChosenOption(liElement).data('denyurl'));
     					event.stopPropagation();
     				});
     			}
    
  • public_html/layouts/basic/modules/Vtiger/resources/RelatedList.js+1 1 modified
    @@ -86,7 +86,7 @@ jQuery.Class(
     					data: postData
     				};
     				if (type === 'sendByForm') {
    -					app.openUrlMethodPost(massActionUrl, postData);
    +					AppConnector.requestForm(massActionUrl, postData);
     					progressIndicatorElement.progressIndicator({ mode: 'hide' });
     				} else {
     					AppConnector.request(actionParams)
    
  • public_html/layouts/basic/modules/Vtiger/resources/Vtiger.js+1 1 modified
    @@ -171,7 +171,7 @@ var Vtiger_Index_Js = {
     				form.append($('<input>', { name: i, value: JSON.stringify(postData[i]) }));
     			}
     			$('body').append(form);
    -			form.submit();
    +			form.trigger('submit');
     		} else {
     			window.location.href = url;
     		}
    
  • public_html/layouts/resources/app.js+16 23 modified
    @@ -306,7 +306,7 @@ var App = (window.App = {
     					$(data).removeAttr('data-validation-engine');
     				});
     				form.addClass('not_validation');
    -				form.submit();
    +				form.trigger('submit');
     			},
     			/**
     			 * Register tab events
    @@ -484,7 +484,7 @@ var App = (window.App = {
     					$(data).removeAttr('data-validation-engine');
     				});
     				form.addClass('not_validation');
    -				form.submit();
    +				form.trigger('submit');
     			},
     			/**
     			 * Save quick create form
    @@ -2627,27 +2627,6 @@ var app = (window.app = {
     			window.location.href = url;
     		}
     	},
    -	openUrlMethodPost(url, postData = {}, formAttr = {}) {
    -		$.extend(formAttr, {
    -			method: 'post',
    -			action: url,
    -			style: 'display:none;'
    -		});
    -		let form = $('<form></form>', formAttr);
    -		if (typeof csrfMagicName !== 'undefined') {
    -			postData[csrfMagicName] = csrfMagicToken;
    -		}
    -		$.each(postData, (index, value) => {
    -			let input = $(document.createElement('input'));
    -			input.attr('type', 'hidden');
    -			input.attr('name', index);
    -			input.val(value);
    -			form.append(input);
    -		});
    -		$('body').append(form);
    -		form.submit();
    -		form.remove();
    -	},
     	/**
     	 * Convert url string to object
     	 *
    @@ -3177,6 +3156,19 @@ var app = (window.app = {
     				}
     			});
     		}
    +	},
    +	/**
    +	 * Register POST action
    +	 * @param {jQuery} container
    +	 */
    +	registerPostActionEvent: function (container) {
    +		container.on('click', '.js-post-action', function (e) {
    +			e.preventDefault();
    +			let element = $(this);
    +			if (element.attr('href')) {
    +				AppConnector.requestForm(element.attr('href'));
    +			}
    +		});
     	}
     });
     CKEDITOR.disableAutoInline = true;
    @@ -3203,6 +3195,7 @@ $(function () {
     	app.registerFormsEvents(document);
     	app.registerRecordActionsEvents(document);
     	app.registerKeyboardShortcutsEvent(document);
    +	app.registerPostActionEvent(document);
     	App.Components.QuickCreate.register(document);
     	App.Components.Scrollbar.initPage();
     	App.Clipboard.register(document);
    
  • public_html/layouts/resources/Connector.js+26 3 modified
    @@ -146,8 +146,31 @@ window.AppConnector = {
     		}
     		return aDeferred.promise();
     	},
    -
    -	requestForm: function (url, params = {}) {
    -		app.openUrlMethodPost(url, params);
    +	/**
    +	 * Send form data
    +	 * @param {string} url
    +	 * @param {object} postData
    +	 * @param {object} formAttr
    +	 */
    +	requestForm: function (url, postData = {}, formAttr = {}) {
    +		$.extend(formAttr, {
    +			method: 'post',
    +			action: url,
    +			style: 'display:none;'
    +		});
    +		let form = $('<form></form>', formAttr);
    +		if (typeof csrfMagicName !== 'undefined') {
    +			postData[csrfMagicName] = csrfMagicToken;
    +		}
    +		$.each(postData, (index, value) => {
    +			let input = $(document.createElement('input'));
    +			input.attr('type', 'hidden');
    +			input.attr('name', index);
    +			input.val(value);
    +			form.append(input);
    +		});
    +		$('body').append(form);
    +		form.trigger('submit');
    +		form.remove();
     	}
     };
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.