Scoped Values and better security

Holo The Sage Wolf holo3146 at gmail.com
Thu Apr 27 14:58:01 UTC 2023


Hello Volker,

The 2 ways of sharing information discussed here are "passing a parameter"
and "having a field in scope", the only thing that Scoped/Thread locals
gives is the thread safety (and integrity in the case of ScopedValues), the
problem of security is more about visibility than those 2 specific classes.

Here is an example that I believe showcase the problem, this example is a
textbook example of how a strong type system solves the problem but it
works just fine for our case.

Imagine I have a function `Print` that prints to a shell, this function has
2 *dependencies*, the input we want to print, and the is the state of the
shell (containing e.g. the offset we are in).

The function `Print` change the state of the shell, let say we pass both of
the dependencies as a parameter (and assume that State is immutable), in
this case the function will have the following signature:

    Print: Input -> State -> State

And we will use it:

    state = ...
    state = Print("0", state)
    state = Print("1", state)

Removing shadowing we have:

    state = ...
    state1 = Print("0", state)
    state2 = Print("1", state1)

But in this way we can have:

    state = ...
    state1 = Print("0", state)
    state2 = Print("1", state)

Which we won't necessarily want to be legal, using a stronger type system
such as linear types solves this problem, but having the State dependency
to not be visible at the user level also solves it, and the latter solution
is much more feasible for Java.

Now add it some threads and you want to have something like Scoped/Thread
locals.

Now this may looks like a silly example, but it comes to show the idea that
we want stuff to not be accessible to the user in some cases.

Another example is having some kind of access Token, which we don't want
the user to be able to access (or we want to control the accessibility),
but this Token is required for the execution.

And indeed I can't think on any public thread local that is not a security
problem (for scoped locals there is some rare use cases for public
accessibility because they have a great integrity and they read-only stack
base, but it is really not the common use cases)

Hope it helps,
Cheers,
Holo

On Thu, Apr 27, 2023, 17:17 Volker Simonis <volker.simonis at gmail.com> wrote:

> I take this discussion from the JEP issue in JBS [1] to the mailing
> list as requested by Alan:
>
> My initial comment was:
>
> In your motivation section you say:
>
>   Normally, data is shared between caller and callee by passing it as
> method arguments,
>   but this is not viable for a Principal shared between the server
> component and the data
>   access component because the server component calls untrusted user
> code first. We need
>   a better way to share data from the server component to the data
> access component than
>   wiring it into a cascade of untrusted method invocations.
>
> I can't see how ThreadLocals or ScopedValues improve the situation
> here with respect to "untrusted code"? I fully agree that passing the
> Principal data from the server component down to the data access
> component by means of method parameters is ugly and disturbing. But I
> can't see how it should be more "unsecure", because the "untrusted
> user code" can access a potential Principle object from its argument
> list in much the same way like a ThreadLocale or ScopedValue defined
> in an enclosing scope.
>
> So maybe it would be better to focus more on the usability aspect than
> on "avoiding information exposure to untrusted code" in the Motivation
> section?
>
> Andrew's response was:
>
> > But I can't see how it should be more "unsecure", because the "untrusted
> user code" can access a potential Principle object from its argument list
> in much the same way like a ThreadLocale or ScopedValue defined in an
> enclosing scope.
>
> I don't understand what you don't understand.
>
> We can reason about code when we know that its access to data is
> constrained in some way. We know that scoped values have particular
> properties, in that we can restrict accesses to them to code we trust.
> This isn't specifically security related: '"trusted code" can mean
> simply code that we've verified, and therefore can trust. If we set a
> scoped value in an outer scope, call via some unknown code, then
> access that scoped value in an inner scope, we know for certain that
> its value is one we set in the outer scope. The (untrusted, unknown)
> code in between can't have substituted something else.
>
> And Alan added:
>
> It may be that Volker has missed the point that the capability, as in
> the ThreadLocal or ScopeLocal variable, is usually stored in a private
> static final so it's not accessible to code in the intermediate frames
> between where it is set and (usually) the callback that will read the
> value. It would probably be better to bring questions to loom-dev
> rather having a protracted discussion in comments here.
>
> So finally my new comment:
>
> In your example "Web framework example with scoped values" both, the
> `Server` class where the ScopedValue `PRINCIPAL` is declared with
> `package-private` visibility as well as the `DBAccess` class which
> uses the `PRINCIPAL` are in the default unnamed package. But I doubt
> that in a real world application the server class and the database
> access class will be in the same package. So if you'd declare
> `PRINCIPAL` in a private field as Alan suggested, it would be
> impossible for another component to access it. If on the other hand
> your scoped value was declared in a public field, any untrusted,
> intermediate code executed between outer and inner scope could access
> it just as well.
>
> @Andrew: the untrusted, intermediate code can both read and even
> rebind the value of the ScopedValue set in an outer scope. The
> "security" you are talking about is a feature of the Java access rules
> and not of the scoped value implementation. I don't see how in a real
> world (e.g. Spring) application, the web server, the DB engine and the
> logging framework can easily share access to a common scoped value
> without exposing this scoped value to intermediate code outside of
> these components as well.
>
> But maybe I'm missing something in which case it might sense to
> explain this a little more detailed in the JEP?
>
> Thank you and best regards,
> Volker
>
> [1] https://bugs.openjdk.org/browse/JDK-8304357
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20230427/eb02def4/attachment-0001.htm>


More information about the loom-dev mailing list