{"record":{"id":"1cf8ba1416100b84","repo":"google/tsunami-security-scanner","slug":"parenthesis-and-or-brackets-not-allowed-within-version-range","errorCode":null,"errorMessage":"Parenthesis and/or brackets not allowed within version range, got '%s'","messagePattern":"Parenthesis and/or brackets not allowed within version range, got '(.+?)'","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"common/src/main/java/com/google/tsunami/common/version/VersionRange.java","lineNumber":144,"sourceCode":"\n    // Version range string must start with '[' or '('.\n    if (!rangeString.startsWith(\"[\") && !rangeString.startsWith(\"(\")) {\n      throw new IllegalArgumentException(\n          String.format(\"Version range must start with '[' or '(', got '%s'\", rangeString));\n    }\n\n    // Version range string must end with ']' or ')'.\n    if (!rangeString.endsWith(\"]\") && !rangeString.endsWith(\")\")) {\n      throw new IllegalArgumentException(\n          String.format(\"Version range must end with ']' or ')', got '%s'\", rangeString));\n    }\n\n    // Remove the leading and ending parenthesis and brackets.\n    String trimmedRange = rangeString.substring(1, rangeString.length() - 1).trim();\n\n    // No more parenthesis and brackets in the string.\n    if (CharMatcher.anyOf(\"[()]\").matchesAnyOf(trimmedRange)) {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Parenthesis and/or brackets not allowed within version range, got '%s'\",\n              rangeString));\n    }\n\n    // Only one comma that separates the minimum and maximum.\n    if (CharMatcher.is(',').countIn(trimmedRange) != 1) {\n      throw new IllegalArgumentException(\n          String.format(\"Invalid range of versions, got '%s'\", rangeString));\n    }\n\n    // Version range of minimum to maximum is not supported.\n    if (trimmedRange.equals(\",\")) {\n      throw new IllegalArgumentException(\n          String.format(\"Infinity range is not supported, got '%s'\", rangeString));\n    }\n  }\n}","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/google/tsunami-security-scanner/blob/363ba87b3543f8ae8e4304d3416818f03da7f262/common/src/main/java/com/google/tsunami/common/version/VersionRange.java#L126-L162","documentation":"VersionRange.parse validates the range string after stripping the leading and trailing bracket/parenthesis. If any '[' , '(' or ')' character remains inside the trimmed string, the range is malformed and this IllegalArgumentException is thrown. Version ranges in Tsunami must look like '[1.0,2.0]' or '[1.0,)' — no nested or stray delimiters.","triggerScenarios":"Calling VersionRange.parse with a string that still contains '[', '(' or ')' after the outer delimiters are removed, e.g. parse(\"[1.0,[2.0]\") or parse(\"[1.0, (2.5]\").","commonSituations":"Hand-written vulnerability fingerprint version ranges with typos (extra bracket), programmatically built range strings where delimiters are concatenated twice, or copy-pasted Maven/npm-style range syntax that Tsunami's stricter grammar rejects.","solutions":["Inspect the range string and remove any inner '[' , '(' or ')' characters, keeping exactly one opening delimiter at the start and one closing delimiter at the end.","Use VersionRange.isValidVersionRange(rangeString) to check the string before calling parse.","Build ranges with explicit min/max strings and a single bracket pair, e.g. \"[\" + min + \",\" + max + \"]\"."],"exampleFix":"// before\nVersionRange.parse(\"[1.0,[2.0]\");\n// after\nVersionRange.parse(\"[1.0,2.0]\");","handlingStrategy":"validation","validationCode":"if (VersionRange.isValidVersionRange(rangeString)) { VersionRange.parse(rangeString); }","typeGuard":"boolean isValidRange(String s) { return s != null && VersionRange.isValidVersionRange(s); }","tryCatchPattern":"try { VersionRange.parse(rangeString); } catch (IllegalArgumentException e) { log.error(\"Bad range: {}\", e.getMessage()); }","preventionTips":["Keep exactly one bracket/paren pair at the outermost ends of the range string.","Never nest delimiters inside the min/max expressions.","Pre-check with isValidVersionRange before parsing user input."],"tags":["version-range","parsing","illegal-argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"363ba87b3543f8ae8e4304d3416818f03da7f262","analyzedAt":"2026-09-13T01:50:53.990Z","contentChangedAt":"2026-09-13T01:50:53.990Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}