mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-03-25 18:32:17 -04:00
Fix SQL injection in suggestions column configuration (#4421)
* Fix SQL injection in suggestions column configuration The suggestions_first_column, suggestions_second_column, and suggestions_third_column configuration values were concatenated directly into SQL SELECT statements without validation, allowing SQL injection attacks through the item search suggestions. Changes: - Add whitelist validation in Config controller to only allow valid column names (name, item_number, description, cost_price, unit_price) - Add defensive validation in Item model's get_search_suggestion_format() and get_search_suggestion_label() methods - Default invalid values to 'name' column for safety - Add unit tests to verify malicious inputs are rejected This is a critical security fix as attackers with config permissions could inject arbitrary SQL through these configuration fields. Vulnerability reported as additional injection point in bug report. * Refactor: Move allowed suggestions columns to Item model constants Extract the list of valid suggestion columns into two constants in the Item model for better cohesion: - ALLOWED_SUGGESTIONS_COLUMNS: valid column names - ALLOWED_SUGGESTIONS_COLUMNS_WITH_EMPTY: includes empty string for config validation This consolidates the validation logic in one place and makes it reusable across Config controller and Item model. * Address PR review comments: improve validation and code quality Changes: - Use camelCase naming for validateSuggestionsColumn() method (PSR-12) - Add field-aware validation with different fallbacks for first vs other columns - Handle non-string POST input by checking is_string() before validation - Refactor duplicate validation logic into suggestionColumnIsAllowed() helper - Use consistent camelCase variable names ($suggestionsFirstColumn) - Update tests to validate constants and behavior rather than implementation - Tests now focus on security properties of the allowlist itself The validation now properly handles: - First column: defaults to 'name' when invalid - Second/Third columns: defaults to '' (empty) when invalid - Non-string inputs: treated as invalid with appropriate fallback --------- Co-authored-by: Ollama <ollama@steganos.dev>
This commit is contained in:
@@ -11,6 +11,7 @@ use App\Models\Appconfig;
|
||||
use App\Models\Attribute;
|
||||
use App\Models\Customer_rewards;
|
||||
use App\Models\Dinner_table;
|
||||
use App\Models\Item;
|
||||
use App\Models\Module;
|
||||
use App\Models\Enums\Rounding_mode;
|
||||
use App\Models\Stock_location;
|
||||
@@ -385,9 +386,9 @@ class Config extends Secure_Controller
|
||||
'gcaptcha_enable' => $this->request->getPost('gcaptcha_enable') != null,
|
||||
'gcaptcha_secret_key' => $this->request->getPost('gcaptcha_secret_key'),
|
||||
'gcaptcha_site_key' => $this->request->getPost('gcaptcha_site_key'),
|
||||
'suggestions_first_column' => $this->request->getPost('suggestions_first_column'),
|
||||
'suggestions_second_column' => $this->request->getPost('suggestions_second_column'),
|
||||
'suggestions_third_column' => $this->request->getPost('suggestions_third_column'),
|
||||
'suggestions_first_column' => $this->validateSuggestionsColumn($this->request->getPost('suggestions_first_column'), 'first'),
|
||||
'suggestions_second_column' => $this->validateSuggestionsColumn($this->request->getPost('suggestions_second_column'), 'other'),
|
||||
'suggestions_third_column' => $this->validateSuggestionsColumn($this->request->getPost('suggestions_third_column'), 'other'),
|
||||
'giftcard_number' => $this->request->getPost('giftcard_number'),
|
||||
'derive_sale_quantity' => $this->request->getPost('derive_sale_quantity') != null,
|
||||
'multi_pack_enabled' => $this->request->getPost('multi_pack_enabled') != null,
|
||||
@@ -976,4 +977,26 @@ class Config extends Secure_Controller
|
||||
|
||||
return $this->response->setJSON(['success' => $success]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates suggestions column configuration to prevent SQL injection.
|
||||
*
|
||||
* @param mixed $column The column value from POST
|
||||
* @param string $fieldType Either 'first' or 'other' to determine default fallback
|
||||
* @return string Validated column name
|
||||
*/
|
||||
private function validateSuggestionsColumn(mixed $column, string $fieldType): string
|
||||
{
|
||||
if (!is_string($column)) {
|
||||
return $fieldType === 'first' ? 'name' : '';
|
||||
}
|
||||
|
||||
$allowed = $fieldType === 'first'
|
||||
? Item::ALLOWED_SUGGESTIONS_COLUMNS
|
||||
: Item::ALLOWED_SUGGESTIONS_COLUMNS_WITH_EMPTY;
|
||||
|
||||
$fallback = $fieldType === 'first' ? 'name' : '';
|
||||
|
||||
return in_array($column, $allowed, true) ? $column : $fallback;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user