sfcc-forms-development — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited sfcc-forms-development (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill guides you through implementing and troubleshooting the Salesforce B2C Commerce Forms Framework.
It covers:
Use this skill when you need to:
cartridge/forms/**.[ ] Form routes are POST-only and HTTPS-only
[ ] CSRF token is generated on GET and validated on POST
[ ] Server-side validation gate exists (do not trust client validation)
[ ] All string fields have max-length (DoS & storage safety)
[ ] Regex is conservative (avoid catastrophic backtracking)
[ ] Persistence happens inside Transaction.wrap
[ ] SFRA persistence is isolated in route:BeforeComplete where appropriate
[ ] Explicit mapping for writes (avoid mass assignment)
[ ] Form state cleared when appropriate (pre-render or after success)
[ ] User-provided values are output-encoded in ISMLForms are defined per cartridge:
/my-cartridge
/cartridge
/forms
/default
profile.xml
contact.xml
/de_DE
profile.xmlResource bundles typically live in:
/my-cartridge
/cartridge
/templates
/resources
forms.properties
forms_de_DE.propertiesFor deeper context and SFRA vs SiteGenesis architectural differences, see:
Keep examples small, but always include:
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.demandware.com/xml/form/2008-04-19">
<field formid="email" type="string"
label="form.email.label"
mandatory="true"
max-length="254"
regexp="^[^@\s]+@[^@\s]+\.[^@\s]+$"
missing-error="form.email.required"
parse-error="form.email.invalid"/>
<action formid="submit" valid-form="true"/>
</form>Prefer include to avoid duplicating complex groups (e.g., an address group reused in checkout, profile, and gift registry).
See the cheat sheet:
Goals:
'use strict';
var server = require('server');
var csrfProtection = require('*/cartridge/scripts/middleware/csrf');
server.get('Show',
server.middleware.https,
csrfProtection.generateToken,
function (req, res, next) {
var form = server.forms.getForm('contact');
form.clear();
res.render('forms/contact', {
contactForm: form
});
next();
}
);
module.exports = server.exports();Goals:
form.validTransaction.wraproute:BeforeComplete for persistence to keep transaction boundaries tight'use strict';
var server = require('server');
var Transaction = require('dw/system/Transaction');
var csrfProtection = require('*/cartridge/scripts/middleware/csrf');
server.post('Submit',
server.middleware.https,
csrfProtection.validateRequest,
function (req, res, next) {
var form = server.forms.getForm('contact');
if (!form.valid) {
// SFRA base commonly provides a helper like */cartridge/scripts/formErrors.
// Prefer using it when available.
res.json({
success: false,
fieldErrors: getFormErrorsSafe(form)
});
return next();
}
var email = form.email.value;
var message = form.message && form.message.value;
this.on('route:BeforeComplete', function () {
Transaction.wrap(function () {
// Persist explicitly (no mass assignment)
// e.g. save a Custom Object, update profile, create a case, etc.
// Keep only assignments inside the transaction.
});
form.clear();
});
res.json({ success: true });
next();
}
);
function getFormErrorsSafe(form) {
try {
var formErrors = require('*/cartridge/scripts/formErrors');
if (formErrors && typeof formErrors.getFormErrors === 'function') {
return formErrors.getFormErrors(form);
}
} catch (e) {
// Optional dependency; fall back if not present.
}
return {};
}
module.exports = server.exports();Notes:
csrfProtection.validateAjaxRequest if your route expects AJAX conventions.Transaction.wrap.app.getForm('id') and rendered via pdict.CurrentForms.htmlName (SiteGenesis uses dwfrm_ prefixes + session-specific IDs).dw.web.CSRFProtection.Use this for migration and pitfalls:
field.htmlName over hardcoded names.pdict.csrf.* when using SFRA CSRF middleware.Typical SFRA token:
<input type="hidden" name="${pdict.csrf.tokenName}" value="${pdict.csrf.token}" />When outputting user-provided values, ensure the context is encoded (default output encoding is usually safe, but be deliberate):
<isprint value="${pdict.contactForm.email.value}" encoding="htmlcontent" />Use custom validation for business rules that XML cannot express (uniqueness checks, cross-field constraints, etc.).
Patterns:
Keep custom validation server-side. Client-side validation is optional and must never be the security gate.
sfcc-security (CSRF, XSS, input validation)sfcc-sfra-controllers (middleware patterns, response handling)sfcc-isml-development (safe output encoding, template constraints)sfcc-localization (resource bundles, locale fallback)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.