How to remove 'Parent Directory' link from root folder in Apache directory listing

25,391

Solution 1

I just ran into the same issue, and this was the first search result, so I thought I'd share my solution. I don't have access to httpd-configs in my case, so I went with a different approach.

Because I won't be maintaining the indexed directory tree, I needed a solution that could exist just in the index root without any specific knowledge of its sub-directories. However, it does use an absolute path to the index root, so if your parent folder structure changes a lot, it may not work for you.

What I came up with was using a CSS URL attribute selector to hide the "Parent Directory" link when it led to the parent of the index root. It leaves a blank row, but at least it's not as intimidating as the "403 FORBIDDEN" error a user gets if they click Parent Directory one too many times.

Theoretically, the fix should be as simple as adding one line to your index root's .htaccess file:

IndexHeadInsert "<style type=\"text/css\">a[href=\"/absolute/path/to/index/root/parent/\"] {display: none;}</style>"

However, it seems that simple solution doesn't work in IE because the default doctype of the html that Apache spits out is too old to use attribute selectors.

Instead, we have to surround Apache's generated code with our own doctype using the HeaderName and ReadmeName keywords in the htaccess file. I went with the HTML5 doctype, although there may be a more appropriate one that works.

.htaccess file:

Options +Indexes

IndexIgnore "_index_header.html" "_index_footer.html"

HeaderName "/absolute/path/to/root/index/_index_header.html"
ReadmeName "/absolute/path/to/root/index/_index_footer.html"

IndexOptions +SuppressHTMLPreamble

_index_header.html file:

<!DOCTYPE html>
<html>
    <head>
        <title>title</title>
        <style type="text/css">
            a[href="/absolute/path/to/index/root/parent/"] {display: none;}
        </style>
    </head>
    <body>

_index_footer.html file:

    </body>
</html>

(Note that the CSS selector is to the index root's parent)

Works in all of the latest browser versions I tested it on (FF, IE, Chrome, Safari, Opera), and also all the way back to IE 7.

Also, now that you went through all the trouble of creating those files, you might as well make your index more snazzy. The apache doc on mod_autoindex has a bunch of options you can use to tweak things, on top of what you can do with CSS.

Solution 2

You can hide the "Parent Directory" link by adding the following to your .htaccess file:

IndexIgnore ..

But this will hide it for every directory.

If you have access to the httpd-configs you could try to remove the directive from per-server context:

<DirectoryMatch "^/(?!var/www/your-root/subfolder)">
...
</DirectoryMatch>

As long as there is no IndexIgnore directive in an higher folder it should work for you.

Solution 3

My solution is the following:

<Directory "/www"> Options +Indexes IndexIgnore .. _other </Directory>

<DirectoryMatch "^/www/download/.{1,}"> IndexIgnoreReset ON IndexIgnore _other </DirectoryMatch>

Solution 4

It seems like you're not asking the right question.

If your point is to prevent users from accessing the upper directory, removing the link won't solve anything for you since anybody can simply strip the last directory from the URL.

For example, if your subfolder is /var/www/secret/hive/subfolder and your DocumentRoot is set to /var/www, and you share link http://your.example.com/secret/hive/subfolder, anybody can still access http://your.example.com/secret/ or http://your.example.com/secret/hive even without that "Parent folder" link.

What you could do is:

  • Put "empty" index.html in each folder above "subfolder". Apache will then offer that file instead of listing, so the users won't know what's in "secret" or "hive".

  • Disable listing in each folder above "subfolder". Apache will then refuse to show the listing, so the users won't know what's in "secret" or "hive".

However, if users are somehow able to guess names of files, they could still assemble a valid URL like http://your.example.com/secret/password.txt and with enough luck (and/or attempts), they could still get to some non-public information.

What you should do is:

  • set DocumentRoot to /var/www/secret/hive/subfolder,

  • or (better) keep DocumentRoot but move everything that is not public out of /var/www.

so http://your.example.com/ will show only the public information and there's no (HTTP) way how users can even ask for anything above.

Solution 5

There's a working trick to solve this issue, checking the url pathname via JQuery. Just add this code at the top of your .htaccess file (obviously we can't separate paragraph lines here):

IndexHeadInsert "<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script><script>$(document).ready(function(){if(document.location.pathname.split('/').length<4){$('tr:nth-of-type(2)').hide();}});</script>"

Note:

  • you may need to change the pathname length value, in my site is "4" because my archive root starts in a secondary subdirectory (if yours starts in the main root, try different values e.g. "3" or "2", or simply check your location.pathname length before all).

  • the "tr:nth-of-type(2)" css points to the second record, that is the one supposed to manage the "PARENT DIRECTORY" we want to hide if the url location is our main root.

Have fun!

Share:
25,391
Khalid Amin
Author by

Khalid Amin

Software Design/Architecture, Databases(Oracle, MS SQL), Web(PHP, Node.js), Java

Updated on June 25, 2020

Comments

  • Khalid Amin
    Khalid Amin almost 4 years

    How can I allow directory listing in Apache for a specific (root) folder and its subfolders, but without showing a link to parent of that root folder. When user is in a subfolder, the 'Parent Directory'link is displayed to navigate to its parent, but when user is at the root folder I need to remove/hide this 'Parent Directory' link so that user cannot move above that 'root' hierarchy.

  • Luke
    Luke over 7 years
    no need for jquery. IndexHeadInsert "<script>if (document.location.pathname == '/') document.querySelector('tbody > tr:nth-child(3)').remove();</script>" should work fine. For some reason my "parent directory" is the 3rd row (I have a header row and a separator before the directory listing starts). Change '/' to whatever pathname you want to hide the parent link for, eg. '/builds/' - it should automagically be hidden for a root pathname anyway.
  • Luke
    Luke over 7 years
    The css approach seems to only hide the link (as you mention). You can use insert a <script> tag instead of a <style> and use javascript to hide the whole row. See stackoverflow.com/a/31904749/1704773 and it's comments below.
  • dr_
    dr_ almost 7 years
    @itoctopus I agree. It's simple and clean. The accepted answer is a kludge.
  • Kevin Jablonski
    Kevin Jablonski about 6 years
    I had to change your answer to this IndexHeadInsert "<script>document.addEventListener('DOMContentLoaded',functi‌​on() {if (document.location.pathname == '/sub-folder/') document.querySelector('tbody > tr:nth-child(3)').remove();},false);</script> This forces the javascript to execute once the DOM is ready
  • Elgoots
    Elgoots almost 6 years
    This is a great option. Works perfectly. The solution will remove the link only in the /www folder but every sub folder within it will be ok. Essentially its almost like you can make your own top level directory visually.
  • MrWhite
    MrWhite over 2 years
    The existing answer from 2012 already states this. But this does not resolve the problem, since this will also remove the "Parent Directory" link from all subdirectories as well, which is not what the OP is wanting.
  • SaidbakR
    SaidbakR over 2 years
    @MrWhite We can workaround this limitation by adding a .htaccess in every subfolder without IndexIgnore.