Salesforce B2C Commerce Data Validation

Introduction to Data Validation

Validation is the process by which data is rigorously checked to ensure that it is exactly the kind of data expected by an application. Invalid requests are generally rejected outright and an error is returned to users. There are many locations a developer can choose to do validation, but this Best Practice focusses on Client-Side and Server-Side only.

  • Client-Side data validation is typically developed by implementing some scripting language to do a quick check of data on a Client’s machine before sending to a Server. On the Commerce Cloud platform, this is usually accomplished by writing JavaScript code that runs inside a user’s browser and validates form data.
  • Server-Side data validation is implemented by writing an additional step into a business flow. This step can validate the type of the data being received – is it a number or true/false or a word – as well as the content – does this value make sense using the knowledge only a server can know. On the Commerce Cloud platform, this is usually accomplished in a Digital Script, using the Commerce Cloud APIs and some basic sanity checks.

Salesforce Commerce Cloud recommends make some light sanity checks using Client-Side validation to provide storefront users with a solid User Experience and immediate feedback, but always validate thoroughly using Server-Side validation, including duplicating all Client-Side checks.

Threats

  • Directly counteracts all Injection attacks – i.e. Cross Site Scripting Attack

Why is Data Validation is Important?

Validation allows developers to ensure that bad or malicious data never enters an application. Duplicating Client-Side checks on the Server ensures an attacker can’t send data directly to a server, bypassing Client checks and inject bad or malicious data into an application.

How does Data Validation protects SFCC against Threats?

  • Proper validation will lightly test data on a client, immediately returning obvious issues to the user. Once the request is sent, the data should again be validated; if invalid data is present, halt all processing and return an error message to the user. This means that accidental, mistyped data is reported to legitimate users via Client-Side validation, while malicious users sending requests directly to servers are stopped by Server-Side validation.

Does this Best Practice not protect against any part of a Threat?

  • In general, proper validation protects against injection attacks. When used in conjunction with output encoding, an application can be given a robust defense against Injection attacks.
  • Exposing sensitive Internal data in client-side validations
    • A common issue when validating data is to put too much internal logic into Client Side checks. This can include a list of expected values, or sending a list of potentially valid data to the client to check against. This can give valuable data away to all clients. Some of those clients may be malicious attackers searching for a vulnerability.
  • Inexact validation can lead to false sense of security
    • Another common issue is an over-reliance on validation for security. Developers should ensure that validation steps are just one piece of a larger security architecture that promotes multiple stages of security checks.
    • This is common with regular expressions as they can be very difficult to verify completely.

Code Examples of Data Validation

Common Bad Practices while validating data

Client-only Checking: In this case, authorized_purchase.isml allows authorized users to submit purchase orders for goods, but only if they’ve passed an authorization check, and sends to SubmitPurchase.js to make the purchase if the parameter is set.

The problem is that the form is “protected” from being submitted because the button has been disabled. This does not prevent an attacker from removing the disabled attribute and clicking the button or submitting the request directly.

				
					<!-- authorized_purchase.isml -->
<form action="${URLUtils.httpsContinue()}">
    <input type="submit" value="Submit My Purchase" disabled="disabled"/>
</form>
				
			
				
					// SubmitPurchase.js
if(parameters.submit_purchase != null && parameters.submit_purchase.length > 0) { 
    submitpurchase();
}

				
			

Exposing Internal Data: In this example, the developer is trying to provide a good UX by doing a client-side check using internal knowledge. However, this exposes three valid values of Promo codes that anyone who examines the webpage can use.

				
					<!-- flashsalecodes.isml -->
<script>
    var good_codes = ["1234", "8675", "31415"];
    function isGoodCode() {
        var code = document.forms["myForm"]["code"].value
        if(good_codes.indexOf(code) == -1) {
            alert("Unknown Promo Code");
            return false;
        }
    }
</script>

<form name="myForm" onsubmit="return isGoodCode()">
    <input type="text" name="code"/>
    <input type="submit" value="Use Promo Code"/>
</form>
				
			

Inexact Validation: Regex is hard. It is very easy to accidentally expose extra matching when working with regular  expressions. Below is a common pattern that demonstrates a bad use of validation.

The developer is trying to ensure that a piece of data “username” contains letters; however, the username could also contain some special characters. The developer has chosen to create a blacklist, a validation where a match shows a failure, rather than a success. The problem with the regex is that it will match “John Doe” as well as “@#$%^&*“, but fails over “John Doe1“.

				
					// TestUsername.js

// Returns true if the username doesn't match the regex
function isGoodUserName(username) {
    var re = /^[\D]+$/; // only matches if the input doesn't contain digits
    return re.exec(username) == null;
}

				
			

Example of Best Practices while validating data

Client-Only Checking: By duplicating the authorization check on the server, legitimate users can see they are disallowed in the UI, but malicious users will actually be halted if they try to submit the form anyway.

				
					<!-- authorized_purchase.isml -->
<form action="${URLUtils.httpsContinue()}">
    <input type="submit" value="Submit My Purchase" disabled="disabled"/>
</form>
				
			
				
					// SubmitPurchase.js
if(parameters.submit_purchase != null && parameters.submit_purchase.length > 0) { 
    submitpurchase();
} else {
    return "User is unauthorized to submit a purchase";
}
				
			

Exposing Internal Data: To counteract this issue, all code checking should be moved to the server side for validation.

				
					<!-- flashsalecodes.isml -->
<form name="myForm" onsubmit="return isGoodCode()">
    <input type="text" name="code"/>
    <input type="submit" value="Use Promo Code"/>
</form>
				
			
				
					// ValidatePromo.js
var good_codes = ["1234", "8675", "31415"];
if (parameters.code != null && parameters.code.length > 0) {
    if(good_codes.indexOf(code) == -1) {
        return "Bad Promo Code
    }
}
				
			

Inexact Validation: This issue can be very hard to overcome, however, it is generally recommended that developers create whitelists (where the list contains only good data) rather than blacklists (where the list contains all possible bad data). Perhaps the regular expression should really match for all letters, some special characters (to handle O’Connor), and the space character. The whitelist regex is much harder to write, but would look like this:

				
					// TestUsername.js

// Returns true if the username matches the regex
function isGoodUserName(username) {
    // Only matches if the input starts with letters and then contains only letters, apostrophes, dashes, or spaces
    // OR input starts with special characters, but then contains letters
    var re = /^([a-zA-Z]+[a-zA-Z'\- ]*)|([a-zA-Z'\- ]*[a-zA-Z]+)$/
    return re.exec(username) != null;
}
				
			

How to be a Certified Salesforce Commerce Cloud Developer for FREE

Unlock a FREE PDF with SFCC B2C Certification questions from our Udemy Course. Join our newsletter!
Check your email, you’ll receive a copy in a few seconds. If you don’t see it, please check your spam folder.

Do you like cookies? 🍪 We use cookies to ensure you get the best experience on our website. Learn more.