The robotsThe thief's own card
The thief's list
Every day, programs ask Pyssly for files we have never had: passwords, source code and backups. Here is the list, how many times they have asked, why a thief wants each file, and how to protect your own site.

Who is the thief?
The thief is usually not a person sitting there searching. It is a program that goes from site to site with the same list and asks for every file on it.
If a site answers with the file, the thief has the key without breaking anything open. Pyssly has none of these files, so the thief gets a pretend page and we count the request.
If you have a homepage, a website or a server: make sure these files cannot be downloaded. At the bottom you can see how to check.
Most wanted
This is how many times robots have asked Pyssly for the files.
Counting …
Passwords and keys
The biggest treasure: a single file with everything that unlocks the site.
/.envCounting …What is it? A small text file where many sites keep their secrets: the database password, keys for payment and email services, and the key that keeps logins safe. Also variants like .env.production and env.js.
Why does the thief want it? With it, the thief can log in to the database, send email in the site's name or use the site's accounts at other services.
/config.jsonCounting …What is it? Settings files: config.json, settings.py, web.config, docker-compose.yml, appsettings.json, credentials.json, a cloud account's service-account.json and Terraform's terraform.tfvars.
Why does the thief want it? They often hold the same secrets as .env, and also where the database and the servers are. A service-account.json or a tfvars file can give away the whole cloud account.
/id_rsaCounting …What is it? An SSH key: the secret half of the key that lets someone log in to a server without a password.
Why does the thief want it? Whoever has the file can often log in to the server right away, just like the owner.
/.htaccessCounting …What is it? Other files whose names start with a dot, like .htaccess, .htpasswd, .DS_Store and .bash_history. The dot means hidden on your computer, but not on the web.
Why does the thief want it? They show how the server is set up and which files exist, and sometimes passwords (.htpasswd) or commands someone typed.
How to protect yourself
- Never put secrets in the folder the web server shows to the world. Read them from environment variables or a secrets service (secrets in Kubernetes, GitHub Actions or the cloud) instead.
- Block all files and folders that start with a dot in the web server, except /.well-known/. How to do it is further down.
- Never put a private key in the web folder, and keep your own login keys to yourself, protected with a passphrase.
Source code
The whole site's code, with every change that was ever made.
/.git/Counting …What is it? The folder where Git keeps a project's whole history. If it sits on the server, anyone can download all the code, file by file.
Why does the thief want it? In the code, the thief looks for passwords that someone once added and later removed (they stay in the history), and for bugs to use.
/.svn/Counting …What is it? The same thing for older version control tools: Subversion (.svn), Mercurial (.hg), Bazaar and CVS.
Why does the thief want it? Just like .git: source code and old secrets.
How to protect yourself
- Never upload the .git folder. Build the site and send only the built result, or keep the folder out with a .dockerignore.
- Block dot folders in the web server for extra protection.
- If a password was ever in the code: change it. Deleting it in a new change is not enough, because it is still in the history.
Databases and backups
Copies that someone put on the server for a while and then forgot.
*.sqlCounting …What is it? A database dump: the whole database as one file, for example backup.sql or db.sql.gz.
Why does the thief want it? It holds everything the site knows: users, email addresses, passwords (hopefully hashed) and orders. A data leak in one go.
*.bakCounting …What is it? Backups and old versions: .bak, .old, .orig, .swp, and archives like site.zip or backup.tar.gz.
Why does the thief want it? A wp-config.php.bak is shown as plain text instead of being run, so the passwords are right there. A zip archive can be the whole site.
How to protect yourself
- Keep backups outside the web folder, preferably on another machine.
- Block .sql, .bak, .zip and the like in the web server.
- Don't edit files directly on the server: editors leave copies like .swp and ~ behind.
WordPress
WordPress runs a big part of the web, so the thief always tries its doors, even on sites without WordPress, like Pyssly.
/wp-login.phpCounting …What is it? The WordPress login page.
Why does the thief want it? The thief tries common usernames and passwords again and again, hoping one fits.
/wp-admin/Counting …What is it? The folder for the WordPress admin panel, with the install page inside.
Why does the thief want it? A half-finished install can be completed by the thief, who then becomes admin. Otherwise it is the same door as the login.
/xmlrpc.phpCounting …What is it? An old WordPress interface for publishing from other programs.
Why does the thief want it? In old versions the thief could try hundreds of passwords in a single request. It is still a door for guessing passwords, and pingbacks can make the site send traffic at other sites.
/wp-content/Counting …What is it? The folder with plugins, themes and uploaded files.
Why does the thief want it? The thief looks for old plugins with known security holes, and for backups that plugins have left there.
/wp-includes/Counting …What is it? WordPress's own program files.
Why does the thief want it? They show which version the site runs, and so which known holes may be there.
/wp-json/Counting …What is it? The WordPress REST interface.
Why does the thief want it? It can list the site's usernames, so the thief knows which accounts are worth trying passwords on.
/wp-config.phpCounting …What is it? The WordPress settings file, with the database password and the site's secret keys.
Why does the thief want it? When PHP runs as it should, nobody sees the contents, but a copy (wp-config.php.bak, wp-config.php~) or a broken server shows everything.
How to protect yourself
- Update WordPress, themes and plugins, and remove plugins you don't use.
- Turn on two-step login, and switch off xmlrpc.php if you don't need it.
- WordPress also looks for wp-config.php one folder above its installation. Move it there only if that folder is not itself served on the web, and never leave copies of the file.
Database tools
Programs that let you manage the database from a web page.
/phpmyadmin/Counting …What is it? phpMyAdmin, a common tool for managing MySQL databases in the browser.
Why does the thief want it? If the thief finds it, it tries passwords, or known holes in old versions. If it gets in, it has the whole database.
/adminer.phpCounting …What is it? Adminer, a similar tool in a single file that often gets uploaded for a while and forgotten.
Why does the thief want it? Same as phpMyAdmin: a login straight into the database.
How to protect yourself
- Don't put database tools on the public site. Run them on your own computer and reach the database through an SSH tunnel or a VPN.
- If they have to be there: lock them behind an extra login or a list of allowed addresses.
Debug pages
Pages that developers use to look inside a site while it runs. Great on your own computer, dangerous on the web.
/phpinfo.phpCounting …What is it? A page that shows all of PHP's settings, including the environment variables.
Why does the thief want it? Passwords and keys are often there, plus paths and exact versions: a map of the server.
/vendor/phpunit/Counting …What is it? A testing tool for PHP that sometimes comes along to the server in the vendor folder.
Why does the thief want it? Old versions have a hole that lets anyone run their own code on the server.
/actuator/Counting …What is it? Spring Boot's operations pages for Java apps.
Why does the thief want it? Some of them show environment variables, settings or a memory dump with passwords in it.
/server-statusCounting …What is it? Apache's status page, which shows what the server is doing right now.
Why does the thief want it? It shows which addresses all visitors ask for, sometimes with secret links and keys in them.
/_ignition/Counting …What is it? Ignition, the debug page in Laravel.
Why does the thief want it? Old versions have a hole that lets the thief run their own code, and an error page often shows the settings.
/_profiler/Counting …What is it? Symfony's profiler, which saves every request with everything that was in it.
Why does the thief want it? It shows logins, sessions and settings for every visit, including other people's.
How to protect yourself
- Never run a site in debug mode on the web: APP_DEBUG=false, and no development setup in production.
- Remove phpinfo files and test tools before the site goes live (composer install --no-dev).
- Lock operations pages like Actuator and server-status to your own address or an internal network.
Old doors
Programs and pages that the server runs when someone asks for them.
/cgi-bin/Counting …What is it? A folder for old scripts that the server runs, often in Perl or shell.
Why does the thief want it? Old scripts have known holes, like Shellshock, that let the thief run commands on the server.
/boaform/Counting …What is it? Settings pages on routers and cameras (boaform, HNAP1).
Why does the thief want it? The thief looks for devices to take over with old holes or factory passwords, to use them in a botnet.
*.phpCounting …What is it? Any PHP file at all, for example shell.php or a file with a strange name.
Why does the thief want it? Often the thief is looking for a backdoor (a web shell) that someone else has already put on the site, to take it over.
*.aspCounting …What is it? Programs in other languages that the server runs: .asp, .aspx, .jsp and .cgi.
Why does the thief want it? Same as with PHP: known holes in old pages, or a backdoor that is already there.
How to protect yourself
- Remove everything the server doesn't need to run: old scripts, test pages and folders like cgi-bin.
- Change the factory password on routers and cameras, update them, and never show their settings pages to the internet.
- Let only what should run be run: an uploaded file must never be able to run as code.
Shops and phishing sites
Two kinds of searching that are not a break-in right away, but close.
/cart.jsCounting …What is it? Files that every Shopify shop has, like cart.js and products.json.
Why does the thief want it? With them the program finds shops and reads off goods and prices, often to copy them into fake shops.
/lander/Counting …What is it? Leftovers from a phishing kit: landing pages and scripts that imitate a bank or a parcel delivery.
Why does the thief want it? Whoever asks is looking for sites where someone has already put such a kit: hacked sites to use again.
How to protect yourself
- What a shop shows to everyone, everyone can read. Don't put anything secret in goods or product fields.
- If you see a folder or file you don't recognize on your server, like lander/: someone may have broken in. Remove it, change all passwords and update everything.
Block them in the web server
The best protection is that the files are never on the server. The blocks here are an extra safety in case something ends up there anyway.
All of them leave /.well-known/ open, because it is needed for things like certificates. Try them on a test site first.
# First in the server block: nginx takes the first regex location that matches,
# and a location ^~ (such as /static/) skips them, so repeat these inside it.
# Dotfiles (.env, .git, .htaccess) at any depth, but not /.well-known/
location ~ /\.(?!well-known/) {
return 404;
}
# Databases, backups and old copies
location ~* \.(sql|bak|old|orig|swp|zip|tar|gz|7z)$ {
return 404;
}# Dotfiles (.env, .git, .htaccess) at any depth, but not /.well-known/
RedirectMatch 404 "/\.(?!well-known/)"
# Databases, backups and old copies
<FilesMatch "\.(sql|bak|old|orig|swp|zip|tar|gz|7z)$">
Require all denied
</FilesMatch># Dotfiles (.env, .git, .htaccess) at any depth, but not /.well-known/
@hidden {
path_regexp /\.
not path_regexp ^/\.well-known/([^./][^/]*/?)*$
}
respond @hidden 404
# Databases, backups and old copies, /.well-known/ included
@copies path_regexp \.(sql|bak|old|orig|swp|zip|tar|gz|7z)$
respond @copies 404**/.git
**/.env*
**/*.sql
**/*.bak
**/*.zip
**/id_*
**/*.tfvarsHow to check
Five minutes in a terminal. Swap example.com for your own address.
Only check your own site. Looking for other people's files is exactly what the thief does.
Ask for .env
curl -sS -i https://example.com/.envLook at both the answer and what comes with it. 404 or 403 is good. If your settings come back, the file is public. (If the site answers 200 to everything, as many apps do, what comes back should be your normal page.)
Ask for .git
curl -sS -i https://example.com/.git/HEADIf you see a line like ref: refs/heads/main, the whole source code is out in the open. An error page or your normal page is good.
Try under other folders
curl -sS -i https://example.com/static/.envA block can be missed in folders that are served directly, like /static/ or /assets/. Try there, and try more files from the list, like a .sql or an old copy of a settings file. What counts is whether the content shows.
Look in the log
grep -E '\.env|\.git/|wp-login|phpinfo|\.sql' /var/log/nginx/access.logThe requests come every day, so seeing them is nothing strange. A 200 in the log does not prove a leak, since many apps answer 200 with their normal page. If you see a 200 for .env or .git/HEAD, fetch the address as above and look at what comes back.
If a file got out
- Remove the file and block the address.
- Change every password and key that was in it: the database, the email, payment services and the cloud account. Assume the thief already has them.
- Look in the log for who fetched the file, and whether anything has happened to the accounts since.
More about thieves and other kinds of robots in How the robots work.