158

I have a website that I use github (closed source) to track changes and update site. The only problem is, it appears the .git directory is accessible via the web. How can I stop this and still be able to use git?

Should I use .htaccess? Should I change permissions of .git?

Chris Muench
  • 17,444
  • 70
  • 209
  • 362
  • 9
    Is on serverfault: http://serverfault.com/questions/128069/how-do-i-prevent-apache-from-serving-the-git-directory/325841 – scribu Oct 28 '11 at 22:06

9 Answers9

456

Put this in an .htaccess file at the root of your web server:

RedirectMatch 404 /\.git

This solution is robust and secure: it

  • works for all .git directories in your site, even if there are more than one,
  • also hides other Git files like .gitignore and .gitmodules
  • works even for newly-added .git directories, and
  • doesn't even give away the fact that the directories exist.
Bennett McElwee
  • 24,740
  • 6
  • 54
  • 63
  • 1
    It worked on the `.git` folder, but I could still get the `.gitignore` file to pull up. – Kurt Emch Apr 12 '14 at 18:43
  • My regex works in my testing, and *should* work according to the [RedirectMatch documentation](http://httpd.apache.org/docs/2.4/mod/mod_alias.html#redirectmatch) since the regex only has to match part of the URL, not the full URL: see the "subtle difference" note in the linked [AliasMatch documentation](http://httpd.apache.org/docs/2.4/mod/mod_alias.html#aliasmatch). Still, the docs are one thing, the real world is another. The @artlogic regex does match the full URL, so maybe there are some version differences in Apache or I'm just misreading things. – Bennett McElwee Feb 09 '15 at 00:27
  • 2
    @BennettMcElwee - after taking a closer look at the documentation, and running a few tests, it looks like the wildcards aren't necessary for me after all. Thanks for the solution. Works great! – artlogic Feb 12 '15 at 05:37
  • According to the [apache2 docs](https://httpd.apache.org/docs/current/mod/mod_alias.html#redirectmatch) you can also put it into other config context: `server config, virtual host, directory, .htaccess` – bennos Jun 07 '16 at 08:31
  • 4
    I would even suggest adding ".*" at the end of the expression, so that no file/folder under .git/ can be accessed --> `RedirectMatch 404 /\.git.*` – Dimitri Hautot Nov 15 '18 at 13:50
  • @DimitriHautot My solutiuon already does that. It matches _any_ path containing the string `/.git`. So that includes /.git, /.git/index, /foo/.gitignore, etc. – Bennett McElwee Nov 15 '18 at 22:15
  • 1
    Strange, because I had the case this morning. Without the `.*`, /.git was not reachable, but /.git/HEAD was. – Dimitri Hautot Nov 15 '18 at 22:19
  • @DimitriHautot The wildcards aren't necessary in my testing, and the docs agree. (See my comment above.) But adding the wildcard should be harmless so no reason not to add it. Something about your setup, perhaps? – Bennett McElwee Nov 16 '18 at 02:13
47

Create a .htaccess file in the .git folder and put the following in this file:

Order allow,deny
Deny from all

But note, that it would be lost if you ever re-cloned the repository

Black
  • 18,150
  • 39
  • 158
  • 271
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • 41
    True, but I would recommend against putting it in the `.git/` directory itself because it would be lost if you ever re-cloned the repository. – Jake Wharton May 26 '11 at 17:36
  • This is a pain if you have more than one .git directory, and must be re-done if you ever re-clone the directory. – Bennett McElwee Jul 29 '13 at 05:10
  • 1
    I tried this & found it works BUT this and seemingly ANY solution which puts this setting within .git/ has the 2 drawbacks mentioned above, the 1st one seeming worst, plus a 3rd maybe worst of all: the quote(Make .git directory web inaccessible), including how its done when & by whom, is small but still key to the data (esp for its security, including analysis when & before not properly done) BUT in .git/ it is NOT really part of the data proper (including versioned&shared&well-preserved) so also NOT restored ...analogous to one best put .gitignore with the data proper and not in .git/ . – Destiny Architect Jan 16 '15 at 01:59
  • 3
    Why is this the accepted answer and not Bennett's? His is simple and effective technique to solving this. – Josh Frankel Feb 05 '15 at 22:44
  • 1
    Most likely because OP accepted this one two years before the other one was posted ;) – ThiefMaster Feb 05 '15 at 22:45
  • I was originally kind of nonplussed by this answer, but really, it's a good answer if you're using WordPress, which sometimes overwrites .htaccess on upgrade. As always, YMMV, different answers are sometimes better for different situations. – aendra Aug 14 '15 at 15:08
37

Both .htaccess and permissions on the .git/ folder would work. I recommend the former:

<Directory .git>
    order allow,deny
    deny from all
</Directory>
Bryant Makes Programs
  • 1,493
  • 2
  • 17
  • 39
Jake Wharton
  • 75,598
  • 23
  • 223
  • 230
  • Is there another way to do with with apache as I am not allowed to use the directive due to server settings. – Chris Muench May 26 '11 at 17:24
  • 2
    There are all kinds of ways of matching (e.g., [``](http://httpd.apache.org/docs/current/mod/core.html#files), [``](http://httpd.apache.org/docs/current/mod/core.html#filesmatch)). – Jake Wharton May 26 '11 at 17:35
  • 6
    This answer is starkly incorrect - Directory is simply not allowed in .htaccess files. It does not depend on server settings. – doublemarked Nov 05 '13 at 17:43
  • 3
    NI8VDY=Failed in the 1 of 1 times I've tried it: on Dreamhost shared hosting, I put this in the website's root's .htaccess then http: to website root gave server logs error quote(.. – Destiny Architect Jan 16 '15 at 01:01
  • Agree with @DestinyArchitect -- sorry for the downvote, but this is misleading. – kael Apr 07 '17 at 23:23
18

I didn't want to muck around in the .git directory and wasn't able to get Bennett's solution to work on Apache 2.2, but adding the following to my <VirtualHost> configuration worked:

RewriteRule ^.*\.git.* - [R=404]
Community
  • 1
  • 1
David Moles
  • 48,006
  • 27
  • 136
  • 235
9

A more robust and simple option would be disabling the READ and Execution permission of the .git directory.

Since mostly Apache (httpd) runs under a special user account, for example, it runs as user apache on CentOS, while the .git directory must be created under a real user account, so we can simply block the access by changing the permission. Moreover, this approach doesn't introduce any new file, nor affect the git commands.

The command can be:

chmod -R o-rx .git
hailong
  • 1,409
  • 16
  • 19
  • On a machine where the SAs don't want .htaccess usage and don't want me messing with their httpd.conf -type files, this appears to be the best solution. – Alien Life Form Dec 16 '16 at 22:07
  • 3
    The obvious downside is that if you re-clone, you will have to remember to run `chmod` again. – Lauri Nurmi Sep 11 '18 at 10:40
9

I'm not comfortable with controlling access to my .git folders individually and choose to do it via apache config instead of .htaccess, to prevent me overwriting them, or forgetting on a new install etc.

Here are some detailed instructions hope they help. I'm using Ubuntu 16.10.

  1. First check what happens if you navigate to the .git folder in a browser. In my case I was presented with a directory listing. If you are seeing what you shouldn't be seeing (ie. you're not getting a 404), do the following.
  2. Use apache2ctl -V to get the HTTPD_ROOT and SERVER_CONFIG_FILE
  3. Use this to edit your apache config, in my case $ sudo nano /etc/apache2/apache2.conf
  4. Add the following somewhere in the config file: RedirectMatch 404 /.git
  5. Restart apache: $ sudo service apache2 restart
  6. Should now get you a 404 if you navigate to the folder again
  7. I tried this with .gitignore and also got a 404
5

mod_rewrite will give you the desired affect:

RewriteEngine on
RewriteRule .*\.git/.* - [F]
Kosh
  • 75
  • 1
  • 1
  • 10
    This is an information disclosure vulnerability: it makes it easy for people to determine the existence of the `.git` directory because it returns a Forbidden code rather than Not Found. – Bennett McElwee Jul 29 '13 at 05:14
  • 3
    It's not a vulnerabity to use git – Adam Apr 26 '17 at 08:09
  • @Adam he means that this will redirect to the homepage instead of giving a 404, so hackers will know a GIT directory exists that they can't access. The CORRECT solution would be to return a 404. – Eliezer Berlin Oct 11 '21 at 11:52
2

solution for apache2 (LAMP) server - you have 2 places to add .htaccess contents.. if 1 fails, try next

  1. for (development environment)

create .htaccess file in /var/www/html root directory and paste the code inside it

<Directorymatch "^/.*/\.git/">
  Order 'deny,allow'
  Deny from all
</Directorymatch>
  1. for (Production environment)

inside virtual host file (/etc/apache2/sites-enabled/) >find your virtualhost file> open file > after closing of virtualhost tag, paste

<Directorymatch "^/.*/\.git/">
  Order 'deny,allow'
  Deny from all
</Directorymatch>

no need to restart the server, it runs when page is called upon

Abhi
  • 119
  • 1
  • 2
1

Instead of messing with .htaccess rules like most answers suggest, why not simply put the .git/ directory above the webroot?

In my setups, my .git directory usually lives in something like:

/home/web/project_name/.git/

My actual code lives in

/home/web/project_name/www_root/

since my web root (as defined on Apache or Nginx.. I prefer the latter) is /home/web/project_name/www_root/ there's no way the .git directory can be accessible from the web since it lives "higher" than the webroot

Javier Larroulet
  • 3,047
  • 3
  • 13
  • 30
  • so public_html is a subdir of the repo working dir ?? sounds interesting – Hayden Thring May 11 '20 at 01:52
  • No, it's not a subdirectory. They are both "siblings" within my main project directory. My `project_name` directory has two subdirectories: `www_root` where the files actually served when a visitor browses my site would be, and `.git` where the repo is. Pulling from the repo updates `www_root` and its contents. The thing is that, since the `.git` directory is hierarchically "above" my front controller, it's inaccessible via web. – Javier Larroulet May 11 '20 at 02:02
  • I think this is what i meant, so you have /home/user/public_html/ and /home/user/.git – Hayden Thring May 11 '20 at 08:57
  • wow that is such an easy and simple solution its genius, ( not that making a server wide block in apache security.conf is hard ) the only thing to watch out for is if your hosting has some weird ownership/permissions settings on publlic_html, that might get changed. – Hayden Thring May 11 '20 at 20:08
  • Actually another advantage of this method is is gives you the option to store other files in the repo that are not automatically web accessible, such a db dumps. – Hayden Thring May 11 '20 at 20:15
  • 1
    very true... I actually have other "sibling directories" for other purposes which remain inaccessible from web, which allows me to sleep a little bit better at night :) – Javier Larroulet May 11 '20 at 20:19
  • Only other thing is you would have to set up a ignore for all you other user home dir content – Hayden Thring May 12 '20 at 00:38
  • Yes, that would be the downside :) – Javier Larroulet May 12 '20 at 18:42