{"record":{"id":"8cc0edf1edd83b9f","repo":"affaan-m/ECC","slug":"memory-body-must-not-contain-unsafe-control-or-bid","errorCode":null,"errorMessage":"memory body must not contain unsafe control or bidirectional formatting characters.","messagePattern":"memory body must not contain unsafe control or bidirectional formatting characters\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault-format.js","lineNumber":149,"sourceCode":"function validateTimestamp(value, label) {\n  const normalized = asNonEmptyString(value, label, 64);\n  const parsed = new Date(normalized);\n  if (\n    !ISO_TIMESTAMP_PATTERN.test(normalized)\n    || Number.isNaN(parsed.getTime())\n    || parsed.toISOString() !== normalized\n  ) {\n    throw new Error(`${label} must be an ISO-8601 timestamp.`);\n  }\n  return normalized;\n}\n\nfunction normalizeBody(value) {\n  if (typeof value !== 'string') {\n    throw new Error('memory body must be a string.');\n  }\n  if (hasUnsafeControlCharacters(value, true)) {\n    throw new Error('memory body must not contain unsafe control or bidirectional formatting characters.');\n  }\n  const normalized = value.trim();\n  if (normalized.length === 0) {\n    throw new Error('memory body must contain non-whitespace context.');\n  }\n  if (Buffer.byteLength(normalized, 'utf8') > MAX_BODY_BYTES) {\n    throw new Error(`memory body is too large (maximum ${MAX_BODY_BYTES} bytes).`);\n  }\n  return normalized;\n}\n\nfunction normalizeMemory(memory) {\n  if (!memory || typeof memory !== 'object' || Array.isArray(memory)) {\n    throw new Error('memory must be an object.');\n  }\n\n  const targetHarnesses = uniqueStrings(memory.targetHarnesses, {\n    label: 'target harnesses',","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/memory-vault-format.js#L131-L167","documentation":"normalizeBody rejects bodies containing control characters (except tab, LF, CR) or Unicode bidirectional-formatting code points (U+202A–U+202E, U+2066–U+2069). This guards against corrupted content and Trojan-Source-style bidirectional attacks that can make code/text render deceptively in the vault.","triggerScenarios":"Calling normalizeMemory with a body containing NUL bytes, ANSI escape sequences, C1 control characters, or invisible RTL/LTR override marks — typically from binary-ish input, terminal-captured output, or copied text with hidden bidi characters.","commonSituations":"Pasting text from terminals, PDFs, or chat apps that embed invisible formatting characters; logging raw process output that includes ANSI color codes; mixed LTR/RTL content copied from bilingual editors; files edited in a tool that inserted BOM/control bytes.","solutions":["Strip unsafe characters before calling: remove /[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/g from the string.","Replace ANSI terminal escape sequences with a regex like /\\x1b\\[[0-9;]*m/g before storing.","Retype or re-export the content from a plain-text editor if it came from a copy/paste with hidden bidi marks.","Remove a leading UTF-8 BOM (\\uFEFF is not in the rejected ranges, but adjacent control bytes often are) and re-check."],"exampleFix":"// before\nnormalizeMemory({ body: rawTerminalOutput, ... })\n// after\nconst clean = rawTerminalOutput.replace(/[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/g, '');\nnormalizeMemory({ body: clean, ... })","handlingStrategy":"validation","validationCode":"const stripUnsafe = (s) => s.replace(/[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/g, '');\nbody = stripUnsafe(body);","typeGuard":"const hasUnsafeChars = (s) => /[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/.test(s);","tryCatchPattern":"try { normalizeMemory(mem); } catch (e) { if (e.message.includes('unsafe control or bidirectional')) { mem.body = stripUnsafe(mem.body); } else throw e; }","preventionTips":["Sanitize any text captured from terminals (strip ANSI escapes)","Beware copy/paste from PDFs and chat apps carrying hidden bidi marks","Run a Trojan-Source scan on pasted code snippets","Store text as UTF-8 and re-encode once before validating"],"tags":["validation","security","control-characters","memory-vault"],"backgroundTag":"invalid-argument-value","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}