4

My work setup includes a company-hosted Github Enterprise Server and Azure Devops pipelines. With sites like shields.io, I can generate badges for build success or code coverage, seemingly without ever authenticating myself with DevOps. The badge is then hosted on shields.io, meaning this 3rd-party site must somehow have access to my build process. They look like this:

enter image description here

Since the github as well as all build pipelines are obviously company internal, I can see three options how this might work:

  1. Even though pipelines and everything are private, build success status is hosted openly for the whole web. This is by design, since it isn't really considered a security risk. Nothing else can be done with knowing the Organization/ProjectName/DefinitionID of my internal project.

  2. This should not happen and something is configured wrongly. I might have a vulnerability in my setup.

  3. There is some form of authentication going on that I do not know about, e.g. I can only see the badge as long as my browser is logged into Azure (unlikely, it seems to work in private mode as well)

I can't find anything on the web or on stackoverflow regarding this. I would be happy about any resources explaining about this since I am not sure whether I can use them safely. Is using shields.io a security risk?

Thomas
  • 4,696
  • 5
  • 36
  • 71
  • If you visit the azure devops build badge page on shields.io, it asks for a project id. Presumably this is private, and providing this id authenticates you to receive the build status from azure. – GoodDeeds Jan 23 '20 at 15:36
  • The project ID seems to simply be a counter that counts upwards, and I cannot change it. Since this is in now way secure, I cannot imagine it is intended as any form of authentication. – Thomas Jan 23 '20 at 15:39
  • In the example I see [here](https://shields.io/category/build) (click on /azure-devops/build/:organization/:projectId/:definitionId), it is a long string. But I am just guessing, so I cannot answer. Travis CI uses a similar strategy for private repos. – GoodDeeds Jan 23 '20 at 15:41
  • The example in shields.io is wrong/outdated: Simply passing the project name instead of the project ID words just as well. – Thomas Jan 24 '20 at 08:33

1 Answers1

7

Badges like you mentioned are usually just blank SVG images without the information (you can take a look at the templates here).

So, for a service to create the SVG (or PNG):

  • the service gets the update data from you through a CI system of some sort
  • The service generates a corresponding image (either SVG or PNG) which is attached to a certain GET endpoint

The Service has two ways to implement this:

  • Use shields.io as a service, sending a JSON with the information on how to generate the image to their JSON endpoint
  • Implement the image generation internally using shields.io as a library or by any custom means.

So either way, SaaS applications that have badges usually serve them themselves (even if internally they call shields.io). This means each service can implement whatever security measures themselves.

The data that is passed to shields.io usually includes two words and some colors. So not too much information is exposed in order to generate the badges (see example below). Also, the communication between the service and shields.io is encrypted and sent over HTTPS.

For privacy, one example is that big companies usually have hosted solutions that are accessible only internally, so the badges are accessible internally only as well.

The badges specifically included in your question contains only public data from app stores or stars for a GitHub project etc. which is usually public as long as the project itself is public. Those badges very often use shields.io API to generate them automatically using the public data.

But if you'll look at badges for things like Coveralls or Travis, you'll see they host their own badges:

  • <img src="https://travis-ci.org/Kibibit/achievibit.svg?branch=master">

  • <img src="https://coveralls.io/repos/github/Kibibit/achievibit/badge.svg?branch=master">

Here's a little typescript example on how to create a badge using the shields.io as a library and serve it:

First, install gh-badges with

npm i gh-badges --save

and this is how you use it:

import { BadgeFactory } from 'gh-badges';

(async () => {
  const bf = new BadgeFactory();

  const format = {
    format: 'svg',
    text: [ 'coverage', '90%' ],
    labelColor: '#894597',
    color: '#5d5d5d',
    template: 'for-the-badge',
    logo: [
      'data:image/png;base64,iVBORw0KGgoAAAA',
      'NSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJL',
      'R0QA/wD/AP+gvaeTAAAA/0lEQVRYhe3WMU7DM',
      'BjFcadqh0qdWWBl7QU4Ss/AjsREF8RdOhYO0E',
      'qoN2DhFIgBOvBjIIMVxSFyUiEhP8lD7C/v/T9',
      '7sEMoKkoIe+Npn8qpOgCM2VBVVa1ZkzFDcjQd',
      'apDqLIR+u/jnO1AACkABKABdAO9DjHEWfb7lA',
      'LwOAQghXPXx6gJ4zE3GJIRwE0095Zhc4PO3iz',
      '7x7zoq+cB5bifr9tg0AK7xFZXcZYXXZjNs+wB',
      'giofG8hazbIDaeI5dFwAu8dxY2mE+KDyCWGCT',
      'YLj3c86xNliMEh5BVLjFseNEjnVN8pU0BsgSh',
      '5bwA5YnC25AVFjhpR6rk3Zd9K/1Dcae2pUn6m',
      'qiAAAAAElFTkSuQmCC'
    ].join('')
  };

  return bf.create(format);
})();

This is basically the same data that is sent to the shields.io as a service endpoint mentioned above.

You can see the full example in a controller context here and here.

About the risk of it, mostly think about what data is actually exposed here. It's almost nothing. and if you're worried about the data privacy, you can just generate the badges yourselves and serve them or embed them as privately as you want ;-)

Axel Köhler
  • 911
  • 1
  • 8
  • 34
Thatkookooguy
  • 6,669
  • 1
  • 29
  • 54
  • 1
    Thank you for the extensive answer. My take-aways are that it seems like the build status of our pipelines are indeed public-facing and could potentially be logged / misused by shields.io or a third party, they really don't stand to gain a lot since this is not really helpful / misusable information. – Thomas Jan 24 '20 at 08:35
  • 1
    @Thomas Yup. Sounds about right :-) As long as there's no authentication and the server is exposed publicly, the badge's image is exposed publicly as well. But an attacker will need to know the exact endpoint to get the image to get some information, and even then, they'll know very little. I think in most cases, that's a small risk companies are willing to take, and when they don't, they can create the badge internally and securely. – Thatkookooguy Jan 24 '20 at 10:01
  • 1
    An example of a working secure solution: self-hosted GitLab has badges baked in as a feature. so because the GitLab is hosted and accessible only by computers connected to the company's internal network, badges GitLab generates for projects or specific branches\buids are only accessible internally as well – Thatkookooguy Jan 24 '20 at 10:10
  • 1
    Another example of a secure solution is running a small script in you CI\CD whenever a build occurs that collects build information and coverage information; generates the images in the script (without calling any API and exposing data); and embeds\uploads the images wherever you want that is a secure location. Not relying on the badges the CI\CD creates on their end. But again... this might be an overkill :-) – Thatkookooguy Jan 24 '20 at 10:11