{"record":{"id":"2efe4998e8dbc35d","repo":"affaan-m/ECC","slug":"label-must-not-contain-control-or-bidirectional","errorCode":null,"errorMessage":"${label} must not contain control or bidirectional formatting characters.","messagePattern":"(.+?) must not contain control or bidirectional formatting characters\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault-format.js","lineNumber":86,"sourceCode":"      || (codePoint >= 0x7f && codePoint <= 0x9f);\n    const isBidirectionalFormatting = (\n      (codePoint >= 0x202a && codePoint <= 0x202e)\n      || (codePoint >= 0x2066 && codePoint <= 0x2069)\n    );\n    return isControl || isBidirectionalFormatting;\n  });\n}\n\nfunction asNonEmptyString(value, label, maxChars = 10_000) {\n  if (typeof value !== 'string' || value.trim().length === 0) {\n    throw new Error(`${label} must be a non-empty string.`);\n  }\n  const normalized = value.trim();\n  if (normalized.length > maxChars) {\n    throw new Error(`${label} is too long (maximum ${maxChars} characters).`);\n  }\n  if (hasUnsafeControlCharacters(normalized)) {\n    throw new Error(`${label} must not contain control or bidirectional formatting characters.`);\n  }\n  return normalized;\n}\n\nfunction validateEnum(value, allowed, label) {\n  const normalized = asNonEmptyString(value, label, 64);\n  if (!allowed.includes(normalized)) {\n    throw new Error(`${label} must be one of: ${allowed.join(', ')}.`);\n  }\n  return normalized;\n}\n\nfunction validateSlug(value, label) {\n  const normalized = asNonEmptyString(value, label, 64);\n  if (!SLUG_PATTERN.test(normalized)) {\n    throw new Error(`${label} must be a lowercase letters/numbers slug.`);\n  }\n  return normalized;","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/memory-vault-format.js#L68-L104","documentation":"Thrown by asNonEmptyString() (via hasUnsafeControlCharacters) when the string contains C0/C1 control characters (excluding permitted whitespace in body mode) or Unicode bidirectional formatting code points (U+202A–U+202E, U+2066–U+2069). This guards against Trojans-source-style attacks and malformed paste input in memory documents.","triggerScenarios":"Pasting text from a terminal or rich-text source that includes ESC, BEL, NUL, or RTL/LTR override marks; binary content leaking into a string field.","commonSituations":"Copy-paste from word processors or web pages that embed invisible formatting; a corrupted file; an adversarial input testing for hidden-character injection.","solutions":["Strip control and bidi characters from the input before submission (e.g. sanitize with a regex over \\\\u0000-\\\\u001F, \\\\u007F-\\\\u009F, and the bidi blocks).","Re-type the value manually if paste is the suspected source.","Audit the upstream producer that generated the string."],"exampleFix":"// before\nasNonEmptyString('\\u202Ereversed text', 'title');\n// after\nconst clean = value.replace(/[\\\\u0000-\\\\u001F\\\\u007F-\\\\u009F\\\\u202A-\\\\u202E\\\\u2066-\\\\u2069]/gu, '');\nasNonEmptyString(clean, 'title');","handlingStrategy":"validation","validationCode":"const UNSAFE = /[\\u0000-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/;\nfunction isSafeString(value) {\n  return typeof value === 'string' && !UNSAFE.test(value);\n}\nfunction stripUnsafe(value) {\n  return value.replace(/[\\u0000-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/gu, '');\n}","typeGuard":"function isSafeFromControlChars(value) {\n  return typeof value === 'string'\n    && !/[\\u0000-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/.test(value);\n}","tryCatchPattern":"try {\n  result = asNonEmptyString(value, label);\n} catch (e) {\n  if (/control or bidirectional/.test(e.message)) {\n    const clean = value.replace(/[\\u0000-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/gu, '');\n    result = asNonEmptyString(clean, label);\n  } else throw e;\n}","preventionTips":["Sanitize paste input through the strip regex before submission.","Display warnings when input contains invisible characters in the UI.","Treat the presence of bidi overrides as a security signal and audit the source."],"tags":["memory-vault","validation","security","unicode","bidi"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}