
Please stop serving .git to the outside world - _wmd
http://pythonsweetness.tumblr.com/post/52587443706/devs-please-stop-serving-git-to-the-outside-world
======
tlongren
[http://www.fcc.gov/.git/config](http://www.fcc.gov/.git/config)

FCC has a github account.

[http://www.fcc.gov/.git/logs/HEAD](http://www.fcc.gov/.git/logs/HEAD)

~~~
blaines
Apparently fixed as it's now a redirect loop.

------
tytso
To be clear (it wasn't mentioned explicitly in the blog post), but it's
obviously what the author was referring to, this is about people who are
deploying web sites with static content which is being managed via git.

~~~
hdra
I'm curious, what security risk does static content could pose by serving the
.git ?

~~~
calpaterson
If you don't expect your source code to be made public and don't take care to
keep secrets out of it, then you will be surprised when attackers have (for
example) your cookie signing key.

I know checking secrets into source code is already a bad practice, but
accidental publication takes bad practice and makes it a security hole.

~~~
drdaeman
Parent post was asking about static content, not dynamic. No code to keep
secret.

------
peterjmag
For simple static sites, I use a workflow very similar to this one[1]. It
takes a minute or two to set up, but once it's all configured, you can deploy
to your heart's content without ever worrying about exposing your .git
directory to the world.

[1] [http://toroid.org/ams/git-website-howto](http://toroid.org/ams/git-
website-howto)

~~~
astrodust
No. Not this. index.html has no business being in the root of your project.

Always, and I mean _always_ put your web content into a directory separate
from the root of your .git archive. This is the easiest way to avoid all of
these problems.

Rails calls this directory "public", but it could be whatever you want, so
long as what's mounted on your web server is not the root.

~~~
devmach
* Any folder in your project can have index.html and indeed it should have.

* Parent talks about static pages, not about rails-ruby/php/python project.

But i get your point : If somehow somebody screw with servers config, there is
a risk to expose your apps files & configs. You can follow parents advice but
set your root path in apache/nginx config to /var/www/www.example.org/public
instead of /var/www/www.example.org

~~~
astrodust
Even a static site can be structured so that the .git directory is outside of
the main public mount.

This gives you a natural place to store notes, documentation, and other non-
public content.

It's not about screwing with the server config, it's so that it takes several
stupid mistakes before your .git folder is flapping in the breeze, not just
one. Being one configuration directive away from embarrassing failure is not a
good idea.

~~~
rlx0x
> Being one configuration directive away from embarrassing failure is not a
> good idea.

I can't stop but thinking about PHP webapps, for instance Wordpress serves wp-
index.php in the same directory as wp-config.php, indeed only one
configuration directive away from blowing it all up in your face.

Every few months or so I encounter a huge site that serves me PHP source code.
For instance the BBC:
[http://www.bbc.co.uk/radio4/hitchhikers/zmachine/hhguide.xml](http://www.bbc.co.uk/radio4/hitchhikers/zmachine/hhguide.xml)

But hey its PHP I guess anyone who would care about something like that has
stopped using it years ago.

~~~
krapp
Why in the world would anyone serve a php file as .xml? That seems to be the
problem... xml files are meant to be readable as text.

~~~
eropple
I would guess it's a configuration error around something like smart
extensions, maybe? "If the clean URL has a .xml at the end, send the request
through PHP."

Dumb, but it's the only thing I can come up with offhand.

------
wldlyinaccurate
I recently discovered that I had been serving .git on my blog for a couple of
years. All it took to fix was a simple rule in my Nginx config:

    
    
        # Don't expose hidden files to the web
        location ~ /\. {
            return 404;
        }

~~~
fohlin
Though, keep in mind the potential conflict with /.well-known/ \-
<[http://tools.ietf.org/html/rfc5785>](http://tools.ietf.org/html/rfc5785>).

------
contingencies
OK, so I knew about this one before. But if you didn't, there's a better
solution than just remembering it, which seems to be the gist of this post.

Solution: run one or more _automated security tools_ across your sites,
_before_ deploying them to public locations. If possible, _automate_ this
process, so it happens _all the time_. The tools won't catch everything, but
they will catch something you didn't, some of the time. Testing is good
practice with all software! Do it.

~~~
koyote
Can you recommend a couple of good automated security tools?

~~~
contingencies
[http://w3af.org/](http://w3af.org/) [http://www.arachni-
scanner.com/](http://www.arachni-scanner.com/)
[http://www.openvas.org/](http://www.openvas.org/)
[https://code.google.com/p/skipfish/](https://code.google.com/p/skipfish/)

~~~
lemonade
Very useful list. None of these have anything running as a service you can try
out easily, I guess that would be a Bad Idea anyway as this kind of tools
might either accidentally cause stuff to happen to a server, or be used as
part of an attack. I guess script youngsters will not be very much deterred by
having to install e.g. a python or ruby library - but any lazy bum that drops
the idea to scan some elses site is a win.

------
alcat
I make it a habit to put all my public files in directory such as www/, where
as .git and other non public but site-related files/directories are contained
above this.

~~~
dan15
IMO this is the correct approach - Exposing every single file in the
repository (including files that don't need to be public) sounds terrible.

------
marijn
This is too much of blanket statement. As long as there's nothing secret in
the repository, serving up .git is perfectly fine. Both
[http://codemirror.net](http://codemirror.net) and
[http://ternjs.net](http://ternjs.net) (projects by me) have websites that are
simply checkouts of the projects' repositories. Which were already public.

~~~
_wmd
This is pretty much a blanket statement for any project of reasonable size (or
even with just a sole clueless developer). But don't take my word for it,
check the evidence first hand by poking around the list for yourself :)

The solution is so effortless that it seems indefensible to serve .git, when
the risk of doing so is a fleeting moment of forgetfulness leading to your
site and databases getting pwned. Kind of like /etc/passwd being "public" so
long as nobody puts their password in their GECOS field. Why take the risk.

~~~
tingletech
Back in the 90s I found I could get to /etc/passwd of a campus machine via
anonymous ftp. I got all worried and I reported to the sysadmin, and they said
anyone of the thousands of students who could log into the machine could read
/etc/passwd anyway, and it was not a big deal because the passwords were in
/etc/shadow and the anonymous ftp user could not read that file. This was back
before ssh, and I think I expressed a concern about people knowing who had
accounts on the machine, but you could tell if someone had an account via
finger. Still seems like a bad idea to me. But if .git is from a public repo
on github already I don't see the issue.

~~~
_wmd
So long as the initial checkout wasn't made via
[https://user:password@github.com/your/repo/](https://user:password@github.com/your/repo/)
URL it might not be an issue. But git doesn't warn in this case, happily
writes the password you provide in plaintext to your web root, and you may
never notice anything is wrong until much later. If it's not that, then
perhaps it's the rude comment made about a coworker in COMMIT_EDITMSG that you
abandoned before committing..

Even if neither of these were the case, the general principle of unnecessarily
exporting chunks of internal state is asking for trouble somewhere, even if
you can't think of a good reason why it would bite today.

------
drdaeman
I think there's nothing wrong with this if there aren't (and weren't) any
secrets directly embedded in the source code and all configuration files that
contain sensitive information are (and always were) properly gitignore'd.

Tech-savvy users can even be encouraged to pull the code and send patches. :)

~~~
wldlyinaccurate
Somebody correct me if I'm wrong here, but doesn't the .git directory
essentially contain the entire history of the repository? The history could
easily contain sensitive information like passwords. It will contain names
email addresses of contributors, too. Try it yourself: cat .git/logs/HEAD

~~~
tokenizerrr
Why would it contain passwords?

~~~
DigitalJack
Naive users have left passwords in by mistake, only to make another mistake in
thinking a commit takes care of it.

~~~
krapp
I've done this, accidentally published my livejournal passwords on a project.
Now I make certain that at the very least I have a folder covered by
.gitignore in my local repo that contains any auth tokens or whatnot and I
double check the history before pushing it anywhere.

------
scubbo
I feel incredible stupid asking this, but...how?

I'm running a (very small) personal site on lighttpd, and updating it via git.
I checked my.server.com/.git/config - and was duly served the config file.
Eek!

So I edited my /var/www/lighttpd/lighttpd.conf file, and added the following
lines: $HTTP["url"] =~ ".git" { url.access-deny = ("") }

and (I have used [asterisk] for the symbol, here, as otherwise it rendered my
text italic)

$HTTP["host"] =~ "(.[asterisk])" { url.redirect = ( "^/.git(.*)" =>
"%1/nope.html" ) }

And restarted the server.

But my.server.com/.git/config still served up the config file. What am I
missing?

~~~
fallenhitokiri
Instead of messing around with access and redirect stuff I would suggest, as
others have in this thread, that you just put your files in a subdirectory and
use this subdirectory as root for lighttpd.

Problem solved with two commands and you can also add additional stuff to your
repository like sources before they went through different processors (coffee
script, SASS,...) or various drafts. This way you also have a full copy of
everything you need for your site in case something happens to your
workstation.

~~~
scubbo
OK, now I'm REALLY confused.

I've moved all my documents from /var/www/lighttpd/mainSite to
/var/www/lighttpd/mainSite/webdocs (leaving .git in .../mainSite).

I've updated /etc/lighttpd/lighttpd.conf to point at
/var/www/lighttpd/mainSite/webdocs, and confirmed that it's pointing at the
right place by editing a file, and confirming that that change shows up on the
site.

I've confirmed that there is no .git folder in webdocs (you never know!)

But calling my.site.com/.git/config still serves a file!?

Time to go ask on some lighttpd fora...

~~~
_wmd
Hit refresh in your browser. :)

~~~
scubbo
Cleared the cache, refreshed, it's still there. Weirdness abounds.

------
dan15
.git should never be in your web root... I can't think of any situation (other
than a very simple site) where you'd want to just stick the whole Git
repository in the web root. Normally there's a bunch of other things in the
repository (documentation, database scripts, etc.) that you wouldn't want
exposed publicly.

~~~
dsirijus
You can hide it very easily with any of the virtual host syntax, and it's easy
to deploy that way. I say, why not.

~~~
brown9-2
You could also very easily add one additional command to your deploy script to
copy all the web content from the directory being pulled to to the web root,
and not have to worry about any accidents.

~~~
astrodust
Or you could set the web root to be that directory.

------
kpommerenke
Same problem with subversion. Try
[http://yoursite/.svn/entries](http://yoursite/.svn/entries)

If you use Apache, you can add the following to prevent the .svn directories
from being served: <LocationMatch ". _\\.svn._ "> Order allow,deny Deny from
all </LocationMatch

------
andyhmltn
This is a brilliant post. I was about to deploy a site before I read this.
It's so easy just to forget that directory.

------
rlpb
You can keep the same workflow but just have .git somewhere else. Just define
GIT_DIR.

~~~
dougws
Last I checked, GIT_DIR wasn't actually respected by a lot of git subcommands.
Is that no longer the case?

~~~
rlpb
As far as I'm aware, it's respected by every git subcommand. I've never had a
problem using it. Do you have any specific examples?

------
coolj
Defcon 19: Adam Baldwin - Pillaging DVCS Repos For Fun And Profit:
[https://www.youtube.com/watch?v=3Tq8tUDKUH0](https://www.youtube.com/watch?v=3Tq8tUDKUH0)

------
andrewflnr
In a word: Rsync. What I do is have source files in one directory, filter them
over to another with, at the moment, jinja2, then rsync that to my server
using a shortcut script. The filtering is the tricky part.

------
level09
I used to restrict that globally in my nginx / apache configurations (since I
mainly work with these two web servers).

------
michaelmior
I just push to a repo out of the web root that has a git hook which sets
GIT_WORK_TREE to my web root and does a checkout.

------
johnbburg
devs aren't always the ones deploying the sites they develop! Also, non-
standard file extensions for source code is often exposed and should probably
be hidden. (e.g. .module for drupal sites).

------
binarydreams
Just keep the .git bare repo outside the document root.

------
trapezor
This is clearly Ops problem.

~~~
DDub
yes, but that doesn't make it not a dev problem.

~~~
andyzweb
devops

------
kumar303
or, to put it another way, please stop writing closed source software ;)

