From 006d77ffdd49dc424d029d81f41de0f3ac4107f5 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 11 Jul 2025 06:13:01 +0100 Subject: [PATCH 1/4] Refactor QL to make type check more concise --- .../semmle/code/java/security/UnsafeDeserializationQuery.qll | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index e10c6cebaf63..541942c6036c 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -149,10 +149,7 @@ predicate unsafeDeserialization(MethodCall ma, Expr sink) { exists(Method m | m = ma.getMethod() | m instanceof ObjectInputStreamReadObjectMethod and sink = ma.getQualifier() and - not exists(DataFlow::ExprNode node | - node.getExpr() = sink and - node.getTypeBound() instanceof SafeObjectInputStreamType - ) + not DataFlow::exprNode(sink).getTypeBound() instanceof SafeObjectInputStreamType or m instanceof XmlDecoderReadObjectMethod and sink = ma.getQualifier() From 34fae324a051f63a856eaec738aa10e9e38fdfb3 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 11 Jul 2025 10:16:25 +0100 Subject: [PATCH 2/4] Add test for ObjectInput.readObject --- .../test/query-tests/security/CWE-502/A.java | 29 ++- .../CWE-502/UnsafeDeserialization.expected | 212 +++++++++--------- .../CWE-502/UnsafeDeserialization.ext.yml | 7 + .../CWE-502/com/example/MyObjectInput.java | 109 +++++++++ 4 files changed, 245 insertions(+), 112 deletions(-) create mode 100644 java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.ext.yml create mode 100644 java/ql/test/query-tests/security/CWE-502/com/example/MyObjectInput.java diff --git a/java/ql/test/query-tests/security/CWE-502/A.java b/java/ql/test/query-tests/security/CWE-502/A.java index 81974edf283e..d36d1d3c0b86 100644 --- a/java/ql/test/query-tests/security/CWE-502/A.java +++ b/java/ql/test/query-tests/security/CWE-502/A.java @@ -1,6 +1,9 @@ +package unsafedeserialization; + import java.io.*; import java.net.Socket; import java.beans.XMLDecoder; +import com.example.MyObjectInput; import com.thoughtworks.xstream.XStream; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; @@ -10,13 +13,23 @@ import org.nibblesec.tools.SerialKiller; public class A { - public Object deserialize1(Socket sock) throws java.io.IOException, ClassNotFoundException { + public Object deserialize1a(Socket sock) throws java.io.IOException, ClassNotFoundException { InputStream inputStream = sock.getInputStream(); // $ Source ObjectInputStream in = new ObjectInputStream(inputStream); return in.readObject(); // $ Alert } - public Object deserialize2(Socket sock) throws java.io.IOException, ClassNotFoundException { + public Object deserialize2() throws java.io.IOException, ClassNotFoundException { + ObjectInput objectInput = A.getTaintedObjectInput(); // $ MISSING: Source + return objectInput.readObject(); // $ MISSING: Alert + } + + public Object deserialize3() throws java.io.IOException, ClassNotFoundException { + MyObjectInput objectInput = A.getTaintedMyObjectInput(); // $ MISSING: Source + return objectInput.readObject(); // $ MISSING: Alert + } + + public Object deserialize4(Socket sock) throws java.io.IOException, ClassNotFoundException { InputStream inputStream = sock.getInputStream(); // $ Source ObjectInputStream in = new ObjectInputStream(inputStream); return in.readUnshared(); // $ Alert @@ -28,20 +41,20 @@ public Object deserializeWithSerialKiller(Socket sock) throws java.io.IOExceptio return in.readUnshared(); // OK } - public Object deserialize3(Socket sock) throws java.io.IOException { + public Object deserialize5(Socket sock) throws java.io.IOException { InputStream inputStream = sock.getInputStream(); // $ Source XMLDecoder d = new XMLDecoder(inputStream); return d.readObject(); // $ Alert } - public Object deserialize4(Socket sock) throws java.io.IOException { + public Object deserialize6(Socket sock) throws java.io.IOException { XStream xs = new XStream(); InputStream inputStream = sock.getInputStream(); // $ Source Reader reader = new InputStreamReader(inputStream); return xs.fromXML(reader); // $ Alert } - public void deserialize5(Socket sock) throws java.io.IOException { + public void deserialize7(Socket sock) throws java.io.IOException { Kryo kryo = new Kryo(); Input input = new Input(sock.getInputStream()); // $ Source A a1 = kryo.readObject(input, A.class); // $ Alert @@ -56,7 +69,7 @@ private Kryo getSafeKryo() throws java.io.IOException { return kryo; } - public void deserialize6(Socket sock) throws java.io.IOException { + public void deserialize8(Socket sock) throws java.io.IOException { Kryo kryo = getSafeKryo(); Input input = new Input(sock.getInputStream()); Object o = kryo.readClassAndObject(input); // OK @@ -101,4 +114,8 @@ public void deserializeSnakeYaml4(Socket sock) throws java.io.IOException { A o4 = yaml.loadAs(input, A.class); // $ Alert A o5 = yaml.loadAs(new InputStreamReader(input), A.class); // $ Alert } + + static ObjectInput getTaintedObjectInput() { return null; } + + static MyObjectInput getTaintedMyObjectInput() { return null; } } diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected index b4064231bec6..599b85603c8b 100644 --- a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected +++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected @@ -1,26 +1,26 @@ #select -| A.java:16:12:16:26 | readObject(...) | A.java:14:31:14:51 | getInputStream(...) : InputStream | A.java:16:12:16:13 | in | Unsafe deserialization depends on a $@. | A.java:14:31:14:51 | getInputStream(...) | user-provided value | -| A.java:22:12:22:28 | readUnshared(...) | A.java:20:31:20:51 | getInputStream(...) : InputStream | A.java:22:12:22:13 | in | Unsafe deserialization depends on a $@. | A.java:20:31:20:51 | getInputStream(...) | user-provided value | -| A.java:34:12:34:25 | readObject(...) | A.java:32:31:32:51 | getInputStream(...) : InputStream | A.java:34:12:34:12 | d | Unsafe deserialization depends on a $@. | A.java:32:31:32:51 | getInputStream(...) | user-provided value | -| A.java:41:12:41:29 | fromXML(...) | A.java:39:31:39:51 | getInputStream(...) : InputStream | A.java:41:23:41:28 | reader | Unsafe deserialization depends on a $@. | A.java:39:31:39:51 | getInputStream(...) | user-provided value | -| A.java:47:12:47:42 | readObject(...) | A.java:46:29:46:49 | getInputStream(...) : InputStream | A.java:47:28:47:32 | input | Unsafe deserialization depends on a $@. | A.java:46:29:46:49 | getInputStream(...) | user-provided value | -| A.java:48:12:48:48 | readObjectOrNull(...) | A.java:46:29:46:49 | getInputStream(...) : InputStream | A.java:48:34:48:38 | input | Unsafe deserialization depends on a $@. | A.java:46:29:46:49 | getInputStream(...) | user-provided value | -| A.java:49:16:49:45 | readClassAndObject(...) | A.java:46:29:46:49 | getInputStream(...) : InputStream | A.java:49:40:49:44 | input | Unsafe deserialization depends on a $@. | A.java:46:29:46:49 | getInputStream(...) | user-provided value | -| A.java:68:16:68:31 | load(...) | A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:68:26:68:30 | input | Unsafe deserialization depends on a $@. | A.java:67:25:67:45 | getInputStream(...) | user-provided value | -| A.java:69:17:69:35 | loadAll(...) | A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:69:30:69:34 | input | Unsafe deserialization depends on a $@. | A.java:67:25:67:45 | getInputStream(...) | user-provided value | -| A.java:70:17:70:56 | parse(...) | A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:70:28:70:55 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:67:25:67:45 | getInputStream(...) | user-provided value | -| A.java:71:12:71:38 | loadAs(...) | A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:71:24:71:28 | input | Unsafe deserialization depends on a $@. | A.java:67:25:67:45 | getInputStream(...) | user-provided value | -| A.java:72:12:72:61 | loadAs(...) | A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:72:24:72:51 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:67:25:67:45 | getInputStream(...) | user-provided value | -| A.java:78:16:78:31 | load(...) | A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:78:26:78:30 | input | Unsafe deserialization depends on a $@. | A.java:77:25:77:45 | getInputStream(...) | user-provided value | -| A.java:79:17:79:35 | loadAll(...) | A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:79:30:79:34 | input | Unsafe deserialization depends on a $@. | A.java:77:25:77:45 | getInputStream(...) | user-provided value | -| A.java:80:17:80:56 | parse(...) | A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:80:28:80:55 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:77:25:77:45 | getInputStream(...) | user-provided value | -| A.java:81:12:81:38 | loadAs(...) | A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:81:24:81:28 | input | Unsafe deserialization depends on a $@. | A.java:77:25:77:45 | getInputStream(...) | user-provided value | -| A.java:82:12:82:61 | loadAs(...) | A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:82:24:82:51 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:77:25:77:45 | getInputStream(...) | user-provided value | -| A.java:98:16:98:31 | load(...) | A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:98:26:98:30 | input | Unsafe deserialization depends on a $@. | A.java:97:25:97:45 | getInputStream(...) | user-provided value | -| A.java:99:17:99:35 | loadAll(...) | A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:99:30:99:34 | input | Unsafe deserialization depends on a $@. | A.java:97:25:97:45 | getInputStream(...) | user-provided value | -| A.java:100:17:100:56 | parse(...) | A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:100:28:100:55 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:97:25:97:45 | getInputStream(...) | user-provided value | -| A.java:101:12:101:38 | loadAs(...) | A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:101:24:101:28 | input | Unsafe deserialization depends on a $@. | A.java:97:25:97:45 | getInputStream(...) | user-provided value | -| A.java:102:12:102:61 | loadAs(...) | A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:102:24:102:51 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:97:25:97:45 | getInputStream(...) | user-provided value | +| A.java:19:12:19:26 | readObject(...) | A.java:17:31:17:51 | getInputStream(...) : InputStream | A.java:19:12:19:13 | in | Unsafe deserialization depends on a $@. | A.java:17:31:17:51 | getInputStream(...) | user-provided value | +| A.java:35:12:35:28 | readUnshared(...) | A.java:33:31:33:51 | getInputStream(...) : InputStream | A.java:35:12:35:13 | in | Unsafe deserialization depends on a $@. | A.java:33:31:33:51 | getInputStream(...) | user-provided value | +| A.java:47:12:47:25 | readObject(...) | A.java:45:31:45:51 | getInputStream(...) : InputStream | A.java:47:12:47:12 | d | Unsafe deserialization depends on a $@. | A.java:45:31:45:51 | getInputStream(...) | user-provided value | +| A.java:54:12:54:29 | fromXML(...) | A.java:52:31:52:51 | getInputStream(...) : InputStream | A.java:54:23:54:28 | reader | Unsafe deserialization depends on a $@. | A.java:52:31:52:51 | getInputStream(...) | user-provided value | +| A.java:60:12:60:42 | readObject(...) | A.java:59:29:59:49 | getInputStream(...) : InputStream | A.java:60:28:60:32 | input | Unsafe deserialization depends on a $@. | A.java:59:29:59:49 | getInputStream(...) | user-provided value | +| A.java:61:12:61:48 | readObjectOrNull(...) | A.java:59:29:59:49 | getInputStream(...) : InputStream | A.java:61:34:61:38 | input | Unsafe deserialization depends on a $@. | A.java:59:29:59:49 | getInputStream(...) | user-provided value | +| A.java:62:16:62:45 | readClassAndObject(...) | A.java:59:29:59:49 | getInputStream(...) : InputStream | A.java:62:40:62:44 | input | Unsafe deserialization depends on a $@. | A.java:59:29:59:49 | getInputStream(...) | user-provided value | +| A.java:81:16:81:31 | load(...) | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:81:26:81:30 | input | Unsafe deserialization depends on a $@. | A.java:80:25:80:45 | getInputStream(...) | user-provided value | +| A.java:82:17:82:35 | loadAll(...) | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:82:30:82:34 | input | Unsafe deserialization depends on a $@. | A.java:80:25:80:45 | getInputStream(...) | user-provided value | +| A.java:83:17:83:56 | parse(...) | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:83:28:83:55 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:80:25:80:45 | getInputStream(...) | user-provided value | +| A.java:84:12:84:38 | loadAs(...) | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:84:24:84:28 | input | Unsafe deserialization depends on a $@. | A.java:80:25:80:45 | getInputStream(...) | user-provided value | +| A.java:85:12:85:61 | loadAs(...) | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:85:24:85:51 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:80:25:80:45 | getInputStream(...) | user-provided value | +| A.java:91:16:91:31 | load(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:91:26:91:30 | input | Unsafe deserialization depends on a $@. | A.java:90:25:90:45 | getInputStream(...) | user-provided value | +| A.java:92:17:92:35 | loadAll(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:92:30:92:34 | input | Unsafe deserialization depends on a $@. | A.java:90:25:90:45 | getInputStream(...) | user-provided value | +| A.java:93:17:93:56 | parse(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:90:25:90:45 | getInputStream(...) | user-provided value | +| A.java:94:12:94:38 | loadAs(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:94:24:94:28 | input | Unsafe deserialization depends on a $@. | A.java:90:25:90:45 | getInputStream(...) | user-provided value | +| A.java:95:12:95:61 | loadAs(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:90:25:90:45 | getInputStream(...) | user-provided value | +| A.java:111:16:111:31 | load(...) | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:111:26:111:30 | input | Unsafe deserialization depends on a $@. | A.java:110:25:110:45 | getInputStream(...) | user-provided value | +| A.java:112:17:112:35 | loadAll(...) | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:112:30:112:34 | input | Unsafe deserialization depends on a $@. | A.java:110:25:110:45 | getInputStream(...) | user-provided value | +| A.java:113:17:113:56 | parse(...) | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:113:28:113:55 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:110:25:110:45 | getInputStream(...) | user-provided value | +| A.java:114:12:114:38 | loadAs(...) | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:114:24:114:28 | input | Unsafe deserialization depends on a $@. | A.java:110:25:110:45 | getInputStream(...) | user-provided value | +| A.java:115:12:115:61 | loadAs(...) | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:115:24:115:51 | new InputStreamReader(...) | Unsafe deserialization depends on a $@. | A.java:110:25:110:45 | getInputStream(...) | user-provided value | | B.java:8:12:8:46 | parseObject(...) | B.java:7:31:7:51 | getInputStream(...) : InputStream | B.java:8:29:8:39 | inputStream | Unsafe deserialization depends on a $@. | B.java:7:31:7:51 | getInputStream(...) | user-provided value | | B.java:15:12:15:28 | parse(...) | B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:15:23:15:27 | bytes | Unsafe deserialization depends on a $@. | B.java:12:31:12:51 | getInputStream(...) | user-provided value | | B.java:23:12:23:30 | parseObject(...) | B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:23:29:23:29 | s | Unsafe deserialization depends on a $@. | B.java:19:31:19:51 | getInputStream(...) | user-provided value | @@ -72,45 +72,45 @@ | ParcelableEntity.java:32:30:32:70 | fromJson(...) | GsonActivity.java:15:54:15:64 | getIntent(...) : Intent | ParcelableEntity.java:32:44:32:62 | readString(...) | Unsafe deserialization depends on a $@. | GsonActivity.java:15:54:15:64 | getIntent(...) | user-provided value | | TestMessageBodyReader.java:22:18:22:65 | readObject(...) | TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | Unsafe deserialization depends on a $@. | TestMessageBodyReader.java:20:55:20:78 | entityStream | user-provided value | edges -| A.java:14:31:14:51 | getInputStream(...) : InputStream | A.java:15:50:15:60 | inputStream : InputStream | provenance | Src:MaD:1 | -| A.java:14:31:14:51 | getInputStream(...) : InputStream | A.java:16:12:16:13 | in | provenance | Src:MaD:1 inputStreamWrapper | -| A.java:15:28:15:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:16:12:16:13 | in | provenance | | -| A.java:15:50:15:60 | inputStream : InputStream | A.java:15:28:15:61 | new ObjectInputStream(...) : ObjectInputStream | provenance | MaD:11 | -| A.java:20:31:20:51 | getInputStream(...) : InputStream | A.java:21:50:21:60 | inputStream : InputStream | provenance | Src:MaD:1 | -| A.java:20:31:20:51 | getInputStream(...) : InputStream | A.java:22:12:22:13 | in | provenance | Src:MaD:1 inputStreamWrapper | -| A.java:21:28:21:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:22:12:22:13 | in | provenance | | -| A.java:21:50:21:60 | inputStream : InputStream | A.java:21:28:21:61 | new ObjectInputStream(...) : ObjectInputStream | provenance | MaD:11 | -| A.java:32:31:32:51 | getInputStream(...) : InputStream | A.java:33:35:33:45 | inputStream : InputStream | provenance | Src:MaD:1 | -| A.java:33:20:33:46 | new XMLDecoder(...) : XMLDecoder | A.java:34:12:34:12 | d | provenance | | -| A.java:33:35:33:45 | inputStream : InputStream | A.java:33:20:33:46 | new XMLDecoder(...) : XMLDecoder | provenance | MaD:7 | -| A.java:39:31:39:51 | getInputStream(...) : InputStream | A.java:40:43:40:53 | inputStream : InputStream | provenance | Src:MaD:1 | -| A.java:40:21:40:54 | new InputStreamReader(...) : InputStreamReader | A.java:41:23:41:28 | reader | provenance | | -| A.java:40:43:40:53 | inputStream : InputStream | A.java:40:21:40:54 | new InputStreamReader(...) : InputStreamReader | provenance | MaD:10 | -| A.java:46:19:46:50 | new Input(...) : Input | A.java:47:28:47:32 | input | provenance | | -| A.java:46:19:46:50 | new Input(...) : Input | A.java:48:34:48:38 | input | provenance | | -| A.java:46:19:46:50 | new Input(...) : Input | A.java:49:40:49:44 | input | provenance | | -| A.java:46:29:46:49 | getInputStream(...) : InputStream | A.java:46:19:46:50 | new Input(...) : Input | provenance | Src:MaD:1 MaD:5 | -| A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:68:26:68:30 | input | provenance | Src:MaD:1 | -| A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:69:30:69:34 | input | provenance | Src:MaD:1 | -| A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:70:50:70:54 | input : InputStream | provenance | Src:MaD:1 | -| A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:71:24:71:28 | input | provenance | Src:MaD:1 | -| A.java:67:25:67:45 | getInputStream(...) : InputStream | A.java:72:46:72:50 | input : InputStream | provenance | Src:MaD:1 | -| A.java:70:50:70:54 | input : InputStream | A.java:70:28:70:55 | new InputStreamReader(...) | provenance | MaD:10 | -| A.java:72:46:72:50 | input : InputStream | A.java:72:24:72:51 | new InputStreamReader(...) | provenance | MaD:10 | -| A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:78:26:78:30 | input | provenance | Src:MaD:1 | -| A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:79:30:79:34 | input | provenance | Src:MaD:1 | -| A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:80:50:80:54 | input : InputStream | provenance | Src:MaD:1 | -| A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:81:24:81:28 | input | provenance | Src:MaD:1 | -| A.java:77:25:77:45 | getInputStream(...) : InputStream | A.java:82:46:82:50 | input : InputStream | provenance | Src:MaD:1 | -| A.java:80:50:80:54 | input : InputStream | A.java:80:28:80:55 | new InputStreamReader(...) | provenance | MaD:10 | -| A.java:82:46:82:50 | input : InputStream | A.java:82:24:82:51 | new InputStreamReader(...) | provenance | MaD:10 | -| A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:98:26:98:30 | input | provenance | Src:MaD:1 | -| A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:99:30:99:34 | input | provenance | Src:MaD:1 | -| A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:100:50:100:54 | input : InputStream | provenance | Src:MaD:1 | -| A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:101:24:101:28 | input | provenance | Src:MaD:1 | -| A.java:97:25:97:45 | getInputStream(...) : InputStream | A.java:102:46:102:50 | input : InputStream | provenance | Src:MaD:1 | -| A.java:100:50:100:54 | input : InputStream | A.java:100:28:100:55 | new InputStreamReader(...) | provenance | MaD:10 | -| A.java:102:46:102:50 | input : InputStream | A.java:102:24:102:51 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:17:31:17:51 | getInputStream(...) : InputStream | A.java:18:50:18:60 | inputStream : InputStream | provenance | Src:MaD:1 | +| A.java:17:31:17:51 | getInputStream(...) : InputStream | A.java:19:12:19:13 | in | provenance | Src:MaD:1 inputStreamWrapper | +| A.java:18:28:18:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:19:12:19:13 | in | provenance | | +| A.java:18:50:18:60 | inputStream : InputStream | A.java:18:28:18:61 | new ObjectInputStream(...) : ObjectInputStream | provenance | MaD:11 | +| A.java:33:31:33:51 | getInputStream(...) : InputStream | A.java:34:50:34:60 | inputStream : InputStream | provenance | Src:MaD:1 | +| A.java:33:31:33:51 | getInputStream(...) : InputStream | A.java:35:12:35:13 | in | provenance | Src:MaD:1 inputStreamWrapper | +| A.java:34:28:34:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:35:12:35:13 | in | provenance | | +| A.java:34:50:34:60 | inputStream : InputStream | A.java:34:28:34:61 | new ObjectInputStream(...) : ObjectInputStream | provenance | MaD:11 | +| A.java:45:31:45:51 | getInputStream(...) : InputStream | A.java:46:35:46:45 | inputStream : InputStream | provenance | Src:MaD:1 | +| A.java:46:20:46:46 | new XMLDecoder(...) : XMLDecoder | A.java:47:12:47:12 | d | provenance | | +| A.java:46:35:46:45 | inputStream : InputStream | A.java:46:20:46:46 | new XMLDecoder(...) : XMLDecoder | provenance | MaD:7 | +| A.java:52:31:52:51 | getInputStream(...) : InputStream | A.java:53:43:53:53 | inputStream : InputStream | provenance | Src:MaD:1 | +| A.java:53:21:53:54 | new InputStreamReader(...) : InputStreamReader | A.java:54:23:54:28 | reader | provenance | | +| A.java:53:43:53:53 | inputStream : InputStream | A.java:53:21:53:54 | new InputStreamReader(...) : InputStreamReader | provenance | MaD:10 | +| A.java:59:19:59:50 | new Input(...) : Input | A.java:60:28:60:32 | input | provenance | | +| A.java:59:19:59:50 | new Input(...) : Input | A.java:61:34:61:38 | input | provenance | | +| A.java:59:19:59:50 | new Input(...) : Input | A.java:62:40:62:44 | input | provenance | | +| A.java:59:29:59:49 | getInputStream(...) : InputStream | A.java:59:19:59:50 | new Input(...) : Input | provenance | Src:MaD:1 MaD:5 | +| A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:81:26:81:30 | input | provenance | Src:MaD:1 | +| A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:82:30:82:34 | input | provenance | Src:MaD:1 | +| A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:83:50:83:54 | input : InputStream | provenance | Src:MaD:1 | +| A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:84:24:84:28 | input | provenance | Src:MaD:1 | +| A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:85:46:85:50 | input : InputStream | provenance | Src:MaD:1 | +| A.java:83:50:83:54 | input : InputStream | A.java:83:28:83:55 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:85:46:85:50 | input : InputStream | A.java:85:24:85:51 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:91:26:91:30 | input | provenance | Src:MaD:1 | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:92:30:92:34 | input | provenance | Src:MaD:1 | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:50:93:54 | input : InputStream | provenance | Src:MaD:1 | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:94:24:94:28 | input | provenance | Src:MaD:1 | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:46:95:50 | input : InputStream | provenance | Src:MaD:1 | +| A.java:93:50:93:54 | input : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:95:46:95:50 | input : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:111:26:111:30 | input | provenance | Src:MaD:1 | +| A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:112:30:112:34 | input | provenance | Src:MaD:1 | +| A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:113:50:113:54 | input : InputStream | provenance | Src:MaD:1 | +| A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:114:24:114:28 | input | provenance | Src:MaD:1 | +| A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:115:46:115:50 | input : InputStream | provenance | Src:MaD:1 | +| A.java:113:50:113:54 | input : InputStream | A.java:113:28:113:55 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:115:46:115:50 | input : InputStream | A.java:115:24:115:51 | new InputStreamReader(...) | provenance | MaD:10 | | B.java:7:31:7:51 | getInputStream(...) : InputStream | B.java:8:29:8:39 | inputStream | provenance | Src:MaD:1 | | B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:14:5:14:15 | inputStream : InputStream | provenance | Src:MaD:1 | | B.java:14:5:14:15 | inputStream : InputStream | B.java:14:22:14:26 | bytes [post update] : byte[] | provenance | MaD:9 | @@ -235,51 +235,51 @@ models | 15 | Summary: java.lang; String; false; split; ; ; Argument[this]; ReturnValue; taint; manual | | 16 | Summary: org.json; JSONObject; false; JSONObject; (String); ; Argument[0]; Argument[this]; taint; manual | nodes -| A.java:14:31:14:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| A.java:15:28:15:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream | -| A.java:15:50:15:60 | inputStream : InputStream | semmle.label | inputStream : InputStream | -| A.java:16:12:16:13 | in | semmle.label | in | -| A.java:20:31:20:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| A.java:21:28:21:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream | -| A.java:21:50:21:60 | inputStream : InputStream | semmle.label | inputStream : InputStream | -| A.java:22:12:22:13 | in | semmle.label | in | -| A.java:32:31:32:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| A.java:33:20:33:46 | new XMLDecoder(...) : XMLDecoder | semmle.label | new XMLDecoder(...) : XMLDecoder | -| A.java:33:35:33:45 | inputStream : InputStream | semmle.label | inputStream : InputStream | -| A.java:34:12:34:12 | d | semmle.label | d | -| A.java:39:31:39:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| A.java:40:21:40:54 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader | -| A.java:40:43:40:53 | inputStream : InputStream | semmle.label | inputStream : InputStream | -| A.java:41:23:41:28 | reader | semmle.label | reader | -| A.java:46:19:46:50 | new Input(...) : Input | semmle.label | new Input(...) : Input | -| A.java:46:29:46:49 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| A.java:47:28:47:32 | input | semmle.label | input | -| A.java:48:34:48:38 | input | semmle.label | input | -| A.java:49:40:49:44 | input | semmle.label | input | -| A.java:67:25:67:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| A.java:68:26:68:30 | input | semmle.label | input | -| A.java:69:30:69:34 | input | semmle.label | input | -| A.java:70:28:70:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | -| A.java:70:50:70:54 | input : InputStream | semmle.label | input : InputStream | -| A.java:71:24:71:28 | input | semmle.label | input | -| A.java:72:24:72:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | -| A.java:72:46:72:50 | input : InputStream | semmle.label | input : InputStream | -| A.java:77:25:77:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| A.java:78:26:78:30 | input | semmle.label | input | -| A.java:79:30:79:34 | input | semmle.label | input | -| A.java:80:28:80:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | -| A.java:80:50:80:54 | input : InputStream | semmle.label | input : InputStream | -| A.java:81:24:81:28 | input | semmle.label | input | -| A.java:82:24:82:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | -| A.java:82:46:82:50 | input : InputStream | semmle.label | input : InputStream | -| A.java:97:25:97:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| A.java:98:26:98:30 | input | semmle.label | input | -| A.java:99:30:99:34 | input | semmle.label | input | -| A.java:100:28:100:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | -| A.java:100:50:100:54 | input : InputStream | semmle.label | input : InputStream | -| A.java:101:24:101:28 | input | semmle.label | input | -| A.java:102:24:102:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | -| A.java:102:46:102:50 | input : InputStream | semmle.label | input : InputStream | +| A.java:17:31:17:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:18:28:18:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream | +| A.java:18:50:18:60 | inputStream : InputStream | semmle.label | inputStream : InputStream | +| A.java:19:12:19:13 | in | semmle.label | in | +| A.java:33:31:33:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:34:28:34:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream | +| A.java:34:50:34:60 | inputStream : InputStream | semmle.label | inputStream : InputStream | +| A.java:35:12:35:13 | in | semmle.label | in | +| A.java:45:31:45:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:46:20:46:46 | new XMLDecoder(...) : XMLDecoder | semmle.label | new XMLDecoder(...) : XMLDecoder | +| A.java:46:35:46:45 | inputStream : InputStream | semmle.label | inputStream : InputStream | +| A.java:47:12:47:12 | d | semmle.label | d | +| A.java:52:31:52:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:53:21:53:54 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader | +| A.java:53:43:53:53 | inputStream : InputStream | semmle.label | inputStream : InputStream | +| A.java:54:23:54:28 | reader | semmle.label | reader | +| A.java:59:19:59:50 | new Input(...) : Input | semmle.label | new Input(...) : Input | +| A.java:59:29:59:49 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:60:28:60:32 | input | semmle.label | input | +| A.java:61:34:61:38 | input | semmle.label | input | +| A.java:62:40:62:44 | input | semmle.label | input | +| A.java:80:25:80:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:81:26:81:30 | input | semmle.label | input | +| A.java:82:30:82:34 | input | semmle.label | input | +| A.java:83:28:83:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | +| A.java:83:50:83:54 | input : InputStream | semmle.label | input : InputStream | +| A.java:84:24:84:28 | input | semmle.label | input | +| A.java:85:24:85:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | +| A.java:85:46:85:50 | input : InputStream | semmle.label | input : InputStream | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:91:26:91:30 | input | semmle.label | input | +| A.java:92:30:92:34 | input | semmle.label | input | +| A.java:93:28:93:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | +| A.java:93:50:93:54 | input : InputStream | semmle.label | input : InputStream | +| A.java:94:24:94:28 | input | semmle.label | input | +| A.java:95:24:95:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | +| A.java:95:46:95:50 | input : InputStream | semmle.label | input : InputStream | +| A.java:110:25:110:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:111:26:111:30 | input | semmle.label | input | +| A.java:112:30:112:34 | input | semmle.label | input | +| A.java:113:28:113:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | +| A.java:113:50:113:54 | input : InputStream | semmle.label | input : InputStream | +| A.java:114:24:114:28 | input | semmle.label | input | +| A.java:115:24:115:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | +| A.java:115:46:115:50 | input : InputStream | semmle.label | input : InputStream | | B.java:7:31:7:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | | B.java:8:29:8:39 | inputStream | semmle.label | inputStream | | B.java:12:31:12:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.ext.yml b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.ext.yml new file mode 100644 index 000000000000..2bc52cf78fd7 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.ext.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sourceModel + data: + - ["unsafedeserialization", "A", False, "getTaintedObjectInput", "()", "", "ReturnValue", "remote", "manual"] + - ["unsafedeserialization", "A", False, "getTaintedMyObjectInput", "()", "", "ReturnValue", "remote", "manual"] diff --git a/java/ql/test/query-tests/security/CWE-502/com/example/MyObjectInput.java b/java/ql/test/query-tests/security/CWE-502/com/example/MyObjectInput.java new file mode 100644 index 000000000000..20eef41ed29b --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-502/com/example/MyObjectInput.java @@ -0,0 +1,109 @@ +package com.example; +import java.io.*; + +public final class MyObjectInput implements ObjectInput { + + @Override + public Object readObject() throws ClassNotFoundException, IOException { + return null; + } + + @Override + public int read() throws IOException { + return 0; + } + + @Override + public int read(byte[] b) throws IOException { + return 0; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return 0; + } + + @Override + public long skip(long n) throws IOException { + return 0; + } + + @Override + public int available() throws IOException { + return 0; + } + + @Override + public void close() throws IOException {} + + @Override + public void readFully(byte[] b) throws IOException {} + + @Override + public void readFully(byte[] b, int off, int len) throws IOException {} + + @Override + public int skipBytes(int n) throws IOException { + return 0; + } + + @Override + public boolean readBoolean() throws IOException { + return false; + } + + @Override + public byte readByte() throws IOException { + return 0; + } + + @Override + public int readUnsignedByte() throws IOException { + return 0; + } + + @Override + public short readShort() throws IOException { + return 0; + } + + @Override + public int readUnsignedShort() throws IOException { + return 0; + } + + @Override + public char readChar() throws IOException { + return 0; + } + + @Override + public int readInt() throws IOException { + return 0; + } + + @Override + public long readLong() throws IOException { + return 0; + } + + @Override + public float readFloat() throws IOException { + return 0; + } + + @Override + public double readDouble() throws IOException { + return 0; + } + + @Override + public String readLine() throws IOException { + return null; + } + + @Override + public String readUTF() throws IOException { + return null; + } +} From 8e4bd1a102bcb47f2552b09ce021edbc9c672cd1 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 11 Jul 2025 10:23:41 +0100 Subject: [PATCH 3/4] Add sink for ObjectInput.readObject to make test pass --- java/ql/lib/semmle/code/java/JDK.qll | 5 + .../security/UnsafeDeserializationQuery.qll | 19 +++- .../test/query-tests/security/CWE-502/A.java | 8 +- .../CWE-502/UnsafeDeserialization.expected | 98 ++++++++++--------- 4 files changed, 78 insertions(+), 52 deletions(-) diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll index 897e857ba108..bdc2fb92fa05 100644 --- a/java/ql/lib/semmle/code/java/JDK.qll +++ b/java/ql/lib/semmle/code/java/JDK.qll @@ -211,6 +211,11 @@ class TypeObjectOutputStream extends RefType { TypeObjectOutputStream() { this.hasQualifiedName("java.io", "ObjectOutputStream") } } +/** The type `java.io.ObjectInput`. */ +class TypeObjectInput extends RefType { + TypeObjectInput() { this.hasQualifiedName("java.io", "ObjectInput") } +} + /** The type `java.io.ObjectInputStream`. */ class TypeObjectInputStream extends RefType { TypeObjectInputStream() { this.hasQualifiedName("java.io", "ObjectInputStream") } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index 541942c6036c..7489fbd00ef9 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -23,10 +23,17 @@ private import semmle.code.java.frameworks.google.Gson private import semmle.code.java.frameworks.apache.Lang private import semmle.code.java.Reflection -private class ObjectInputStreamReadObjectMethod extends Method { - ObjectInputStreamReadObjectMethod() { +private class ObjectInputReadObjectMethod extends Method { + ObjectInputReadObjectMethod() { + this.getDeclaringType().getASourceSupertype*() instanceof TypeObjectInput and + this.hasName("readObject") + } +} + +private class ObjectInputStreamReadUnsharedMethod extends Method { + ObjectInputStreamReadUnsharedMethod() { this.getDeclaringType().getASourceSupertype*() instanceof TypeObjectInputStream and - (this.hasName("readObject") or this.hasName("readUnshared")) + this.hasName("readUnshared") } } @@ -147,7 +154,11 @@ private module SafeKryoFlow = DataFlow::Global; */ predicate unsafeDeserialization(MethodCall ma, Expr sink) { exists(Method m | m = ma.getMethod() | - m instanceof ObjectInputStreamReadObjectMethod and + m instanceof ObjectInputReadObjectMethod and + sink = ma.getQualifier() and + not DataFlow::exprNode(sink).getTypeBound() instanceof SafeObjectInputStreamType + or + m instanceof ObjectInputStreamReadUnsharedMethod and sink = ma.getQualifier() and not DataFlow::exprNode(sink).getTypeBound() instanceof SafeObjectInputStreamType or diff --git a/java/ql/test/query-tests/security/CWE-502/A.java b/java/ql/test/query-tests/security/CWE-502/A.java index d36d1d3c0b86..6d52babf693f 100644 --- a/java/ql/test/query-tests/security/CWE-502/A.java +++ b/java/ql/test/query-tests/security/CWE-502/A.java @@ -20,13 +20,13 @@ public Object deserialize1a(Socket sock) throws java.io.IOException, ClassNotFou } public Object deserialize2() throws java.io.IOException, ClassNotFoundException { - ObjectInput objectInput = A.getTaintedObjectInput(); // $ MISSING: Source - return objectInput.readObject(); // $ MISSING: Alert + ObjectInput objectInput = A.getTaintedObjectInput(); // $ Source + return objectInput.readObject(); // $ Alert } public Object deserialize3() throws java.io.IOException, ClassNotFoundException { - MyObjectInput objectInput = A.getTaintedMyObjectInput(); // $ MISSING: Source - return objectInput.readObject(); // $ MISSING: Alert + MyObjectInput objectInput = A.getTaintedMyObjectInput(); // $ Source + return objectInput.readObject(); // $ Alert } public Object deserialize4(Socket sock) throws java.io.IOException, ClassNotFoundException { diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected index 599b85603c8b..89ddc0c1bf9e 100644 --- a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected +++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected @@ -1,5 +1,7 @@ #select | A.java:19:12:19:26 | readObject(...) | A.java:17:31:17:51 | getInputStream(...) : InputStream | A.java:19:12:19:13 | in | Unsafe deserialization depends on a $@. | A.java:17:31:17:51 | getInputStream(...) | user-provided value | +| A.java:24:12:24:35 | readObject(...) | A.java:23:31:23:55 | getTaintedObjectInput(...) : ObjectInput | A.java:24:12:24:22 | objectInput | Unsafe deserialization depends on a $@. | A.java:23:31:23:55 | getTaintedObjectInput(...) | user-provided value | +| A.java:29:12:29:35 | readObject(...) | A.java:28:33:28:59 | getTaintedMyObjectInput(...) : MyObjectInput | A.java:29:12:29:22 | objectInput | Unsafe deserialization depends on a $@. | A.java:28:33:28:59 | getTaintedMyObjectInput(...) | user-provided value | | A.java:35:12:35:28 | readUnshared(...) | A.java:33:31:33:51 | getInputStream(...) : InputStream | A.java:35:12:35:13 | in | Unsafe deserialization depends on a $@. | A.java:33:31:33:51 | getInputStream(...) | user-provided value | | A.java:47:12:47:25 | readObject(...) | A.java:45:31:45:51 | getInputStream(...) : InputStream | A.java:47:12:47:12 | d | Unsafe deserialization depends on a $@. | A.java:45:31:45:51 | getInputStream(...) | user-provided value | | A.java:54:12:54:29 | fromXML(...) | A.java:52:31:52:51 | getInputStream(...) : InputStream | A.java:54:23:54:28 | reader | Unsafe deserialization depends on a $@. | A.java:52:31:52:51 | getInputStream(...) | user-provided value | @@ -75,56 +77,58 @@ edges | A.java:17:31:17:51 | getInputStream(...) : InputStream | A.java:18:50:18:60 | inputStream : InputStream | provenance | Src:MaD:1 | | A.java:17:31:17:51 | getInputStream(...) : InputStream | A.java:19:12:19:13 | in | provenance | Src:MaD:1 inputStreamWrapper | | A.java:18:28:18:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:19:12:19:13 | in | provenance | | -| A.java:18:50:18:60 | inputStream : InputStream | A.java:18:28:18:61 | new ObjectInputStream(...) : ObjectInputStream | provenance | MaD:11 | +| A.java:18:50:18:60 | inputStream : InputStream | A.java:18:28:18:61 | new ObjectInputStream(...) : ObjectInputStream | provenance | MaD:13 | +| A.java:23:31:23:55 | getTaintedObjectInput(...) : ObjectInput | A.java:24:12:24:22 | objectInput | provenance | Src:MaD:5 | +| A.java:28:33:28:59 | getTaintedMyObjectInput(...) : MyObjectInput | A.java:29:12:29:22 | objectInput | provenance | Src:MaD:4 | | A.java:33:31:33:51 | getInputStream(...) : InputStream | A.java:34:50:34:60 | inputStream : InputStream | provenance | Src:MaD:1 | | A.java:33:31:33:51 | getInputStream(...) : InputStream | A.java:35:12:35:13 | in | provenance | Src:MaD:1 inputStreamWrapper | | A.java:34:28:34:61 | new ObjectInputStream(...) : ObjectInputStream | A.java:35:12:35:13 | in | provenance | | -| A.java:34:50:34:60 | inputStream : InputStream | A.java:34:28:34:61 | new ObjectInputStream(...) : ObjectInputStream | provenance | MaD:11 | +| A.java:34:50:34:60 | inputStream : InputStream | A.java:34:28:34:61 | new ObjectInputStream(...) : ObjectInputStream | provenance | MaD:13 | | A.java:45:31:45:51 | getInputStream(...) : InputStream | A.java:46:35:46:45 | inputStream : InputStream | provenance | Src:MaD:1 | | A.java:46:20:46:46 | new XMLDecoder(...) : XMLDecoder | A.java:47:12:47:12 | d | provenance | | -| A.java:46:35:46:45 | inputStream : InputStream | A.java:46:20:46:46 | new XMLDecoder(...) : XMLDecoder | provenance | MaD:7 | +| A.java:46:35:46:45 | inputStream : InputStream | A.java:46:20:46:46 | new XMLDecoder(...) : XMLDecoder | provenance | MaD:9 | | A.java:52:31:52:51 | getInputStream(...) : InputStream | A.java:53:43:53:53 | inputStream : InputStream | provenance | Src:MaD:1 | | A.java:53:21:53:54 | new InputStreamReader(...) : InputStreamReader | A.java:54:23:54:28 | reader | provenance | | -| A.java:53:43:53:53 | inputStream : InputStream | A.java:53:21:53:54 | new InputStreamReader(...) : InputStreamReader | provenance | MaD:10 | +| A.java:53:43:53:53 | inputStream : InputStream | A.java:53:21:53:54 | new InputStreamReader(...) : InputStreamReader | provenance | MaD:12 | | A.java:59:19:59:50 | new Input(...) : Input | A.java:60:28:60:32 | input | provenance | | | A.java:59:19:59:50 | new Input(...) : Input | A.java:61:34:61:38 | input | provenance | | | A.java:59:19:59:50 | new Input(...) : Input | A.java:62:40:62:44 | input | provenance | | -| A.java:59:29:59:49 | getInputStream(...) : InputStream | A.java:59:19:59:50 | new Input(...) : Input | provenance | Src:MaD:1 MaD:5 | +| A.java:59:29:59:49 | getInputStream(...) : InputStream | A.java:59:19:59:50 | new Input(...) : Input | provenance | Src:MaD:1 MaD:7 | | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:81:26:81:30 | input | provenance | Src:MaD:1 | | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:82:30:82:34 | input | provenance | Src:MaD:1 | | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:83:50:83:54 | input : InputStream | provenance | Src:MaD:1 | | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:84:24:84:28 | input | provenance | Src:MaD:1 | | A.java:80:25:80:45 | getInputStream(...) : InputStream | A.java:85:46:85:50 | input : InputStream | provenance | Src:MaD:1 | -| A.java:83:50:83:54 | input : InputStream | A.java:83:28:83:55 | new InputStreamReader(...) | provenance | MaD:10 | -| A.java:85:46:85:50 | input : InputStream | A.java:85:24:85:51 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:83:50:83:54 | input : InputStream | A.java:83:28:83:55 | new InputStreamReader(...) | provenance | MaD:12 | +| A.java:85:46:85:50 | input : InputStream | A.java:85:24:85:51 | new InputStreamReader(...) | provenance | MaD:12 | | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:91:26:91:30 | input | provenance | Src:MaD:1 | | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:92:30:92:34 | input | provenance | Src:MaD:1 | | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:50:93:54 | input : InputStream | provenance | Src:MaD:1 | | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:94:24:94:28 | input | provenance | Src:MaD:1 | | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:46:95:50 | input : InputStream | provenance | Src:MaD:1 | -| A.java:93:50:93:54 | input : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) | provenance | MaD:10 | -| A.java:95:46:95:50 | input : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:93:50:93:54 | input : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) | provenance | MaD:12 | +| A.java:95:46:95:50 | input : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) | provenance | MaD:12 | | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:111:26:111:30 | input | provenance | Src:MaD:1 | | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:112:30:112:34 | input | provenance | Src:MaD:1 | | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:113:50:113:54 | input : InputStream | provenance | Src:MaD:1 | | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:114:24:114:28 | input | provenance | Src:MaD:1 | | A.java:110:25:110:45 | getInputStream(...) : InputStream | A.java:115:46:115:50 | input : InputStream | provenance | Src:MaD:1 | -| A.java:113:50:113:54 | input : InputStream | A.java:113:28:113:55 | new InputStreamReader(...) | provenance | MaD:10 | -| A.java:115:46:115:50 | input : InputStream | A.java:115:24:115:51 | new InputStreamReader(...) | provenance | MaD:10 | +| A.java:113:50:113:54 | input : InputStream | A.java:113:28:113:55 | new InputStreamReader(...) | provenance | MaD:12 | +| A.java:115:46:115:50 | input : InputStream | A.java:115:24:115:51 | new InputStreamReader(...) | provenance | MaD:12 | | B.java:7:31:7:51 | getInputStream(...) : InputStream | B.java:8:29:8:39 | inputStream | provenance | Src:MaD:1 | | B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:14:5:14:15 | inputStream : InputStream | provenance | Src:MaD:1 | -| B.java:14:5:14:15 | inputStream : InputStream | B.java:14:22:14:26 | bytes [post update] : byte[] | provenance | MaD:9 | +| B.java:14:5:14:15 | inputStream : InputStream | B.java:14:22:14:26 | bytes [post update] : byte[] | provenance | MaD:11 | | B.java:14:22:14:26 | bytes [post update] : byte[] | B.java:15:23:15:27 | bytes | provenance | | | B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:21:5:21:15 | inputStream : InputStream | provenance | Src:MaD:1 | -| B.java:21:5:21:15 | inputStream : InputStream | B.java:21:22:21:26 | bytes [post update] : byte[] | provenance | MaD:9 | +| B.java:21:5:21:15 | inputStream : InputStream | B.java:21:22:21:26 | bytes [post update] : byte[] | provenance | MaD:11 | | B.java:21:22:21:26 | bytes [post update] : byte[] | B.java:22:27:22:31 | bytes : byte[] | provenance | | | B.java:22:16:22:32 | new String(...) : String | B.java:23:29:23:29 | s | provenance | | -| B.java:22:27:22:31 | bytes : byte[] | B.java:22:16:22:32 | new String(...) : String | provenance | MaD:13 | +| B.java:22:27:22:31 | bytes : byte[] | B.java:22:16:22:32 | new String(...) : String | provenance | MaD:15 | | B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:29:5:29:15 | inputStream : InputStream | provenance | Src:MaD:1 | -| B.java:29:5:29:15 | inputStream : InputStream | B.java:29:22:29:26 | bytes [post update] : byte[] | provenance | MaD:9 | +| B.java:29:5:29:15 | inputStream : InputStream | B.java:29:22:29:26 | bytes [post update] : byte[] | provenance | MaD:11 | | B.java:29:22:29:26 | bytes [post update] : byte[] | B.java:30:27:30:31 | bytes : byte[] | provenance | | | B.java:30:16:30:32 | new String(...) : String | B.java:31:23:31:23 | s | provenance | | -| B.java:30:27:30:31 | bytes : byte[] | B.java:30:16:30:32 | new String(...) : String | provenance | MaD:13 | +| B.java:30:27:30:31 | bytes : byte[] | B.java:30:16:30:32 | new String(...) : String | provenance | MaD:15 | | C.java:23:17:23:44 | getParameter(...) : String | C.java:24:13:24:16 | data | provenance | Src:MaD:3 | | C.java:23:17:23:44 | getParameter(...) : String | C.java:25:19:25:22 | data | provenance | Src:MaD:3 | | C.java:23:17:23:44 | getParameter(...) : String | C.java:26:25:26:28 | data | provenance | Src:MaD:3 | @@ -142,28 +146,28 @@ edges | C.java:52:18:52:37 | new YamlReader(...) : YamlReader | C.java:54:3:54:3 | r | provenance | | | C.java:52:18:52:37 | new YamlReader(...) : YamlReader | C.java:55:3:55:3 | r | provenance | | | C.java:52:33:52:36 | data : String | C.java:52:18:52:37 | new YamlReader(...) : YamlReader | provenance | Config | -| C.java:60:18:60:45 | getParameter(...) : String | C.java:60:18:60:56 | getBytes(...) : byte[] | provenance | Src:MaD:3 MaD:14 | +| C.java:60:18:60:45 | getParameter(...) : String | C.java:60:18:60:56 | getBytes(...) : byte[] | provenance | Src:MaD:3 MaD:16 | | C.java:60:18:60:56 | getBytes(...) : byte[] | C.java:61:55:61:59 | bytes : byte[] | provenance | | | C.java:60:18:60:56 | getBytes(...) : byte[] | C.java:62:48:62:50 | bis : ByteArrayInputStream | provenance | inputStreamWrapper | | C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:62:48:62:50 | bis : ByteArrayInputStream | provenance | | -| C.java:61:55:61:59 | bytes : byte[] | C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | provenance | MaD:8 | +| C.java:61:55:61:59 | bytes : byte[] | C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | provenance | MaD:10 | | C.java:62:31:62:51 | new HessianInput(...) : HessianInput | C.java:63:3:63:14 | hessianInput | provenance | | | C.java:62:31:62:51 | new HessianInput(...) : HessianInput | C.java:64:3:64:14 | hessianInput | provenance | | | C.java:62:48:62:50 | bis : ByteArrayInputStream | C.java:62:31:62:51 | new HessianInput(...) : HessianInput | provenance | Config | -| C.java:69:18:69:45 | getParameter(...) : String | C.java:69:18:69:56 | getBytes(...) : byte[] | provenance | Src:MaD:3 MaD:14 | +| C.java:69:18:69:45 | getParameter(...) : String | C.java:69:18:69:56 | getBytes(...) : byte[] | provenance | Src:MaD:3 MaD:16 | | C.java:69:18:69:56 | getBytes(...) : byte[] | C.java:70:55:70:59 | bytes : byte[] | provenance | | | C.java:69:18:69:56 | getBytes(...) : byte[] | C.java:71:50:71:52 | bis : ByteArrayInputStream | provenance | inputStreamWrapper | | C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:71:50:71:52 | bis : ByteArrayInputStream | provenance | | -| C.java:70:55:70:59 | bytes : byte[] | C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | provenance | MaD:8 | +| C.java:70:55:70:59 | bytes : byte[] | C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | provenance | MaD:10 | | C.java:71:32:71:53 | new Hessian2Input(...) : Hessian2Input | C.java:72:3:72:14 | hessianInput | provenance | | | C.java:71:32:71:53 | new Hessian2Input(...) : Hessian2Input | C.java:73:3:73:14 | hessianInput | provenance | | | C.java:71:50:71:52 | bis : ByteArrayInputStream | C.java:71:32:71:53 | new Hessian2Input(...) : Hessian2Input | provenance | Config | -| C.java:79:43:79:70 | getParameter(...) : String | C.java:79:26:79:71 | new StringReader(...) | provenance | Src:MaD:3 MaD:12 | -| C.java:84:27:84:54 | getParameter(...) : String | C.java:84:27:84:65 | getBytes(...) : byte[] | provenance | Src:MaD:3 MaD:14 | +| C.java:79:43:79:70 | getParameter(...) : String | C.java:79:26:79:71 | new StringReader(...) | provenance | Src:MaD:3 MaD:14 | +| C.java:84:27:84:54 | getParameter(...) : String | C.java:84:27:84:65 | getBytes(...) : byte[] | provenance | Src:MaD:3 MaD:16 | | C.java:84:27:84:65 | getBytes(...) : byte[] | C.java:85:54:85:67 | serializedData : byte[] | provenance | | | C.java:84:27:84:65 | getBytes(...) : byte[] | C.java:86:45:86:46 | is : ByteArrayInputStream | provenance | inputStreamWrapper | | C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:86:45:86:46 | is : ByteArrayInputStream | provenance | | -| C.java:85:54:85:67 | serializedData : byte[] | C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | provenance | MaD:8 | +| C.java:85:54:85:67 | serializedData : byte[] | C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | provenance | MaD:10 | | C.java:86:29:86:47 | new BurlapInput(...) : BurlapInput | C.java:87:3:87:13 | burlapInput | provenance | | | C.java:86:45:86:46 | is : ByteArrayInputStream | C.java:86:29:86:47 | new BurlapInput(...) : BurlapInput | provenance | Config | | C.java:86:45:86:46 | is : ByteArrayInputStream | C.java:90:21:90:22 | is : ByteArrayInputStream | provenance | | @@ -177,12 +181,12 @@ edges | GsonServlet.java:53:23:53:46 | getParameter(...) : String | GsonServlet.java:60:40:60:43 | json | provenance | Src:MaD:3 | | JabsorbServlet.java:89:23:89:46 | getParameter(...) : String | JabsorbServlet.java:93:48:93:51 | json : String | provenance | Src:MaD:3 | | JabsorbServlet.java:93:33:93:52 | new JSONObject(...) : JSONObject | JabsorbServlet.java:102:83:102:92 | jsonObject | provenance | | -| JabsorbServlet.java:93:48:93:51 | json : String | JabsorbServlet.java:93:33:93:52 | new JSONObject(...) : JSONObject | provenance | MaD:16 | +| JabsorbServlet.java:93:48:93:51 | json : String | JabsorbServlet.java:93:33:93:52 | new JSONObject(...) : JSONObject | provenance | MaD:18 | | JabsorbServlet.java:110:23:110:46 | getParameter(...) : String | JabsorbServlet.java:116:52:116:55 | json | provenance | Src:MaD:3 | -| JacksonTest.java:20:25:20:47 | getInputStream(...) : InputStream | JacksonTest.java:20:54:20:58 | bytes [post update] : byte[] | provenance | Src:MaD:1 MaD:9 | +| JacksonTest.java:20:25:20:47 | getInputStream(...) : InputStream | JacksonTest.java:20:54:20:58 | bytes [post update] : byte[] | provenance | Src:MaD:1 MaD:11 | | JacksonTest.java:20:54:20:58 | bytes [post update] : byte[] | JacksonTest.java:21:46:21:50 | bytes : byte[] | provenance | | | JacksonTest.java:21:35:21:57 | new String(...) : String | JacksonTest.java:22:28:22:35 | jexlExpr : String | provenance | | -| JacksonTest.java:21:46:21:50 | bytes : byte[] | JacksonTest.java:21:35:21:57 | new String(...) : String | provenance | MaD:13 | +| JacksonTest.java:21:46:21:50 | bytes : byte[] | JacksonTest.java:21:35:21:57 | new String(...) : String | provenance | MaD:15 | | JacksonTest.java:22:28:22:35 | jexlExpr : String | JacksonTest.java:74:32:74:37 | string : String | provenance | | | JacksonTest.java:22:28:22:35 | jexlExpr : String | JacksonTest.java:83:32:83:37 | string : String | provenance | | | JacksonTest.java:22:28:22:35 | jexlExpr : String | JacksonTest.java:92:32:92:37 | string : String | provenance | | @@ -197,14 +201,14 @@ edges | JacksonTest.java:139:32:139:37 | string : String | JacksonTest.java:142:30:142:35 | string | provenance | | | JacksonTest.java:148:32:148:37 | string : String | JacksonTest.java:151:62:151:67 | string : String | provenance | | | JacksonTest.java:151:62:151:67 | string : String | JacksonTest.java:151:31:151:68 | createParser(...) | provenance | Config | -| JacksonTest.java:151:62:151:67 | string : String | JacksonTest.java:151:31:151:68 | createParser(...) | provenance | MaD:6 | +| JacksonTest.java:151:62:151:67 | string : String | JacksonTest.java:151:31:151:68 | createParser(...) | provenance | MaD:8 | | JacksonTest.java:157:32:157:37 | string : String | JacksonTest.java:160:48:160:53 | string : String | provenance | | | JacksonTest.java:160:48:160:53 | string : String | JacksonTest.java:160:32:160:54 | readTree(...) | provenance | Config | | JacksonTest.java:166:32:166:36 | input : String | JacksonTest.java:167:30:167:34 | input : String | provenance | | -| JacksonTest.java:167:30:167:34 | input : String | JacksonTest.java:167:30:167:45 | split(...) : String[] | provenance | MaD:15 | +| JacksonTest.java:167:30:167:34 | input : String | JacksonTest.java:167:30:167:45 | split(...) : String[] | provenance | MaD:17 | | JacksonTest.java:167:30:167:45 | split(...) : String[] | JacksonTest.java:172:30:172:33 | data | provenance | | | JacksonTest.java:178:32:178:36 | input : String | JacksonTest.java:179:30:179:34 | input : String | provenance | | -| JacksonTest.java:179:30:179:34 | input : String | JacksonTest.java:179:30:179:45 | split(...) : String[] | provenance | MaD:15 | +| JacksonTest.java:179:30:179:34 | input : String | JacksonTest.java:179:30:179:45 | split(...) : String[] | provenance | MaD:17 | | JacksonTest.java:179:30:179:45 | split(...) : String[] | JacksonTest.java:183:30:183:33 | data | provenance | | | JoddJsonServlet.java:32:23:32:46 | getParameter(...) : String | JoddJsonServlet.java:45:37:45:40 | json | provenance | Src:MaD:3 | | JoddJsonServlet.java:32:23:32:46 | getParameter(...) : String | JoddJsonServlet.java:47:56:47:59 | json | provenance | Src:MaD:3 | @@ -213,32 +217,38 @@ edges | JoddJsonServlet.java:58:23:58:46 | getParameter(...) : String | JoddJsonServlet.java:63:39:63:42 | json | provenance | Src:MaD:3 | | ObjectMessageTest.java:6:27:6:41 | message : Message | ObjectMessageTest.java:7:26:7:32 | message | provenance | Src:MaD:2 | | ParcelableEntity.java:29:50:29:62 | parcel : Parcel | ParcelableEntity.java:32:44:32:49 | parcel : Parcel | provenance | | -| ParcelableEntity.java:32:44:32:49 | parcel : Parcel | ParcelableEntity.java:32:44:32:62 | readString(...) | provenance | MaD:4 | +| ParcelableEntity.java:32:44:32:49 | parcel : Parcel | ParcelableEntity.java:32:44:32:62 | readString(...) | provenance | MaD:6 | | TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | provenance | inputStreamWrapper | | TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | provenance | | -| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | provenance | MaD:11 | +| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | provenance | MaD:13 | models | 1 | Source: java.net; Socket; false; getInputStream; (); ; ReturnValue; remote; manual | | 2 | Source: javax.jms; MessageListener; true; onMessage; (Message); ; Parameter[0]; remote; manual | | 3 | Source: javax.servlet; ServletRequest; false; getParameter; (String); ; ReturnValue; remote; manual | -| 4 | Summary: android.os; Parcel; false; readString; ; ; Argument[this]; ReturnValue; taint; manual | -| 5 | Summary: com.esotericsoftware.kryo.io; Input; false; Input; ; ; Argument[0]; Argument[this]; taint; manual | -| 6 | Summary: com.fasterxml.jackson.core; JsonFactory; false; createParser; ; ; Argument[0]; ReturnValue; taint; manual | -| 7 | Summary: java.beans; XMLDecoder; false; XMLDecoder; ; ; Argument[0]; Argument[this]; taint; manual | -| 8 | Summary: java.io; ByteArrayInputStream; false; ByteArrayInputStream; ; ; Argument[0]; Argument[this]; taint; manual | -| 9 | Summary: java.io; InputStream; true; read; (byte[]); ; Argument[this]; Argument[0]; taint; manual | -| 10 | Summary: java.io; InputStreamReader; false; InputStreamReader; ; ; Argument[0]; Argument[this]; taint; manual | -| 11 | Summary: java.io; ObjectInputStream; false; ObjectInputStream; ; ; Argument[0]; Argument[this]; taint; manual | -| 12 | Summary: java.io; StringReader; false; StringReader; ; ; Argument[0]; Argument[this]; taint; manual | -| 13 | Summary: java.lang; String; false; String; ; ; Argument[0]; Argument[this]; taint; manual | -| 14 | Summary: java.lang; String; false; getBytes; ; ; Argument[this]; ReturnValue; taint; manual | -| 15 | Summary: java.lang; String; false; split; ; ; Argument[this]; ReturnValue; taint; manual | -| 16 | Summary: org.json; JSONObject; false; JSONObject; (String); ; Argument[0]; Argument[this]; taint; manual | +| 4 | Source: unsafedeserialization; A; false; getTaintedMyObjectInput; (); ; ReturnValue; remote; manual | +| 5 | Source: unsafedeserialization; A; false; getTaintedObjectInput; (); ; ReturnValue; remote; manual | +| 6 | Summary: android.os; Parcel; false; readString; ; ; Argument[this]; ReturnValue; taint; manual | +| 7 | Summary: com.esotericsoftware.kryo.io; Input; false; Input; ; ; Argument[0]; Argument[this]; taint; manual | +| 8 | Summary: com.fasterxml.jackson.core; JsonFactory; false; createParser; ; ; Argument[0]; ReturnValue; taint; manual | +| 9 | Summary: java.beans; XMLDecoder; false; XMLDecoder; ; ; Argument[0]; Argument[this]; taint; manual | +| 10 | Summary: java.io; ByteArrayInputStream; false; ByteArrayInputStream; ; ; Argument[0]; Argument[this]; taint; manual | +| 11 | Summary: java.io; InputStream; true; read; (byte[]); ; Argument[this]; Argument[0]; taint; manual | +| 12 | Summary: java.io; InputStreamReader; false; InputStreamReader; ; ; Argument[0]; Argument[this]; taint; manual | +| 13 | Summary: java.io; ObjectInputStream; false; ObjectInputStream; ; ; Argument[0]; Argument[this]; taint; manual | +| 14 | Summary: java.io; StringReader; false; StringReader; ; ; Argument[0]; Argument[this]; taint; manual | +| 15 | Summary: java.lang; String; false; String; ; ; Argument[0]; Argument[this]; taint; manual | +| 16 | Summary: java.lang; String; false; getBytes; ; ; Argument[this]; ReturnValue; taint; manual | +| 17 | Summary: java.lang; String; false; split; ; ; Argument[this]; ReturnValue; taint; manual | +| 18 | Summary: org.json; JSONObject; false; JSONObject; (String); ; Argument[0]; Argument[this]; taint; manual | nodes | A.java:17:31:17:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | | A.java:18:28:18:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream | | A.java:18:50:18:60 | inputStream : InputStream | semmle.label | inputStream : InputStream | | A.java:19:12:19:13 | in | semmle.label | in | +| A.java:23:31:23:55 | getTaintedObjectInput(...) : ObjectInput | semmle.label | getTaintedObjectInput(...) : ObjectInput | +| A.java:24:12:24:22 | objectInput | semmle.label | objectInput | +| A.java:28:33:28:59 | getTaintedMyObjectInput(...) : MyObjectInput | semmle.label | getTaintedMyObjectInput(...) : MyObjectInput | +| A.java:29:12:29:22 | objectInput | semmle.label | objectInput | | A.java:33:31:33:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | | A.java:34:28:34:61 | new ObjectInputStream(...) : ObjectInputStream | semmle.label | new ObjectInputStream(...) : ObjectInputStream | | A.java:34:50:34:60 | inputStream : InputStream | semmle.label | inputStream : InputStream | From 7764fbb664075a5df393eb749968d770843a218d Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 11 Jul 2025 11:01:51 +0100 Subject: [PATCH 4/4] Change note --- .../2025-07-11-unsafe-deserialization-extra-sink.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2025-07-11-unsafe-deserialization-extra-sink.md diff --git a/java/ql/lib/change-notes/2025-07-11-unsafe-deserialization-extra-sink.md b/java/ql/lib/change-notes/2025-07-11-unsafe-deserialization-extra-sink.md new file mode 100644 index 000000000000..26f745a2bb72 --- /dev/null +++ b/java/ql/lib/change-notes/2025-07-11-unsafe-deserialization-extra-sink.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The qualifiers of a calls to `readObject` on any classes that implement `java.io.ObjectInput` are now recognised as sinks for `java/unsafe-deserialization`. Previously this was only the case for classes which extend `java.io.ObjectInputStream`.