• Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major Major
    • script-security-plugin
    • None
    • Jenkins 2.387.1, everything mostly a few weeks old.

      Hi, I'm trying to use this dead simple enum in a shared library:

      package x.y.z
      enum ProjectTypes {
          python,
          node
          // workaround https://issues.jenkins.io/browse/JENKINS-33023
          ProjectTypes() {}
      }

      but I'm hitting a ridiculous bunch of errors. This time I'm really desperate and didn't find any workaround.
      The enum is placed in the library's /src directory and called from a method in a /vars script, that does type coercion from a string such as this, let's call it tripMine.groovy:

      import x.y.z.ProjectTypes
      def call(String projectTypeStr) {
          return projectTypeStr as ProjectTypes
      }

      This is supposed to work thanks to enum's valueOf() static method, but if I call it from a basic scripted pipeline (where the library is included on the folder-level):

      @Library('my-library@my-branch') _
      node {
          stage('trip') {
              def trouble = tripMine('python')
          }
      } 

      I get this exception back:

      org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: No such static method found: staticMethod x.y.z.ProjectTypes valueOf java.lang.Class java.lang.String 

      This is the main trouble, but the fun continues.

      The exception is from the script-security-plugin, I'm an admin, so I can easily whitelist that in the In-process script approval page, but yikes, it's not there. I found JENKINS-53700, but that's why I abandoned the usual declarative pipeline and used the scripted one. Still no dice.

      Next I tried to add the method to the enum:

      static ProjectTypes valueOf(Class clazz, String str) {
          return python
      } 

      This time the execution passed (why?), but reimplementing the whole method defies the very reason I used enum in the first place.

       

      Is there something sensible I can do to make this work? I've also found this "improvement" suggestion JENKINS-56948, which looks quite like the same thing, but I don't believe that's an improvement material. Hope I'm right   Thanks a lot!

          [JENKINS-71056] Shared library Enum fails on valueOf

          Vit added a comment -

          I've figured out a rather scalable boilerplate workaround. The enum needs to look like this:

          enum ProjectTypes {
              python,
              node
           
              ProjectTypes() {}
          
              @NonCPS
              static <T extends Enum<T>> T valueOf(Class<T> clazz, String str) {
                  return Enum.valueOf(clazz, str)
              }
          } 

          Running this for the first time bails out on:

          org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use staticMethod java.lang.Enum valueOf java.lang.Class java.lang.String 

          But that one can be finally allowed in the admin page. Wouldn't it make sense to add it to the defaults?

          Generally it seems like something fails to handle the particular enum as an Enum subclass, which (although kinda transitively) is the case by definiton.

          Vit added a comment - I've figured out a rather scalable boilerplate workaround. The enum needs to look like this: enum ProjectTypes { python, node ProjectTypes() {}   @NonCPS     static <T extends Enum<T>> T valueOf( Class <T> clazz, String str) {         return Enum.valueOf(clazz, str)     } } Running this for the first time bails out on: org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use staticMethod java.lang.Enum valueOf java.lang.Class java.lang.String But that one can be finally allowed in the admin page. Wouldn't it make sense to add it to the defaults? Generally it seems like something fails to handle the particular enum as an Enum subclass, which (although kinda transitively) is the case by definiton .

          Devin Nusbaum added a comment -

          Enum support in the sandbox is just very bad and I would avoid using enums.

          RejectedAccessException: No such static method found: staticMethod x.y.z.ProjectTypes valueOf java.lang.Class java.lang.String

          This looks like a general bug with static method resolution. Here is a minimal reproducer:

          class Super {
            static void method() { }
          }
          class Child extends Super { }
          Child.method() // Allowed by Groovy, but fails in the Jenkins Groovy sandbox 

          SandboxInterceptor.onStaticCall needs to consider supertypes to fix that issue, but in this particular case even with that fixed you would just run into the issue with Enum.valueOf not being allowed in the sandbox as you noted.

          org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use staticMethod java.lang.Enum valueOf java.lang.Class java.lang.String
          But that one can be finally allowed in the admin page. Wouldn't it make sense to add it to the defaults?

          Whitelisting staticMethod java.lang.Enum valueOf java.lang.Class java.lang.String by default would effectively allow sandboxed scripts to access any enum constant on any enum type available in the JVM. Is that a problem? I am not sure, but it would need to be considered carefully. Currently enum fields have to be individually allowed by a whitelist unless the enum itself is defined in the sandbox, so it would be a departure from the current behavior. Perhaps we could special-case that method for cases where the enum is defined in the sandbox itself to maintain the status quo.

          As far as practical advice/workarounds, given that Groovy and Jenkins Pipeline are extremely dynamic and so IMO much of the value of enums is lost, I would just use string constants in cases where you would be inclined to use enums. Even more generally speaking, I would avoid using src/ in libraries, since you can very quickly end up with an unmaintainable mess of Jenkins-specific complexity and limitations. If complexity is unavoidable, consider creating a CLI tool in the programming language of your choice with whatever logic you need that you can invoke from Jenkins using steps like sh.

          Devin Nusbaum added a comment - Enum support in the sandbox is just very bad and I would avoid using enums. RejectedAccessException: No such static method found: staticMethod x.y.z.ProjectTypes valueOf java.lang.Class java.lang.String This looks like a general bug with static method resolution. Here is a minimal reproducer: class Super { static void method() { } } class Child extends Super { } Child.method() // Allowed by Groovy, but fails in the Jenkins Groovy sandbox SandboxInterceptor.onStaticCall needs to consider supertypes to fix that issue, but in this particular case even with that fixed you would just run into the issue with Enum.valueOf not being allowed in the sandbox as you noted. org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use staticMethod java.lang.Enum valueOf java.lang.Class java.lang.String But that one can be finally allowed in the admin page. Wouldn't it make sense to add it to the defaults? Whitelisting staticMethod java.lang.Enum valueOf java.lang.Class java.lang.String by default would effectively allow sandboxed scripts to access any enum constant on any enum type available in the JVM. Is that a problem? I am not sure, but it would need to be considered carefully. Currently enum fields have to be individually allowed by a whitelist unless the enum itself is defined in the sandbox, so it would be a departure from the current behavior. Perhaps we could special-case that method for cases where the enum is defined in the sandbox itself to maintain the status quo. As far as practical advice/workarounds, given that Groovy and Jenkins Pipeline are extremely dynamic and so IMO much of the value of enums is lost, I would just use string constants in cases where you would be inclined to use enums. Even more generally speaking, I would avoid using src/ in libraries, since you can very quickly end up with an unmaintainable mess of Jenkins-specific complexity and limitations. If complexity is unavoidable, consider creating a CLI tool in the programming language of your choice with whatever logic you need that you can invoke from Jenkins using steps like sh .

          Vit added a comment -

          Thanks a lot dnusbaum , for the advice and the summary of the current state of affairs. It's a bit disappointing, but that's life I guess. Still, would you think we could distill some workable items from this? I see one obvious and one a little less:

          • consider supertypes in SandboxInterceptor.onStaticCall
          • work towards whitelisting staticMethod java.lang.Enum valueOf java.lang.Class java.lang.String (i.e. mostly evaluate feasibility/safety of such step)

          Generally, I believe jenkins might surely benefit from the support of such an essential construct as enums are, and those two items could make the things a lot better.

          Thanks!

          Vit added a comment - Thanks a lot dnusbaum , for the advice and the summary of the current state of affairs. It's a bit disappointing, but that's life I guess. Still, would you think we could distill some workable items from this? I see one obvious and one a little less: consider supertypes in SandboxInterceptor.onStaticCall work towards whitelisting staticMethod java.lang.Enum valueOf java.lang.Class java.lang.String (i.e. mostly evaluate feasibility/safety of such step) Generally, I believe jenkins might surely benefit from the support of such an essential construct as enums are, and those two items could make the things a lot better. Thanks!

          Devin Nusbaum added a comment -

          tlwhitec Sure, if someone has time to spend on it, fixing those issues would be nice. For what it's worth though, I would probably not frame the second improvement as literally adding Enum.valueOf to generic-whitelist, I would instead say that enum classes defined in sandboxed Groovy scripts should support standard enum operations by default (e.g. not just this, but things like JENKINS-33023 as well). What that looks like may be something different than additional generic-whitelist entries, for example I personally would look into special-casing enums in various cases in SandboxInterceptor or maybe groovy-sandbox first.

          Devin Nusbaum added a comment - tlwhitec Sure, if someone has time to spend on it, fixing those issues would be nice. For what it's worth though, I would probably not frame the second improvement as literally adding Enum.valueOf to generic-whitelist , I would instead say that enum classes defined in sandboxed Groovy scripts should support standard enum operations by default (e.g. not just this, but things like JENKINS-33023 as well). What that looks like may be something different than additional generic-whitelist entries, for example I personally would look into special-casing enums in various cases in SandboxInterceptor or maybe groovy-sandbox first.

            Unassigned Unassigned
            tlwhitec Vit
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: