Security: Blocking web access to source control directories

Published:  24/09/2020 13:44


When you want to quickly deploy an application, one easy way is to just clone the Git repository on the production server and publish that.

It may not be the most solid, DevOps friendly continuously integrated [insert other buzzwords] way to go but it gets the job done, we do it too sometimes.

Now, thing is, a clone of a Git repository holds a hidden folder called ".git" at the root, which has a copy of the entire workspace and all of its history.

Someone downloading your .git folder could not only recreate the current state of the repository, but they could also look for passwords or information that shouldn't have been there that you might have deleted at some point.

We can confirm bots are looking for ".git" quite often.

An older source control software that was popular in the past is SVN, which does not actually store the whole history of the repository locally but may have cleartext passwords or personnal information saved in config files.

Even outside of the context of source control, it's always a good idea to think about files that may be publicly available but shouldn't be. For instance ".env" files and any config file in general.

For more information about how to recreated a working copy from a publicly available .git directory, see the following article.

Blocking source control directories

We mostly use Debian as our Linux distribution of choice and there is usually already something prepared for blocking source control directories when using the official packages.


On Debian we like to add the directive to /etc/apache2/conf-available/security.conf but you could add it anywhere, including directly in /etc/apache2/apache2.conf (as you probably would when creating a Docker image for instance).

There should already be these lines commented out (this is for Debian 10):

<DirectoryMatch "/\.svn">
  Require all denied

We primarily want to block .git, so let's add it to the regex:

<DirectoryMatch "/(\.svn|\.git)">
  Require all denied

Which also works at any level of directory depth. You don't need a more complex regex for that as some people would have you believe.

In case you're still using Apache 2.2, the syntax is just a little bit different:

<DirectoryMatch "/(\.svn|\.git)">
  Order deny,allow
  Deny from all

Quick note while you're in security.conf: you might want to set these options too for a production server:

ServerTokens Prod
ServerSignature Off

Once you're done, check configuration and reload:

sudo apachectl configtest
sudo systemctl reload apache2


The Debian package for Nginx has the following lines in its default website config file (/etc/nginx/sites-available/default):

#location ~ /\.ht {
	#	deny all;

Which is meant to block .htaccess files that Nginx doesn't use anyway.

You could uncomment and modify the directive here to also block .git and .svn:

location ~ /(\.ht|\.git|\.svn) {
	deny all;

With Nginx the location directive is only allowed inside server {} blocks, which means we'll have to copy these lines into every single virtual host we define.

What we like to do is create the file in /etc/nginx/snippets/security.conf and write the location directive shown above in the file.

Next you'll want to edit all of your virtual hosts (server directives) and add the following line:

include snippets/security.conf;

Check the configuration and reload:

sudo nginx -t
sudo systemctl reload nginx