CVE-2022-25867 (Java, published 2022-08-02T14:15Z)
Description: value: The package io.socket:socket.io-client before 2.0.1 are vulnerable to NULL Pointer Dereference when parsing a packet with with invalid payload format.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-476 \u2014 NULL Pointer Dereference
The product dereferences a pointer that it expects to be valid but is NULL.
Repository: https://github.com/socketio/socket.io-client-java
Files changed:
src/main/java/io/socket/client/Manager.java
src/main/java/io/socket/parser/IOParser.java
src/test/java/io/socket/parser/ByteArrayTest.java
src/test/java/io/socket/parser/ParserTest.java
Commit message: fix: ensure the payload format is valid

This commit should prevent some NPE issues encountered after the
parsing of the packet.

Related:

- https://github.com/socketio/socket.io-client-java/issues/642
- https://github.com/socketio/socket.io-client-java/issues/609
- https://github.com/socketio/socket.io-client-java/issues/505


Vulnerable code:
                if (data instanceof String) {
                    Manager.this.ondata((String)data);
                } else if (data instanceof byte[]) {
                    Manager.this.ondata((byte[])data);
    private void ondata(String data) {
        try {
            this.decoder.add(data);
        } catch (DecodingException e) {
            this.onerror(e);
        }
    }

    private void ondata(byte[] data) {
        try {
            this.decoder.add(data);
        } catch (DecodingException e) {
            this.onerror(e);
        }
    }

import io.socket.emitter.Emitter;
import org.json.JSONObject;
    public void encodeByteArray() {
        Packet<byte[]> packet = new Packet<>(Parser.BINARY_EVENT);
        packet.data = "abc".getBytes(Charset.forName("UTF-8"));
        Packet<byte[]> packet = new Packet<>(Parser.BINARY_EVENT);
        packet.data = new byte[2];
        JSONObject data = new JSONObject("{a: \"hi\", b: {}, c: {a: \"bye\", b: {}}}");
        data.getJSONObject("b").put("why", new byte[3]);
        data.getJSONObject("c").getJSONObject("b").put("a", new byte[6]);
        Packet<JSONObject> packet = new Packet<>(Parser.BINARY_EVENT);
        JSONObject data = new JSONObject("{a: \"b\", c: 4, e: {g: null}, h: null}");
        data.put("h", new byte[9]);
        Packet<JSONObject> packet = new Packet<>(Parser.BINARY_EVENT);

Fixed code:
                try {
                    if (data instanceof String) {
                        Manager.this.decoder.add((String) data);
                    } else if (data instanceof byte[]) {
                        Manager.this.decoder.add((byte[]) data);
                    }
                } catch (DecodingException e) {
                    logger.fine("error while decoding the packet: " + e.getMessage());
import org.json.JSONArray;
import org.json.JSONObject;
                if (!isPayloadValid(p.type, p.data)) {
                    throw new DecodingException("invalid payload");
                }
        private static boolean isPayloadValid(int type, Object payload) {
            switch (type) {
                case Parser.CONNECT:
                case Parser.CONNECT_ERROR:
                    return payload instanceof JSONObject;
                case Parser.DISCONNECT:
                    return payload == null;
                case Parser.EVENT:
                case Parser.BINARY_EVENT:
                    return payload instanceof JSONArray
                            && ((JSONArray) payload).length() > 0
                            && !((JSONArray) payload).isNull(0);
                case Parser.ACK:
                case Parser.BINARY_ACK:
                    return payload instanceof JSONArray;
                default:
                    return false;
            }
        }

import java.nio.charset.StandardCharsets;
import static java.util.Arrays.asList;
    public void encodeByteArray() throws JSONException {
        Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
        packet.data = new JSONArray(asList("abc", "abc".getBytes(StandardCharsets.UTF_8)));
        Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
        packet.data = new JSONArray(asList("2", new byte[] { 0, 1 }));
        JSONArray data = new JSONArray("[{a: \"hi\", b: {}, c: {a: \"bye\", b: {}}}]");
        data.getJSONObject(0).getJSONObject("b").put("why", new byte[3]);
        data.getJSONObject(0).getJSONObject("c").getJSONObject("b").put("a", new byte[6]);
        Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
        JSONArray data = new JSONArray("[{a: \"b\", c: 4, e: {g: null}, h: null}]");
        data.getJSONObject(0).put("h", new byte[9]);
        Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
        Helpers.testDecodeError(Parser.EVENT + "2{}");
        Helpers.testDecodeError(Parser.EVENT + "2[]");
        Helpers.testDecodeError(Parser.EVENT + "2[null]");