Search code examples
laravel.htaccesshttp-redirectmod-rewrite

how to allow /.well-known/security.txt in htaccess


I want to whitelist this file only in .well-known directory .

My htaccess file

Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_URI} !^public 
RewriteRule ^(.*)$ public/$1 [L]

<IfModule mod_rewrite.c>
  RewriteCond %{SCRIPT_FILENAME} -d [OR]
  RewriteCond %{SCRIPT_FILENAME} -f
  RewriteRule "(^|/)\." - [F]
</IfModule>

my attempts

<Files .well-known/security.txt>
Allow from all
Satisfy Any
</Files>
RewriteEngine on
RewriteCond %{REQUEST_URI} !^(public|.well-known/security.txt)
RewriteRule ^(.*)$ public/$1 [L]

Conclusion ! I just want to whitelist security.txt file only in .well-known directory


Solution

  • RewriteCond %{REQUEST_URI} !^public 
    RewriteRule ^(.*)$ public/$1 [L]
    

    This condition is in error since the REQUEST_URI server variable always starts with a slash, so the expression !^public is always successful.

    (From this I assume you must have another .htaccess file in the /public subdirectory, otherwise you would get a rewrite loop.)

    Once you realise this then you can modify the rule in the way you had tried. For example:

    RewriteCond %{REQUEST_URI} !^/(public|\.well-known/security\.txt$)
    RewriteRule ^(.*)$ public/$1 [L]
    

    HOWEVER, your other rule blocks all requests for physical files/directories that start with a dot, so the request will still be blocked (with a 403 Forbidden). This rule is also in the wrong place for other requests (it needs to be before the rewrite to the /public subdirectory).

    You are better off making an exception as a separate rule at the start of the file instead. For example, try the following instead:

    Options -Indexes
    
    RewriteEngine on
    
    # Prevent further processing for special files
    RewriteRule ^\.well-known/security\.txt$ - [L]
    
    # Block access to all dot-files
    RewriteCond %{SCRIPT_FILENAME} -d [OR]
    RewriteCond %{SCRIPT_FILENAME} -f
    RewriteRule (^|/)\. - [F]
    
    # Rewrite request to "/public" subdirectory
    RewriteCond %{REQUEST_URI} !^/public
    RewriteRule (.*) public/$1 [L]
    

    The <IfModule> wrapper on that one rule was superfluous.