frohoff/ysoserial · error · IllegalArgumentException

Bad command format.

Error message

Bad command format.

What it means

ysoserial's Wicket1 payload generator throws this IllegalArgumentException from getObject() when the command string does not split into exactly 3 ';'-separated parts. The Wicket1 DiskFileItem gadget requires a command of the form '<operation>;<arg1>;<arg2>', so any other shape is rejected before dispatch.

Solutions

  1. Supply exactly three semicolon-separated fields: operation, arg1, arg2 (e.g. 'copyAndDelete;/tmp/source;/tmp/dest' or 'write;/tmp/target;content').
  2. Check the command for stray/missing semicolons; escape-free ';' characters must number exactly two.
  3. Pick a supported operation name as parts[0]: 'copyAndDelete', 'write', 'writeOld', or 'writeOldB64' (see error 21 for unknown ops).

Example fix

// before
String command = "write /tmp/x hello";
DiskFileItem item = new Wicket1().getObject(command);
// after
String command = "write;/tmp/x;hello";
DiskFileItem item = new Wicket1().getObject(command);
Defensive patterns

Strategy: validation

Validate before calling

public static void validateWicket1Command(String command) {
    if (command == null || command.split(";", -1).length != 3) {
        throw new IllegalArgumentException("Wicket1 command must be 'op;arg1;arg2' (exactly 3 parts): " + command);
    }
}

Type guard

public static boolean isValidWicket1Command(String command) {
    return command != null && command.split(";", -1).length == 3;
}

Try / catch

try {
    DiskFileItem item = new Wicket1().getObject(command);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Bad command format")) {
        System.err.println("Command must have exactly 3 ';'-separated parts: 'op;arg1;arg2'");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling new Wicket1().getObject(command) with a command that yields parts.length != 3 after command.split(";"), e.g. 'write' alone, 'copyAndDelete;file' (only 2 parts), or a string containing no semicolons at all.

Common situations: Users forget the semicolon-delimited format when configuring the payload, pass a path containing no separator but omit the second argument, or copy a command from another ysoserial payload with a different argument format.

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/e29863ad49eee70f. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/ysoserial/payloads/Wicket1.java:59

 * Wicket1 "write;/tmp;blue lobster"
 *
 * Result:
 * $ ls -l /tmp/
 * -rw-rw-r-- 1 albino_lobster albino_lobster   12 Jul 25 14:10 upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp
 * $ cat /tmp/upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp
 * blue lobster
 */
@PayloadTest(harness="ysoserial.test.payloads.FileUploadTest", flaky="possible race condition")
@Dependencies({"org.apache.wicket:wicket-util:6.23.0", "org.slf4j:slf4j-api:1.6.4"})
@Authors({ Authors.JACOBAINES })
public class Wicket1 implements ReleaseableObjectPayload<DiskFileItem> {

    public DiskFileItem getObject(String command) throws Exception {

        String[] parts = command.split(";");

        if (parts.length != 3) {
        	throw new IllegalArgumentException("Bad command format.");
        }

        if ("copyAndDelete".equals(parts[0])) {
            return copyAndDelete(parts[1], parts[2]);
        }
        else if ("write".equals(parts[0])) {
            return write(parts[1], parts[2].getBytes("US-ASCII"));
        }
        else if ("writeB64".equals(parts[0]) ) {
            return write(parts[1], Base64.decodeBase64(parts[2]));
        }
        else if ("writeOld".equals(parts[0]) ) {
            return writeOldJRE(parts[1], parts[2].getBytes("US-ASCII"));
        }
        else if ("writeOldB64".equals(parts[0]) ) {
            return writeOldJRE(parts[1], Base64.decodeBase64(parts[2]));
        }
        throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts));

View on GitHub (pinned to 218bcffcaa)