Validation Sanitization Snippets
Custom Code Snippets — Validation & Sanitization
Copy-paste examples for validating and cleaning user-supplied data inside a Custom Code workflow step. Run these as the first step in a workflow to fail fast on bad input — every snippet returns an ok flag and an error message a downstream condition can branch on.
Validate an email address
const email = (params["email"] || "").toString().trim().toLowerCase();
const valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
returnData("valid", valid);
returnData("email", valid ? email : null);
returnData("error", valid ? null : "Invalid email format");
Sanitize a US phone number
// "(555) 123-4567" -> "5551234567"
const digits = (params["phone"] || "").replace(/\D/g, "");
const valid = digits.length === 10;
returnData("valid", valid);
returnData("phone_e164", valid ? `+1${digits}` : null);
returnData("phone_pretty", valid
? `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`
: null
);
Sanitize an international phone number to E.164
// Inputs: phone, default_country (custom_val "1" for US, "972" for Israel)
const raw = String(params["phone"] || "");
const country = String(params["default_country"] || "1");
let digits = raw.replace(/\D/g, "");
if (raw.trim().startsWith("+")) {
// Already has a country code
} else if (digits.length === 10 && country === "1") {
digits = `1${digits}`;
} else if (!digits.startsWith(country)) {
digits = `${country}${digits}`;
}
const valid = digits.length >= 10 && digits.length <= 15;
returnData("valid", valid);
returnData("phone_e164", valid ? `+${digits}` : null);
Require certain fields, fail fast
const required = ["first_name", "email", "company"];
const missing = required.filter(k => !record[k] || String(record[k]).trim() === "");
if (missing.length) {
returnData("ok", false);
returnData("missing", missing);
returnData("message", `Missing required fields: ${missing.join(", ")}`);
return;
}
returnData("ok", true);
returnData("message", "All required fields present");
Check a string against an allowlist
const ALLOWED = ["draft", "submitted", "approved", "rejected"];
const status = (params["status"] || "").toLowerCase();
returnData("status", ALLOWED.includes(status) ? status : "draft");
returnData("was_normalized", !ALLOWED.includes(status));
Validate a URL
const raw = String(params["url"] || "").trim();
let valid = false;
let normalized = null;
try {
const u = new URL(raw);
valid = u.protocol === "http:" || u.protocol === "https:";
normalized = valid ? u.toString() : null;
} catch (_) {
valid = false;
}
returnData("valid", valid);
returnData("url", normalized);
returnData("error", valid ? null : "Must be a valid http:// or https:// URL");
Validate a UUID
const id = String(params["id"] || "").toLowerCase();
const valid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id);
returnData("valid", valid);
returnData("id", valid ? id : null);
Check password strength
const pw = String(params["password"] || "");
const checks = {
long_enough: pw.length >= 12,
has_upper: /[A-Z]/.test(pw),
has_lower: /[a-z]/.test(pw),
has_digit: /\d/.test(pw),
has_symbol: /[^A-Za-z0-9]/.test(pw)
};
const passed = Object.values(checks).filter(Boolean).length;
const strong = passed === 5;
returnData("strong", strong);
returnData("checks", checks);
returnData("score", passed);
returnData("message", strong
? "Strong password"
: "Password must be 12+ chars and include upper, lower, digit, and symbol.");
Validate a US ZIP code
const zip = String(params["zip"] || "").trim();
const valid = /^\d{5}(-\d{4})?$/.test(zip);
returnData("valid", valid);
returnData("zip5", valid ? zip.slice(0, 5) : null);
Validate a credit card with Luhn checksum
// We don't store the number — we just confirm the user typed it correctly.
const digits = String(params["card_number"] || "").replace(/\D/g, "");
let sum = 0, double = false;
for (let i = digits.length - 1; i >= 0; i--) {
let n = Number(digits[i]);
if (double) { n *= 2; if (n > 9) n -= 9; }
sum += n;
double = !double;
}
const valid = digits.length >= 13 && digits.length <= 19 && sum % 10 === 0;
returnData("valid", valid);
returnData("last4", digits.slice(-4));
// Never return the full number.
Validate a numeric range
// Inputs: value, min, max
const v = Number(params["value"]);
const min = Number(params["min"]) || 0;
const max = Number(params["max"]) || Infinity;
if (Number.isNaN(v)) {
returnData("ok", false);
returnData("error", "Value is not a number");
return;
}
if (v < min || v > max) {
returnData("ok", false);
returnData("error", `Value ${v} is outside ${min}–${max}`);
return;
}
returnData("ok", true);
returnData("value", v);
Trim and normalize all string fields on a record
// Useful right after import — strip leading/trailing whitespace everywhere.
const cleaned = {};
for (const [k, v] of Object.entries(record || {})) {
cleaned[k] = typeof v === "string"
? v.replace(/\s+/g, " ").trim()
: v;
}
setResult({ cleaned });
Block disposable email domains
const blocklist = ["mailinator.com", "tempmail.com", "guerrillamail.com", "10minutemail.com"];
const email = String(params["email"] || "").toLowerCase().trim();
const domain = email.split("@")[1] || "";
const isDisposable = blocklist.includes(domain);
returnData("ok", !isDisposable);
returnData("error", isDisposable ? "Please use a non-disposable email address." : null);
Parse a JSON string safely
// Inputs: raw_json (custom_val or an Action Response Value)
let parsed = null;
let valid = true;
try {
parsed = JSON.parse(params["raw_json"] || "null");
} catch (e) {
valid = false;
console.error("JSON parse failed", e.message);
}
returnData("valid", valid && parsed != null);
returnData("data", parsed);
returnData("error", valid ? null : "raw_json is not valid JSON");
Sanitize HTML to remove script/style tags
// Defense-in-depth — Tadabase already escapes user-rendered content,
// but if you pass HTML to a Pipe or external API, sanitize first.
const html = String(params["html"] || "");
const cleaned = html
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")
.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, "")
.replace(/\son\w+\s*=\s*"[^"]*"/gi, "")
.replace(/\son\w+\s*=\s*'[^']*'/gi, "")
.replace(/\sjavascript:[^\s"']*/gi, "");
returnData("clean_html", cleaned);
We'd love to hear your feedback.