-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
This behavior may be security-relevant when JSONObject#fromJson(Class<T>) is used on untrusted input, so I am reporting it here as a public issue in line with the repository's published vulnerability-reporting guidance.
In release 20251224, JSONObject#fromJson(Class<T>) iterates clazz.getDeclaredFields(), calls Field#setAccessible(true), and assigns matching JSON values without excluding static fields:
JSON-java/src/main/java/org/json/JSONObject.java
Lines 3365 to 3378 in cf65368
| public <T> T fromJson(Class<T> clazz) { | |
| try { | |
| T obj = clazz.getDeclaredConstructor().newInstance(); | |
| for (Field field : clazz.getDeclaredFields()) { | |
| field.setAccessible(true); | |
| String fieldName = field.getName(); | |
| if (has(fieldName)) { | |
| Object value = get(fieldName); | |
| Type fieldType = field.getGenericType(); | |
| Object convertedValue = convertValue(value, fieldType); | |
| field.set(obj, convertedValue); | |
| } | |
| } | |
| return obj; |
As a result, deserialization can write not only per-instance state but also mutable declared class-level state on the caller-selected target type, subject to normal runtime access restrictions. That expands the binding surface beyond ordinary object population and may have integrity implications in applications that use fromJson() with untrusted JSON.
If helpful, I can provide a minimal reproducer and a regression test. A straightforward mitigation appears to be skipping static fields during binding.