Using GitLab to build LaTeX

Generating documents in PDF form is becoming the standard nowadays, but how to generate them easily when they’re mostly free format? One of the goals of the Offensive Security Certified Professional (OSCP) Certification is writing a report based on the evidence you find. This is where LaTeX comes into the picture as you can easily have multiple files with data and one or more TeX-files combining this into a proper document. The question than also comes “How to optimise this pipeline?”

The first step is to see every report as a git repository where you can store and version all data. And running rubber locally solves the problem to quickly create a PDF from your sources, but wouldn’t it be nice of this part also could be automated? Who didn’t make a last moment change and forgot to run rubber if the document would still compile into a PDF? GitLab CI can luckily also compile LaTeX into a PDF and the notification if your update broke the build process comes for free.

The example .gitlab-ci.yml below for my latex-test repository generates a PDF that is being kept for one week and then you need to generate the document again.

  - build

  stage: build
  image: aergus/latex
    - latexmk -pdf main.tex
    expire_in: 1 week
      - main.pdf

This example can also be included as part of another project as compile_pdf is triggered in the build phase of the pipeline. No project has to be shipped without a digital document anymore.

Integrity checking for JavaScript

Including JavaScript files from a CDN can be beneficial in many ways as you don’t have to ship the code with your code and caching can be done by the browser of a proxy server. It also allows for injecting untrusted code into a web page as someone else is hosting the code you rely on. But Firefox, Chrome and Opera already support Subresource Integrity checking script and link tags. Hopefully both Safari and Edge (or Internet Explorer) will support it soon.

But how does it work? First let calculate the SHA256 hash of JQuery version 3.2.1 hosted by CloudFlare. Also keep in mind to verify this number with the official version offered by JQuery. In this example we download the minimized version of JQuery with curl and run it twice through openssl to generate the checksum and encode the result in base64 format.

$ curl -s | openssl dgst -sha256 -binary | openssl enc -base64 -A

Now that we have the hash we can add the integrity attribute to the script tag and the prefix for the hash is “sha256-” to indicate the hashing used. From this point forward a browser that supports SubResource Integrity will require that the provided hash will match the calculated hash of the downloaded file.

<script src="" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>

Beside SHA256 the specification allows for SHA384 and SHA512 to be used. Calculation is the same as with SHA256 and we only change the algorithm that openssl needs to use.

$ curl -s | openssl dgst -sha512 -binary | openssl enc -base64 -A

We could put only the SHA512 hash in the attribute, but we can put multiple algorithm results in the same attribute by just splitting them with a space. This leaves a lot of room for proper lifecycle management of hashing algorithms as you can present multiple hashes when you switch to a better version instead of doing it big bang style and hope for the best.

<script src="" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4= sha512-3P8rXCuGJdNZOnUx/03c1jOTnMn3rP63nBip5gOP2qmUh5YAdVAvFZ1E+QLZZbC1rtMrQb+mah3AfYW11RUrWA==" crossorigin="anonymous"></script>

The next step is to have a fallback when the CDN you rely on goes down or is serving corrupt files. You could add a second src tag as in the example below that tells the browser to use the Google CDN when CloudFlare has issues serving the correct files.

<script src="" noncanonical-src="" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4= sha512-3P8rXCuGJdNZOnUx/03c1jOTnMn3rP63nBip5gOP2qmUh5YAdVAvFZ1E+QLZZbC1rtMrQb+mah3AfYW11RUrWA==" crossorigin="anonymous"></script>

The next step is to get the Content-Security-Policy header correct, but for now only Firefox 49 and higher have the option to act on the require-sri-for attribute. This would basically force the browser to only load scripts and style sheets if the SRI-steps are successful, but many a lot of developers need to optimise their build pipeline to produce correct hashes and have correct monitoring to detect problems.

Google Reader, farewell

For years I have been using Google Reader to keep up to date with websites as I could read them when I had time and I saw which sites where updated. Even if they where idle for months, so a dream for everyone who has a time management plan in place. Google Reader had a webinterface, an API for third-party applications like Feedly and Liferea, but also an app for Android so you could check things when you where waiting somewhere. Until now as Google announced it will stop Google Reader in the summer of 2013. Some people try to revert this decision with a petition, but to be honest I’m not going to wait and that may be sad as Google Reader was the reason I had a Google-account in the past.

That said, I already started to experiment with an alternative last summer and while it is still in development and misses some features the time has come to switch from Google Reader towards TT-RSS. As of today I imported all feeds into TT-RSS and removed also all feeds from Google Reader. The only feeds still in Google Reader are those for Google Listen and the time has come to start searching for an alternative. Google Listen is a podcast application, also discontinued and will also stop working this summer. Maybe I’ll move all podcasts back to my desktop, but it was handy to have them on my phone so I could listen to them in the car.

For now TT-RSS is a good self-hosted alternative with a webinterface, applications for Android and Liferea has also an option to use your TT-RSS installation. Maybe I should spend some time soon to get OPML support just like in Liferea so that Planet-feeds aren’t needed anymore and will make message deduplication easier, but for now it works and I can only say, Google thanks for all the fish. And to be honest I think my Google account will have the same destination as my Twitter account.