class
Analyzer::Java::Cli
- Analyzer::Java::Cli
- Analyzer
- Reference
- Object
Overview
Surfaces the command-line attack surface of Java programs as cli://
endpoints: one endpoint per (sub)command with named options
(param_type "flag"), positional arguments ("argument") and consumed
environment variables ("env"). Covers picocli, args4j, JCommander,
commons-cli, airline and jopt-simple, plus gated System.getenv reads.
Line-scan analyzer (Go/Ruby/Rust CLI house style) merging endpoints by URL. Subclasses Analyzer directly (JavaEngine is a module) and uses JavaEngine.test_path? to skip tests.
Defined in:
analyzer/analyzers/java/cli.crConstant Summary
-
ADD_OPTION_LL =
/\.addOption\s*\(\s*"([^"]+)"\s*,\s*"([^"]+)"\s*,/ -
commons-cli (no subcommands; flags on root).
-
ADD_OPTION_SHORT =
/\.addOption\s*\(\s*"([^"]+)"\s*,\s*(?:true|false)\s*,/ -
Current (non-deprecated)
addOption(String opt, boolean hasArg, String description)overload used for short-only flags. Thetrue|falseliteral gate in the 2nd argument position guarantees this never overlaps with ADD_OPTION_LL above (which requires a quoted string there), so a given call is matched by exactly one of the two. -
ARGUMENT_ATTR =
/@Argument\b/ -
ARGUMENTS_ATTR =
/@Arguments\s*\(([^)]*)\)/ -
CLI_GATE_RE =
/@Command\b|@Parameter\b|new\s+JCommander|new\s+CmdLineParser|new\s+Options\s*\(/ -
COMMAND_ATTR =
/@Command\s*\([^)]*\bname\s*=\s*"([^"]+)"/ -
COMMAND_NAME_KV =
/\bname\s*=\s*"([^"]+)"/ -
COMMAND_OPEN =
/@Command\b/ -
FIELD_DECL =
/^\s*(?:public|private|protected)?\s*(?:final\s+|static\s+)*[\w<>\[\].]+\s+(\w+)\s*[;=]/ -
GET_ENV =
/\bSystem\.getenv\s*\(\s*"([^"]+)"\s*\)/ -
JC_COMMAND =
/@Parameters\s*\([^)]*\bcommandNames\s*=\s*\{?\s*"([^"]+)"/ -
JOPT_ACCEPTS =
/\b(\w+)\.accepts\s*\(\s*"([^"]+)"/ -
JOPT_ACCEPTS_ALL =
/\b(\w+)\.acceptsAll\s*\(\s*(?:Arrays\.asList|List\.of|Collections\.singletonList)\s*\(\s*"([^"]+)"/ -
JOPT_PARSER_DECL =
/\b(\w+)\s*=\s*new\s+OptionParser\s*\(/ -
jopt-simple (no subcommands; flags land on root, like commons-cli).
.accepts("flag")/.acceptsAll(List.of("f","flag"))are only real CLI flags when called on a variable that was actually bound tonew OptionParser(...)— jopt-simple'sOptionParserisn't the only class with anaccepts(...)method (e.g. aFormatMatcher.accepts(fmt)helper), so the receiver is tracked per-file in the same forward pass and matches on an untracked receiver are dropped rather than attributed to the root command. -
LIB_MARKERS =
["picocli.", "org.kohsuke.args4j", "com.beust.jcommander", "org.apache.commons.cli", "com.github.rvesse.airline", "io.airlift.airline", "joptsimple."] -
LIB_MARKERS_RE =
Regex.union(LIB_MARKERS) -
LONG_OPT =
/\.longOpt\s*\(\s*"([^"]+)"/ -
OPTION_ATTR =
/@Option\s*\(([^)]*)\)/ -
PARAMETER_ATTR =
/@Parameter\s*\(([^)]*)\)/ -
PARAMETERS_ATTR =
/@Parameters\b([^)\n]*\)?)/ -
RAW_CLI_MARKERS_RE =
Regex.union(LIB_MARKERS + ["@Command", "@Parameter", "JCommander", "CmdLineParser", "Options"]) -
Cheap pre-gate applied to the RAW file, before the comment strip.
strip_commentsmaterialises anArray(Char)of the whole file and rebuilds it character by character; running it on all 8,658.javafiles in spring-boot to then reject 97% of them on the gate below was the bulk of this analyzer. Stripping only replaces characters with' 'or'\n'and never changes the character count, so a literal with no whitespace in it can appear in the stripped text only if it already appears, unchanged, in the raw text. Each alternative of the real gate requires one of these literals verbatim (thenew\s+Xforms requireX; the\s-carrying parts are deliberately not relied on, since blanking a comment can manufacture whitespace). Files that pass still go through the full, comment-aware gate. -
SUBCOMMANDS_KEY =
/\bsubcommands\s*=/ -
WEB_FRAMEWORK_RE =
/\bimport\s+(?:org\.springframework|jakarta\.ws\.rs|javax\.ws\.rs|io\.quarkus|io\.micronaut|io\.javalin|io\.vertx|com\.linecorp\.armeria|io\.dropwizard|spark\.|org\.apache\.struts)/