Skip to content

Systemd start script: allow * from JAVA_OPTS to be passed to the Jenkins process (escaping in eval) #303

@tholewebgods

Description

@tholewebgods

What feature do you want to see added?

The Jenkins start script accidentally expands * (to all files in the working directory) originating from an environment variable with its eval.

This lead to a 500 error, when opening a file from the directory browser:

Error while serving https://qa-hidrive.de/job/XXXXX/XXXXX/Report.html
org.eclipse.jetty.http.BadMessageException: 500: Response header too large
    at org.eclipse.jetty.server.HttpConnection$SendCallback.process(HttpConnection.java:768)
    at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241)
    at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:223)
    at org.eclipse.jetty.server.HttpConnection.send(HttpConnection.java:550)
    at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:910)
    at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:987)
    at org.eclipse.jetty.server.HttpOutput.channelWrite(HttpOutput.java:285)
    at org.eclipse.jetty.server.HttpOutput.channelWrite(HttpOutput.java:269)
    at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:869)
    at com.jcraft.jzlib.DeflaterOutputStream.deflate(DeflaterOutputStream.java:144)
    at com.jcraft.jzlib.DeflaterOutputStream.write(DeflaterOutputStream.java:102)
    at org.kohsuke.stapler.compression.FilterServletOutputStream.write(FilterServletOutputStream.java:41)
    at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:638)
    at org.kohsuke.stapler.Stapler.serveStaticResource(Stapler.java:628)
    at org.kohsuke.stapler.ResponseImpl.serveFile(ResponseImpl.java:231)
    at hudson.model.DirectoryBrowserSupport.serveFile(DirectoryBrowserSupport.java:415)
    at hudson.model.DirectoryBrowserSupport.generateResponse(DirectoryBrowserSupport.java:164)
    at htmlpublisher.HtmlPublisherTarget$BaseHTMLAction.doDynamic(HtmlPublisherTarget.java:275)
    at htmlpublisher.HtmlPublisherTarget$HTMLAction.doDynamic(HtmlPublisherTarget.java:283)
    at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:710)
    at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:398)
Caused: java.lang.reflect.InvocationTargetException
    at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:402)
    at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:410)
    ...

This is what we had in the config initially:

cat /etc/systemd/system/jenkins.service.d/override.conf 
[Service]
Environment="JAVA_OPTS=-Djava.awt.headless=true \"-Dhudson.model.DirectoryBrowserSupport.CSP=sandbox allow-same-origin allow-scripts; default-src 'self'; script-src * 'unsafe-eval'; img-src *; style-src * 'unsafe-inline'; font-src *;\""

This is what the process command looked like:

jenkins    22175       1 99 17:32 ?        00:00:16 /usr/bin/java -Djava.awt.headless=true -Dhudson.model.DirectoryBrowserSupport.CSP=sandbox allow-same-origin allow-scripts; default-src 'self'; script-src Report browserstack-id.txt caches com.browserstack.automate.ci.jenkins.BrowserStackBuildWrapper.xml <<<... OMITTED A LOT OF OTHER SYSTEM FILES ...>>> workflow-libs workspace 'unsafe-eval'; img-src *; style-src Report browserstack-id.txt caches com.browserstack.automate.ci.jenkins.BrowserStackBuildWrapper.xml <<<... OMITTED A LOT OF OTHER SYSTEM FILES ...>>> workflow-libs workspace 'unsafe-inline'; font-src *; -jar /usr/share/java/jenkins.war --webroot=/var/cache/jenkins/war --httpPort=8080 --httpListenAddress=127.0.0.1

Initially I did not recognized this as an error until I compared that with the command, when the CSP config was absent:

jenkins    28509       1  8 09:26 ?        00:00:59 /usr/bin/java -Djava.awt.headless=true -jar /usr/share/java/jenkins.war --webroot=/var/cache/jenkins/war --httpPort=8080 --httpListenAddress=127.0.0.1

Now I understood * was expanded by the shell, so the CSP system property no longer contained the * but a lot of filenames from the working directory.

This is a MCVE for the underlying problem:

$ foo="\"a * b\"" ; eval echo ${foo}
a file-1.txt file-2 b
$ foo="\"a \* b\"" ; eval echo ${foo}
a \* b
$ foo="a \* b" ; eval echo ${foo}
a * b

$ foo="a * b" ; eval echo "${foo}"
a file-1.txt file-2 b
$ foo="\"a * b\"" ; eval echo "${foo}"
a * b

Although we probably stick with enumerating the actual domains instead of using *, I though you want to fix this.

This is a proposed fix:

--- /usr/bin/jenkins    2022-04-01 13:17:00.122267704 +0200
+++ /usr/bin/jenkins    2022-04-01 13:21:42.354954818 +0200
@@ -148,7 +148,7 @@
    unset JENKINS_WEBROOT
    eval exec \
        "${java_cmd}" \
-       ${java_opts_tmp} \
+       "${java_opts_tmp}" \
        -jar "${jenkins_war_tmp}" \
        ${inferred_jenkins_opts}
 }

This is the current Jenkins version:

$ sudo dpkg --list | grep 'jenkins'
ii  jenkins                               2.332.1                            all          Jenkins is an ...

Upstream changes

None.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions