Page MenuHomePhabricator

Unable to view mw-debug log in Jenkins
Open, LowPublic

Description

  1. https://integration.wikimedia.org/ci/job/quibble-vendor-mysql-php72-selenium-docker/58183/artifact/log/
  2. Try clicking mw-debug-www.log.gz. And then try clicking "View" next to it.

Expected:

Text file served from web server.

Actual:

Binary compressed data served (via "View"), or "Download this file" when clicking the filename.


I understand the need to compress these files, but afaik we had something in place to automatically serve these as compressed text over HTTP so that the browser still displays it. It seems this has stopped working?

/cc @hashar

Event Timeline

This is still broken, and thus makes logs difficult to access (e.g. save as, locally unzip, then view by other means).

We previously (T249268) added a hack to stream compressed fresnel.json.gz files which was https://gerrit.wikimedia.org/r/c/operations/puppet/+/675515/4/modules/contint/templates/apache/proxy_jenkins.erb

apache/proxy_jenkins.conf
SetEnvIf Request_URI "^<%=prefix -%>/.*fresnel.*\.json\.gz$" JSON_GZ
Header set Content-Type application/json env=JSON_GZ
Header set Content-Encoding gzip env=JSON_GZ

For the other gz files:

Direct file linkContent-Type: application/x-gzip
View link (/*view*/)Content-Type: text/plain

More or less related is T56599 which at the time @Krinkle and I reported as https://issues.jenkins-ci.org/browse/SECURITY-95 (not public). A browser could end up executing JavaScript code from the artifact and that got fixed by adding a Content-Security-Policy. There were also mentions of using X-Content-Type-Options: nosniff and/or forcing text/plain.

The relevant code in Jenkins is:

core/src/main/java/hudson/model/DirectoryBrowserSupport.java
        boolean view = rest.equals("*view*");
...
        if (view) {
            InputStream in;
            try {
                in = baseFile.open(getNoFollowLinks());
            } catch (IOException ioe) {
                rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // for binary files, provide the file name for download
            rsp.setHeader("Content-Disposition", "inline; filename=" + baseFile.getName());

            // pseudo file name to let the Stapler set text/plain
            rsp.serveFile(req, in, lastModified, -1, length, "plain.txt");

Thus the request is served with:

Content-Disposition: inline; filename=mw-debug-cli.log.gz
Content-Type: text/plain

The code has been pretty much the same since support for /*view*/ URLs got introduced back in 2007 and it definitely serves everything with text/plain. The same thing garbage output happens for png file or pretty much anything.