How this check works
Scanaris requests a list of paths where files that should never sit on a public server tend to remain: .env, .env.local, .env.production, .git/config, .git/HEAD, wp-config.php, config.json, docker-compose.yml, backup.sql, phpinfo.php, .npmrc, Dockerfile, .gitlab-ci.yml, .aws/credentials, .ssh/id_rsa, web.config, adminer.php and .DS_Store. A 200 is not enough to flag anything: many single-page applications answer 200 with their HTML on any path. That is why the scanner checks that the content looks real, for example that a .env has KEY=value lines and is not HTML, or that .git/HEAD starts with ref:. Severity depends on the file: critical for .env, database dumps and private keys; high for .git and server configurations; low for .DS_Store or a Dockerfile.
What an attacker does with this
The same as the scanner, but against every domain that exists. A reachable .env hands over the database credentials, the payment keys and the email tokens in one go. An exposed .git directory lets anyone download the full repository with a command-line tool, with the entire history, including keys deleted in a later commit. A backup.sql is your whole database, users and hashed passwords included. It is one of the simplest flaws to exploit and one of the most serious.
Why it happens
Two causes. The first is deploying the whole project folder instead of the build output folder: everything in the repository becomes servable. The second is a web server (nginx, Apache, IIS) serving a folder where development or backups also happen. Platforms like Vercel or Netlify only publish the output folder, which is why there this flaw usually comes down to files copied by mistake into public/.
How to fix it
- Remove the file and rotate everything it contained. If a
.envwas reachable, every key inside it is compromised even if nobody told you. - Deploy only the build output (
dist/,.output/,.next/), never the project root. In Express,express.staticmust point at that folder. - Block the paths on the server as a second barrier. In nginx:
location ~ /\.(?!well-known) { deny all; }blocks everything starting with a dot except.well-known; add rules for*.sql,*.ymland*.log. In Apache, the equivalent withFilesMatchandRequire all denied. - Review your project's public/ folder: nothing should be there except images, fonts or files meant to be downloaded.
- Look at the access logs for requests to
/.envor/.gitwith a 200 response to know whether someone got there before you.
Check it is fixed
for p in .env .env.local .git/config .git/HEAD config.json backup.sql docker-compose.yml .npmrc; do
printf "%-20s " "$p"; curl -s -o /dev/null -w "%{http_code}\n" "https://yourdomain.com/$p"
done
Expected: 404 or 403 on all of them. A 200 on an SPA may be the usual HTML: open it and confirm it is not the real file.
Frequently asked questions
My site answers 200 on every path. Will it flag false positives?
No. The scanner validates the content before opening a finding; a generic HTML page does not count as a .env.
Why is .DS_Store a finding if it contains no secrets?
Because it lists the names of the files in the folder, including the ones you do not link from any page. It is a free map for anyone looking for backups or forgotten files. Low severity, but worth removing.
What about the .well-known paths?
Those must be reachable: that is where security.txt, domain verifications and certificates live. The nginx rule in the example excludes them from the block.