Fix guide · critical · exposed_htpasswd
.htpasswd file exposed — password hashes leaked
Your /.htpasswd file is publicly reachable. It contains usernames and bcrypt / SHA-1 / crypt password hashes. The hashes are CRACKABLE OFFLINE — attackers run hashcat against them and recover the passwords at their leisure.
Why it matters
.htpasswd is the file Apache uses for HTTP Basic Auth. Each line is username:hash. The hash format depends on how the file was generated:
- bcrypt (
$2y$...) — the modern default. Strong, but still crackable for weak passwords. APassword1!hash gets recovered in seconds. - MD5 crypt (
$apr1$...) — Apache's own MD5-based format. Considered broken; hashcat does ~1B/s on consumer hardware. - SHA-1 (
{SHA}...) — fast hash with no salt. Recovered for any common password in minutes. - Traditional crypt (
<13 chars>) — uses DES with only 8 chars of password material. Recovered in hours regardless of password strength.
Once an attacker recovers the credentials they get whatever access .htpasswd gates — typically an admin panel, internal tool, or staging environment. In real audits, the gated area is usually less secure than the front of the site because operators relied on Basic Auth alone for everything inside.
How to fix it
- Move the file outside the document root.
.htpasswdshould NEVER be reachable via HTTP. Reference it via an absolute filesystem path in your Apache config:AuthUserFile /etc/apache2/.htpasswd. - If it's already exposed, assume the hashes are compromised. Rotate every password in the file. Email anyone whose username was listed.
- Add a server-level block for
.ht*paths. Default Apache config does this — confirm yours hasn't been overridden:
``apache <FilesMatch "^\.ht"> Require all denied </FilesMatch> ``
- Consider replacing Basic Auth. For team access to admin panels, OAuth + SSO (or even a single-factor flag in your app's auth model) provides better audit trails and is no harder to operate.
Did vibecheck flag this on your app?
If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.
Run another inspection