1

Ok, after I have got several comments about clarifying my equestion, I now will break down the question to the very essentials:

In my code there is a get-method for a variable (field) named "socket", which represents a correctly defined Java network socket of the type "Socket". This is the get method:

public Socket getSocket() {
 return socket;
}

The Spotbugs analysis of this code snippet results in a warning, which looks like this (cited letterwise, but lines separated by ">"):

> Malicious code vulnerability
> Method returning array may expose internal representation
> May expose internal representation by retruning reference to mutable object
> [package].[class].getSocket() may expose internal representation by returning [class].socket

If I modify the above code snippet to:

public Socket getSocket() {
 List<Socket> sockets = new ArrayList<>();
 sockets.add(socket);
 List<Socket> immutableSockets = Collections.unmodifiableList(sockets);
 return immutableSockets.get(0);
}

the Spotbugs warning vanishes.

I do not understand why, for the following reason: Spotbug analyzes the byte code, not the source code. So, if the latter code snipped just returns the reference to the mutable object likewise the first snippet, the byte code should be the same for both snippets. Up to now I have not concerned myself with details of Java compiler optimization algorithms but compilers usually optimize code snippets of such simple structure having the same result to the same machine level code (however, this may be a wrong perception). So, the latter "work around", in my eyes, should not have any effect on the Spotbugs warning, but it has, as noted above.

Now, from my point of view, there are three explanations right away:

  1. My understanding of Spotbugs is wrong and it analyzes not the byte code but at least the source code as well and, therefore, can be cheated by the second snippet as compared to the first one.
  2. This is a bug in Spotbugs.
  3. The second code snippet does not simply return the same reference to a mutable object, like the first one.

Finally I want to note, that this "work around" does work for any kind of reference to a mutable object, which is subject to a corresponding Spotbugs warning of the same kind as noted above, i.e., also for warnings leaded by "Storing reference to mutable object."

I do hope, that there is somebody out there to clarify this dubious situation and to give a satisfactory explanation for this behavior.

Finally let me note that, if the question is still not clear enough, it may be closed. This then means to me, that the observed behavior is not important enough to be considered more closely and I will not care either any more.

OK, I see that more clarification to my question is required. Let's try another approach:
First: the socket thing is only an example. The socket may be replaced by any arbitrary object, the Situation stays the same.
Second: Spotbugs analyzes the byte code, not the source code. Naming conventions and code structures, which do not alter anything should be irrelevant in my eyes, as the byte code still shows the problem of referencing a mutable object. So, both snippets should generate the same warning if both of them simply return a reference to a mutable object, the one directly and the other one as a list element. Why don't they do this? THIS is my question.

rebit
  • 51
  • 5
  • 1
    Is the code you show the old vulnerable code? Or the new fixed code? What is the difference between the vulnerable and fixed code? – Some programmer dude Jul 08 '22 at 09:43
  • 1
    Could you provide the exact message/error code from Spotbugs ? If the code that you show "fix" the issue and the "erroneous" code was a plain getter for "socket", it's just a trick to cheat Spotbugs, because your are fixing nothing. – Julien Jul 08 '22 at 09:45
  • 3
    My gut feeling is the code works around the alarm but does not solve it. Please show the exact vulnerability, the vulnerable code and the modification you did to mitigate it. – Queeg Jul 08 '22 at 09:53
  • Voting to close as its missing detail. Its hard to tell what exact message you are talking about, a quick google search doesnt find it. Impossible to tell what exactly you are referring to without you showing the old code. – Zabuzard Jul 08 '22 at 09:55
  • Minor note, to put something into an unmodifiable list, you can also just do `List.of(foo)`. – Zabuzard Jul 08 '22 at 09:56
  • 2
    My wild guess would be that the "vulernaribility" was referring to exposing a mutable object, such as the `socket` via the getter. If thats the case, then you did not fix the issue at all but just tricked Spotbugs. The correct action would be to redesign and not expose the socket in the first place. Move all use-cases into the class instead and keep the socket an internal implementation detail. The alternative, but not in this case, is to expose an immutable wrapper around the actual object or a copy. But that would not make much sense for a socket. – Zabuzard Jul 08 '22 at 09:59
  • Once the function returns, both `sockets` and `immutableSockets` are up for garbage collection. What you return will still be a reference to the original `socket` object. – Some programmer dude Jul 08 '22 at 10:00
  • As it stands, your question is unclear, and may be closed. Can you modify it to show, in sequence: [1] The exact original code snippet. [2] Any related messages from SpotBugs for that code, in text and screen shot form. [3] The revised code. [4] Your specific question(s). Closely relate your question(s) to the modified code, rather than just raising abstract concerns. (I realize that some of that information is already in your question, but it is presented in a jumbled and disorganized manner.) – skomisa Jul 08 '22 at 15:45
  • Your modified method does effectively the same as your original one. You're just wrapping the socket in a list and then unwrap it. I think you have just tricked Spotbugs by adding complexity to your code. Tools like Spotbugs are no holy grail, instead, they're – indeed – tools. – MC Emperor Jul 09 '22 at 17:56

2 Answers2

2

Your first code

public Socket getSocket() {
    return socket;
}

and the second code

public Socket getSocket() {
    List<Socket> sockets = new ArrayList<>();
    sockets.add(socket);
    List<Socket> immutableSockets = Collections.unmodifiableList(sockets);
    return immutableSockets.get(0);
}

are not resulting in the same byte code. Your statement

So, if the latter code snipped just returns the reference to the mutable object likewise the first snippet, the byte code should be the same for both snippets.

is simply not true. The first one only returns the value of a field, the second one involves different classes and method calls. It just happens to do kinda the same thing as in returning the field this.socket, only that the second code is doing it in a more "obfuscated" way. The Spotbugs library has only a limited set of patterns/detections, so it can't see that eventually the second code will leak the internal mutable object of your class.

Progman
  • 16,827
  • 6
  • 33
  • 48
  • Thank you, that's what I wanted to know. In the end, the issue came up, as the class was final, all fields private and final and no setters provided - nevertheless SB moaned. Only this "obsfucation" made it "happy". Like a screwdriver, which first refuses to fit to the screw and finally breaks. :( – rebit Jul 09 '22 at 22:06
  • @rebit There might be false positives in what Spotbugs is finding, but you shouldn't simply try to circumvent the found issues by obfuscating the code in a way that the warning is gone, the underlying problem might be still there (like leaking internal mutable objects). You should rather investigate your class if the found issue/warning is real or not (but that might be a different question). – Progman Jul 09 '22 at 22:12
  • I'm **sure** you did this only as an exercise to make a point about your question but in production code if you really want to tell SB to be quiet, use a Suppression annotation instead. It's much more maintainable and far easier than engineering some obfuscation to confuse the tool as well as other developers who follow behind to look for issues in the region. – dan Apr 26 '23 at 14:56
0

Common sense goes away when someone starts to play with security...

One the one hand, yes, exposing mutable objects to the wild is not a good idea in any case, for example the recent RCE in Spring has actually became RCE due combination of following reasons:

  • spring guys implemented bizarre functionality
  • tomcat log config turn to be mutable ("our case")

On the other hand spotbugs checks are based on naming conventions, and all setXXX methods of java.net.Socket are actually setOption - there are no security concerns, however I can't imagine situation when I would need to return Socket object via getter.

Andrey B. Panfilov
  • 4,324
  • 2
  • 12
  • 18
  • 1
    Thank you for this answer as it tends to be related to my real question, but only kind of. It's not really about sockets (that's only an example), it's about this somewhat bizarr structure with this immutable list. I can understand that it might be possible to cheat Spotbugs as a tool, right, as long as it relies on the source code. But why do Spotbug checks require compilation and testing the byte code, if they're based on naming conventions? Naming conventions are only relevant to the typed source code, not to the byte code - or is this a misperception? This is the core of my question. – rebit Jul 09 '22 at 19:49
  • You need to be a compiler to understand source code, working with bytecode is much simpler. "that might be possible to cheat Spotbugs as a tool" - if you have a requirement to pass static code analysis you must not cheat: you need to analyse every warning and either fix/mitigate it or mark as `false positive`: https://stackoverflow.com/questions/1829904/is-there-a-way-to-ignore-a-single-findbugs-warning. If it is actually not a requirement - you need to talk with initiator. – Andrey B. Panfilov Jul 09 '22 at 20:02