jexl

errors upon apache jexl upgrade from 3.2.1 to 3.3


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


Solution

  • 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(); }
      }