NationalSecurityAgency/ghidra · error · IOException

Bad characters in requested category type

Error message

Bad characters in requested category type

What it means

Thrown by InstallCategoryRequest.saveXml when the type_name contains characters not permitted by CategoryRecord.enforceTypeCharacters. The allowed character set is: letters, digits, spaces, periods, underscores, colons, forward slashes, and parentheses. An empty or null type_name also fails. This validation prevents SQL injection and XML corruption when the category type name is used in database queries and XML serialization.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/protocol/InstallCategoryRequest.java:53

	public boolean isdatecolumn;	// True if name should be treated as new name for date column
	public ResponseInfo installresponse;
	
	public InstallCategoryRequest() {
		super("installcategory");
		type_name = "";
		isdatecolumn = false;
	}
	
	@Override
	public void buildResponseTemplate() {
		if (response == null)
			response = installresponse = new ResponseInfo();
	}
	
	@Override
	public void saveXml(Writer fwrite) throws IOException {
		if (!CategoryRecord.enforceTypeCharacters(type_name))
			throw new IOException("Bad characters in requested category type");
		fwrite.append('<').append(name);
		if (isdatecolumn)
			fwrite.append(" datecolumn=\"true\"");
		fwrite.append('>');
		fwrite.append(type_name);
		fwrite.append("</").append(name).append(">\n");
	}

	@Override
	public void restoreXml(XmlPullParser parser, LSHVectorFactory vectorFactory) throws LSHException {
		XmlElement el = parser.start(name);
		isdatecolumn = XmlUtilities.parseBoolean(el.getAttribute("datecolumn"));
		type_name = parser.end().getText();
	}

}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Sanitize the type_name to contain only letters, digits, spaces, periods, underscores, colons, slashes, and parentheses before calling saveXml.
  2. Replace disallowed characters (e.g., hyphens to underscores) as a preprocessing step.
  3. Validate with CategoryRecord.enforceTypeCharacters(type_name) before serialization and fail early with a clear message.
  4. If the category name comes from external input, validate it at the boundary before constructing the request.

Example fix

// before
public void saveXml(Writer fwrite) throws IOException {
    if (!CategoryRecord.enforceTypeCharacters(type_name))
        throw new IOException("Bad characters in requested category type");
    ...
}

// caller fix — sanitize before sending
// before:
//   req.type_name = "my-category; DROP";
//   req.saveXml(writer);

// after:
//   String sanitized = req.type_name.replaceAll("[^a-zA-Z0-9 ._:()/]", "_");
//   if (!CategoryRecord.enforceTypeCharacters(sanitized)) {
//       throw new IllegalArgumentException("Invalid category name: " + req.type_name);
//   }
//   req.type_name = sanitized;
//   req.saveXml(writer);
Defensive patterns

Strategy: validation

Validate before calling

// Validate the category type name before serialization
public static String sanitizeCategoryType(String name) {
    if (name == null || name.isEmpty()) {
        throw new IllegalArgumentException("Category type name must not be null or empty");
    }
    if (!CategoryRecord.enforceTypeCharacters(name)) {
        // Replace disallowed characters with underscores
        String sanitized = name.replaceAll("[^a-zA-Z0-9 ._:()/]", "_");
        if (!CategoryRecord.enforceTypeCharacters(sanitized)) {
            throw new IllegalArgumentException(
                "Category type name contains invalid characters even after sanitization: " + name);
        }
        return sanitized;
    }
    return name;
}

// Usage:
req.type_name = sanitizeCategoryType(userInput);
req.saveXml(writer);

Type guard

public static boolean isValidCategoryType(String name) {
    return CategoryRecord.enforceTypeCharacters(name);
}

// Allowed characters: letters, digits, space, period, underscore,
// colon, forward slash, parentheses

Try / catch

try {
    req.saveXml(writer);
} catch (IOException e) {
    if (e.getMessage().contains("Bad characters")) {
        // Sanitize and retry
        req.type_name = req.type_name.replaceAll("[^a-zA-Z0-9 ._:()/]", "_");
        req.saveXml(writer);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling saveXml on an InstallCategoryRequest whose type_name contains disallowed characters such as hyphens, semicolons, quotes, angle brackets, or any special character. Also triggered by null or empty type_name. The validation runs at serialization time, not at object construction.

Common situations: Using a category name with hyphens (e.g., 'my-category'); including SQL-special characters like quotes or semicolons; passing a category name derived from user input without sanitization; an empty string default if the type_name was never set.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/1d1ee13312b39690. Report an issue: GitHub.