i have upgraded from apache jexl 3.2.1 to 3.3 and suddenly my test cases fail
on jexl 3.3 this test case works but only after reverting to 3.2.1 behaviour
@Test
public void testUsingWhiteSandbox() {
// given
JexlSandbox sandbox = new JexlSandbox(false);
sandbox.allow(System.class.getName()).execute("currentTimeMillis");
sandbox.allow(AtomicLong.class.getName()).execute("set");
Map<String, Object> namespaces = new HashMap<>();
namespaces.put("sns", System.class);
JexlEngine jexl = new JexlBuilder()
.sandbox(sandbox)
.namespaces(namespaces)
.strict(true)
.silent(false)
**.permissions(JexlPermissions.UNRESTRICTED)**
.create();
AtomicLong atomicLong = new AtomicLong();
MapContext context = new MapContext();
context.set("result", atomicLong);
long now = System.currentTimeMillis();
//when
jexl.createScript("result.set(sns:currentTimeMillis())").execute(context);
// then
AtomicLong result = (AtomicLong) context.get("result");
assertThat(result.get()).isGreaterThanOrEqualTo(now);
}
but if i comment out the line ".permissions(JexlPermissions.UNRESTRICTED)" which i had to add to revert to 3.2.1 behaviour, the test case fails. how do i get this to work without having to use the 3.2.1 behaviour which is less secure
your help is much appreciated
In your test - at least -, you are in a very secure sandbox since the only allowed methods are System::currentTimeMillis and AtomicLong::set. The 3.3 restricted set precludes using the System class and permissions are applied before sandboxes, thus your test failure. An easy fix would be to use:
JexlPermissions permissions = new JexlPermissions.ClassPermissions(System.class);
Which will use the restricted set as a base augmented with the classes you allow as arguments, in this case re-allowing System as a class through permissions, the sandbox still only allowing currentTimeMillis as callable method.
If I may, I'd probably avoid exposing System however - belt and suspenders - and would probably create a dedicated class for the 'sns' namespace to only expose what is necessary (permissions and sandbox being tailored accordingly). Something like:
public static class SnsNamespace {
public long currentTimeMillis() { return System.currentTimeMillis(); }
}