{"record":{"id":"1d1ee13312b39690","repo":"NationalSecurityAgency/ghidra","slug":"bad-characters-in-requested-category-type","errorCode":null,"errorMessage":"Bad characters in requested category type","messagePattern":"Bad characters in requested category type","errorType":"validation","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/protocol/InstallCategoryRequest.java","lineNumber":53,"sourceCode":"\tpublic boolean isdatecolumn;\t// True if name should be treated as new name for date column\n\tpublic ResponseInfo installresponse;\n\t\n\tpublic InstallCategoryRequest() {\n\t\tsuper(\"installcategory\");\n\t\ttype_name = \"\";\n\t\tisdatecolumn = false;\n\t}\n\t\n\t@Override\n\tpublic void buildResponseTemplate() {\n\t\tif (response == null)\n\t\t\tresponse = installresponse = new ResponseInfo();\n\t}\n\t\n\t@Override\n\tpublic void saveXml(Writer fwrite) throws IOException {\n\t\tif (!CategoryRecord.enforceTypeCharacters(type_name))\n\t\t\tthrow new IOException(\"Bad characters in requested category type\");\n\t\tfwrite.append('<').append(name);\n\t\tif (isdatecolumn)\n\t\t\tfwrite.append(\" datecolumn=\\\"true\\\"\");\n\t\tfwrite.append('>');\n\t\tfwrite.append(type_name);\n\t\tfwrite.append(\"</\").append(name).append(\">\\n\");\n\t}\n\n\t@Override\n\tpublic void restoreXml(XmlPullParser parser, LSHVectorFactory vectorFactory) throws LSHException {\n\t\tXmlElement el = parser.start(name);\n\t\tisdatecolumn = XmlUtilities.parseBoolean(el.getAttribute(\"datecolumn\"));\n\t\ttype_name = parser.end().getText();\n\t}\n\n}\n","sourceCodeStart":35,"sourceCodeEnd":70,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/protocol/InstallCategoryRequest.java#L35-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Sanitize the type_name to contain only letters, digits, spaces, periods, underscores, colons, slashes, and parentheses before calling saveXml.","Replace disallowed characters (e.g., hyphens to underscores) as a preprocessing step.","Validate with CategoryRecord.enforceTypeCharacters(type_name) before serialization and fail early with a clear message.","If the category name comes from external input, validate it at the boundary before constructing the request."],"exampleFix":"// before\npublic void saveXml(Writer fwrite) throws IOException {\n    if (!CategoryRecord.enforceTypeCharacters(type_name))\n        throw new IOException(\"Bad characters in requested category type\");\n    ...\n}\n\n// caller fix — sanitize before sending\n// before:\n//   req.type_name = \"my-category; DROP\";\n//   req.saveXml(writer);\n\n// after:\n//   String sanitized = req.type_name.replaceAll(\"[^a-zA-Z0-9 ._:()/]\", \"_\");\n//   if (!CategoryRecord.enforceTypeCharacters(sanitized)) {\n//       throw new IllegalArgumentException(\"Invalid category name: \" + req.type_name);\n//   }\n//   req.type_name = sanitized;\n//   req.saveXml(writer);","handlingStrategy":"validation","validationCode":"// Validate the category type name before serialization\npublic static String sanitizeCategoryType(String name) {\n    if (name == null || name.isEmpty()) {\n        throw new IllegalArgumentException(\"Category type name must not be null or empty\");\n    }\n    if (!CategoryRecord.enforceTypeCharacters(name)) {\n        // Replace disallowed characters with underscores\n        String sanitized = name.replaceAll(\"[^a-zA-Z0-9 ._:()/]\", \"_\");\n        if (!CategoryRecord.enforceTypeCharacters(sanitized)) {\n            throw new IllegalArgumentException(\n                \"Category type name contains invalid characters even after sanitization: \" + name);\n        }\n        return sanitized;\n    }\n    return name;\n}\n\n// Usage:\nreq.type_name = sanitizeCategoryType(userInput);\nreq.saveXml(writer);","typeGuard":"public static boolean isValidCategoryType(String name) {\n    return CategoryRecord.enforceTypeCharacters(name);\n}\n\n// Allowed characters: letters, digits, space, period, underscore,\n// colon, forward slash, parentheses","tryCatchPattern":"try {\n    req.saveXml(writer);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"Bad characters\")) {\n        // Sanitize and retry\n        req.type_name = req.type_name.replaceAll(\"[^a-zA-Z0-9 ._:()/]\", \"_\");\n        req.saveXml(writer);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always validate type_name with CategoryRecord.enforceTypeCharacters before calling saveXml.","Sanitize user-supplied category names by replacing disallowed characters with underscores.","Remember the allowed set: letters, digits, spaces, periods, underscores, colons, slashes, parentheses — no hyphens or special chars.","Validate at input boundaries (CLI parsing, config loading) rather than at serialization time."],"tags":["bsim","validation","xml-serialization","category","sanitization"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}