affaan-m/ECC · error · Error
${label} must not contain control or bidirectional formattin
Error message
${label} must not contain control or bidirectional formatting characters. What it means
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.
Source
Thrown at scripts/lib/memory-vault-format.js:86
|| (codePoint >= 0x7f && codePoint <= 0x9f);
const isBidirectionalFormatting = (
(codePoint >= 0x202a && codePoint <= 0x202e)
|| (codePoint >= 0x2066 && codePoint <= 0x2069)
);
return isControl || isBidirectionalFormatting;
});
}
function asNonEmptyString(value, label, maxChars = 10_000) {
if (typeof value !== 'string' || value.trim().length === 0) {
throw new Error(`${label} must be a non-empty string.`);
}
const normalized = value.trim();
if (normalized.length > maxChars) {
throw new Error(`${label} is too long (maximum ${maxChars} characters).`);
}
if (hasUnsafeControlCharacters(normalized)) {
throw new Error(`${label} must not contain control or bidirectional formatting characters.`);
}
return normalized;
}
function validateEnum(value, allowed, label) {
const normalized = asNonEmptyString(value, label, 64);
if (!allowed.includes(normalized)) {
throw new Error(`${label} must be one of: ${allowed.join(', ')}.`);
}
return normalized;
}
function validateSlug(value, label) {
const normalized = asNonEmptyString(value, label, 64);
if (!SLUG_PATTERN.test(normalized)) {
throw new Error(`${label} must be a lowercase letters/numbers slug.`);
}
return normalized;View on GitHub (pinned to 01e15490f0)
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.
Example fix
// before
asNonEmptyString('\u202Ereversed text', 'title');
// after
const clean = value.replace(/[\\u0000-\\u001F\\u007F-\\u009F\\u202A-\\u202E\\u2066-\\u2069]/gu, '');
asNonEmptyString(clean, 'title'); Defensive patterns
Strategy: validation
Validate before calling
const UNSAFE = /[\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069]/;
function isSafeString(value) {
return typeof value === 'string' && !UNSAFE.test(value);
}
function stripUnsafe(value) {
return value.replace(/[\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069]/gu, '');
} Type guard
function isSafeFromControlChars(value) {
return typeof value === 'string'
&& !/[\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069]/.test(value);
} Try / catch
try {
result = asNonEmptyString(value, label);
} catch (e) {
if (/control or bidirectional/.test(e.message)) {
const clean = value.replace(/[\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069]/gu, '');
result = asNonEmptyString(clean, label);
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Copy-paste from word processors or web pages that embed invisible formatting; a corrupted file; an adversarial input testing for hidden-character injection.
Related errors
- memory body must not contain unsafe control or bidirectional
- No trusted boundary policy is configured for memory scope "$
- ${label} must be a regular, non-symlink file.
- Project memory .gitignore does not contain the required fail
- Refusing to save memory containing a suspected secret (${sec
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/2efe4998e8dbc35d.
Report an issue: GitHub.