Weakness reference
CWE-552

Files or Directories Accessible to External Parties

This weakness occurs when sensitive files or directories—such as configuration files, private keys, database backups, or source code—are stored in locations…

01Summary

This weakness occurs when sensitive files or directories—such as configuration files, private keys, database backups, or source code—are stored in locations that are publicly accessible over the web or network. An attacker can discover and download these files without authentication, leading to exposure of credentials, API keys, or other confidential data.

02How It Happens

Developers often place files in web-accessible directories (like the document root) for convenience during development, then forget to move or restrict them before deployment. This can happen through misconfigured web servers that serve files outside the intended public directory, backup files left in place, or configuration files accidentally committed to a public repository. The underlying issue is a failure to enforce proper access controls and directory separation between public and private resources.

03Real-World Impact

Exposed configuration files can reveal database credentials, API keys, or encryption secrets. Backup files may contain entire databases or source code. Private keys can be used to impersonate the application or decrypt sensitive communications. In many cases, a single exposed file provides an attacker with enough information to escalate to full system compromise or data theft.

04Vulnerable & Fixed Patterns

Vulnerable pattern
# Flask app storing sensitive config in web root
import os
from flask import Flask

app = Flask(__name__)

# Config file placed in static/ directory (publicly served)
config_path = os.path.join(app.static_folder, 'config.ini')
with open(config_path, 'r') as f:
    config_data = f.read()
    # Contains: DATABASE_PASSWORD=secret123, API_KEY=xyz789

Why it's vulnerable:
The configuration file is stored in the static/ folder, which Flask serves directly to any HTTP request. An attacker can request /static/config.ini and retrieve all secrets.

Fixed pattern
# Config stored outside web root with restricted permissions
import os
from flask import Flask

app = Flask(__name__)

# Config file in parent directory, outside static/ and not web-accessible
config_path = os.path.join(os.path.dirname(app.root_path), 'config.ini')
with open(config_path, 'r') as f:
    config_data = f.read()

# Ensure file permissions are restrictive (owner read-only)
os.chmod(config_path, 0o600)
Vulnerable pattern
<?php
// WordPress site with backup database in web root
$backup_file = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/db_backup.sql';

if (file_exists($backup_file)) {
    // Backup is publicly accessible at example.com/wp-content/db_backup.sql
    $db_data = file_get_contents($backup_file);
}
?>

Why it's vulnerable:
The SQL backup file is stored directly in wp-content/, which is served by the web server. An attacker can download it via a direct HTTP request.

Fixed pattern
<?php
// Backup stored outside document root
$backup_dir = dirname($_SERVER['DOCUMENT_ROOT']) . '/backups/';
$backup_file = $backup_dir . 'db_backup_' . date('Y-m-d') . '.sql';

// Ensure directory exists and is not web-accessible
if (!is_dir($backup_dir)) {
    mkdir($backup_dir, 0700, true);
}

// Write backup with restrictive permissions
file_put_contents($backup_file, $backup_data);
chmod($backup_file, 0600);
?>

05Prevention Checklist

Separate public and private directories.
Store all sensitive files (configs, keys, backups, logs) outside the web root or document root.
Use environment variables or secure vaults.
Never hardcode secrets in files; use environment variables, .env files (outside web root), or a secrets management system.
Restrict file permissions.
Set ownership and permissions (e.g., 0600 or 0700) so only the application user can read sensitive files.
Audit your deployment.
Before going live, verify that no .sql, .env, .key, .pem, .conf, or backup files are in publicly served directories.
Configure web server correctly.
Ensure your web server (Apache, Nginx) is configured to serve only the intended public directory and denies access to parent directories.
Remove development artifacts.
Delete or move .git, .env.example, composer.lock, package-lock.json, and other files that may leak information before deployment.

06Signs You May Already Be Affected

Check your web server logs for requests to suspicious file paths like /config.php, /backup.sql, /.env, or /.git/config. Use a web scanner or manual inspection to verify that sensitive files are not accessible via HTTP requests to your domain. Review your deployment process and directory structure to confirm that no configuration, key, or backup files exist in your document root.

07Related Recent Vulnerabilities