Initialization of a Resource with an Insecure Default

Description

Initialization of a Resource with an Insecure Default occurs when a product initializes or sets a resource with a default value that is intended to be changed by the product's installer, administrator, or maintainer, but the default is not secure. Developers often prioritize ease-of-use by creating permissive default configurations, assuming administrators will modify them. However, this assumption frequently fails when administrators either overlook the defaults or lack awareness that changes are necessary, leaving the system vulnerable.

Risk

Insecure defaults have significant security implications. Default passwords are commonly exploited by attackers. Permissive access control defaults allow unauthorized access. Debug modes enabled by default expose sensitive information. Insecure default ports or protocols may be used. Default encryption settings may be weak or disabled. Administrative interfaces may be exposed by default. Logging defaults may omit security events. Resource limits may be too permissive. Users assume secure-by-default and don't change settings.

Solution

Apply secure-by-default principles. Require explicit opt-in for less secure configurations. Use strong random defaults for credentials and keys. Default to deny-all access control. Disable debug and test features by default. Use secure protocols by default (HTTPS, TLS). Require password changes on first use. Document all security-relevant defaults clearly. Provide configuration wizards that prompt for secure settings. Log warnings when insecure defaults are in use. Default to minimal functionality.

Common Consequences

ImpactDetails
OtherScope: Other

Varies By Context - The negative effects depend heavily on what functionality the insecure default controls, ranging from information disclosure to complete system compromise.
Confidentiality/Integrity/AvailabilityScope: All

Security Compromise - Insecure defaults in authentication, authorization, or encryption can lead to full system compromise.

Example Code

Vulnerable Code

// Vulnerable: PHP with register_globals-style vulnerability
// Default allows request parameters to set internal variables

<?php
// $user and $pass automatically set from POST request (old PHP behavior)
// But so is $authorized if attacker includes it in POST!

if (login_user($user, $pass)) {
    $authorized = true;
}

if ($authorized) {
    // Attacker can bypass by POSTing authorized=true
    generateAdminPage();
}
?>
# Vulnerable: Python application with insecure defaults

class DatabaseConfig:
    def __init__(self):
        # Insecure defaults - should require explicit secure configuration

        # Default to no authentication!
        self.host = "localhost"
        self.port = 5432
        self.username = "postgres"
        self.password = ""  # Empty password by default!
        self.ssl_mode = "disable"  # SSL disabled by default!

        # Permissive connection settings
        self.max_connections = 1000  # Too many - DoS risk
        self.connection_timeout = 0  # No timeout - resource exhaustion


class AppConfig:
    def __init__(self):
        # Debug mode on by default - exposes sensitive info
        self.debug = True
        self.log_level = "DEBUG"  # Logs sensitive data

        # Weak session defaults
        self.session_secret = "change-me"  # Known default!
        self.session_timeout = 86400 * 30  # 30 days - too long

        # Insecure CORS defaults
        self.cors_origins = "*"  # Allow all origins

        # Admin interface exposed by default
        self.admin_enabled = True
        self.admin_path = "/admin"  # Predictable path


class UserDefaults:
    # Default admin account with known credentials
    ADMIN_USERNAME = "admin"
    ADMIN_PASSWORD = "admin123"  # Weak, known default password

    # Default permissions too permissive
    DEFAULT_ROLE = "admin"  # Should be "user" or "guest"
// Vulnerable: Java with insecure defaults

public class SecurityConfig {

    // Insecure default constructor
    public SecurityConfig() {
        // Debug enabled by default
        this.debugMode = true;

        // Weak crypto defaults
        this.encryptionAlgorithm = "DES";  // Weak algorithm
        this.keySize = 56;  // Too small

        // Permissive CORS
        this.allowedOrigins = Arrays.asList("*");
        this.allowCredentials = true;  // Dangerous with wildcard origin

        // No rate limiting by default
        this.maxRequestsPerMinute = Integer.MAX_VALUE;

        // Insecure session defaults
        this.sessionTimeout = 60 * 60 * 24 * 365;  // 1 year!
        this.cookieSecure = false;  // Sent over HTTP too
        this.cookieHttpOnly = false;  // Accessible to JS

        // Default admin account
        this.defaultAdminPassword = "admin";
    }
}

// Spring Security with insecure defaults
@Configuration
public class InsecureWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // CSRF disabled by default - bad for web apps
            .csrf().disable()

            // No authentication required by default
            .authorizeRequests()
            .anyRequest().permitAll()

            // Frame options disabled - clickjacking risk
            .and().headers().frameOptions().disable();
    }

    // Default user with known password
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("admin")
            .password("{noop}admin")  // Plain text, known password
            .roles("ADMIN");
    }
}
// Vulnerable: Node.js/Express with insecure defaults

const express = require('express');
const session = require('express-session');

const app = express();

// Insecure session configuration
app.use(session({
    secret: 'keyboard cat',  // Known default secret!
    resave: false,
    saveUninitialized: true,  // Creates sessions for unauthenticated users
    cookie: {
        secure: false,  // Sent over HTTP
        httpOnly: false,  // Accessible to JavaScript
        maxAge: 1000 * 60 * 60 * 24 * 365  // 1 year!
    }
}));

// CORS wide open by default
const cors = require('cors');
app.use(cors());  // Allows ALL origins

// No rate limiting
// No CSRF protection
// No helmet security headers

// Debug info exposed
app.get('/debug', (req, res) => {
    res.json({
        env: process.env,  // Exposes environment variables!
        config: app.settings
    });
});

// Default admin credentials
const DEFAULT_ADMIN = {
    username: 'admin',
    password: 'password123'  // Weak default
};

Fixed Code

// Fixed: PHP with secure initialization

<?php
// Explicitly initialize security-critical variables
$authorized = false;  // Secure default

// Get input explicitly
$user = filter_input(INPUT_POST, 'user', FILTER_SANITIZE_STRING);
$pass = filter_input(INPUT_POST, 'pass', FILTER_SANITIZE_STRING);

// $authorized cannot be set via POST - it's initialized above
if ($user && $pass && login_user($user, $pass)) {
    $authorized = true;
}

if ($authorized) {
    generateAdminPage();
}
?>
# Fixed: Python with secure defaults

import os
import secrets
from typing import Optional

class DatabaseConfig:
    def __init__(
        self,
        host: str,
        port: int,
        username: str,
        password: str,  # Required - no default
        ssl_mode: str = "require"  # SSL required by default
    ):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.ssl_mode = ssl_mode

        # Secure connection defaults
        self.max_connections = 100  # Reasonable limit
        self.connection_timeout = 30  # 30 second timeout

    @classmethod
    def from_env(cls):
        """Create config from environment - fails if not configured."""
        password = os.environ.get('DB_PASSWORD')
        if not password:
            raise ValueError("DB_PASSWORD environment variable required")

        return cls(
            host=os.environ.get('DB_HOST', 'localhost'),
            port=int(os.environ.get('DB_PORT', '5432')),
            username=os.environ.get('DB_USER', 'app'),
            password=password
        )


class AppConfig:
    def __init__(self):
        # Secure defaults
        self.debug = False  # Debug OFF by default
        self.log_level = "WARNING"  # Don't log sensitive data

        # Strong random session secret
        self.session_secret = os.environ.get(
            'SESSION_SECRET',
            secrets.token_urlsafe(32)  # Random if not configured
        )
        self.session_timeout = 3600  # 1 hour

        # Restrictive CORS
        self.cors_origins = []  # No origins allowed by default

        # Admin disabled by default
        self.admin_enabled = False
        self.admin_path = f"/admin-{secrets.token_urlsafe(8)}"  # Random path


class UserService:
    def create_admin_user(self, username: str, password: str = None):
        """Create admin user with provided or generated password."""
        if password is None:
            # Generate strong random password
            password = secrets.token_urlsafe(24)
            print(f"Generated admin password: {password}")
            print("IMPORTANT: Change this password after first login!")

        # Validate password strength
        if len(password) < 12:
            raise ValueError("Password must be at least 12 characters")

        return self._create_user(username, password, role="admin")

    def _create_user(self, username: str, password: str, role: str = "user"):
        """Create user with secure defaults."""
        return User(
            username=username,
            password_hash=self._hash_password(password),
            role=role,
            must_change_password=True,  # Force password change
            mfa_enabled=False,  # But prompt to enable
            account_locked=False,
            failed_login_attempts=0
        )
// Fixed: Java with secure defaults

public class SecurityConfig {

    private SecurityConfig() {
        // Private constructor - use builder
    }

    public static class Builder {
        private boolean debugMode = false;  // Secure default
        private String encryptionAlgorithm = "AES";
        private int keySize = 256;
        private List<String> allowedOrigins = new ArrayList<>();  // Empty by default
        private boolean allowCredentials = false;
        private int maxRequestsPerMinute = 100;  // Reasonable default
        private int sessionTimeout = 30 * 60;  // 30 minutes
        private boolean cookieSecure = true;  // HTTPS only
        private boolean cookieHttpOnly = true;  // Not accessible to JS

        public Builder withDebugMode(boolean debug) {
            this.debugMode = debug;
            return this;
        }

        public Builder withAllowedOrigins(List<String> origins) {
            // Validate no wildcards with credentials
            if (allowCredentials && origins.contains("*")) {
                throw new IllegalArgumentException(
                    "Cannot allow credentials with wildcard origin");
            }
            this.allowedOrigins = new ArrayList<>(origins);
            return this;
        }

        public SecurityConfig build() {
            return new SecurityConfig(this);
        }
    }
}

// Spring Security with secure defaults
@Configuration
@EnableWebSecurity
public class SecureWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // CSRF enabled (default, but explicit)
            .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

            // Deny by default, allow specific paths
            .and()
            .authorizeRequests()
            .antMatchers("/public/**").permitAll()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()

            // Secure headers
            .and()
            .headers()
            .frameOptions().deny()
            .contentSecurityPolicy("default-src 'self'")

            // Session management
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            .maximumSessions(1);
    }

    // No default users - must be configured
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // Use database or LDAP - no in-memory defaults
        auth.userDetailsService(userDetailsService)
            .passwordEncoder(new BCryptPasswordEncoder());
    }
}
// Fixed: Node.js/Express with secure defaults

const express = require('express');
const session = require('express-session');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const crypto = require('crypto');

const app = express();

// Require SESSION_SECRET environment variable
if (!process.env.SESSION_SECRET) {
    console.error('ERROR: SESSION_SECRET environment variable required');
    process.exit(1);
}

// Security headers
app.use(helmet());

// Rate limiting
app.use(rateLimit({
    windowMs: 15 * 60 * 1000,  // 15 minutes
    max: 100  // Limit each IP
}));

// Secure session configuration
app.use(session({
    secret: process.env.SESSION_SECRET,  // From environment
    resave: false,
    saveUninitialized: false,  // Don't create sessions until needed
    cookie: {
        secure: process.env.NODE_ENV === 'production',  // HTTPS in prod
        httpOnly: true,  // Not accessible to JavaScript
        sameSite: 'strict',  // CSRF protection
        maxAge: 1000 * 60 * 60  // 1 hour
    }
}));

// Restrictive CORS - must be explicitly configured
const cors = require('cors');
const allowedOrigins = process.env.CORS_ORIGINS
    ? process.env.CORS_ORIGINS.split(',')
    : [];

app.use(cors({
    origin: allowedOrigins,
    credentials: true
}));

// No debug endpoints in production
if (process.env.NODE_ENV !== 'production') {
    app.get('/debug', authRequired, adminRequired, (req, res) => {
        // Only show safe debug info
        res.json({
            uptime: process.uptime(),
            memoryUsage: process.memoryUsage()
        });
    });
}

// No default credentials - must be set up
console.log('Admin account must be created via setup script');

CVE Examples

Many CVEs result from insecure defaults:

  • Default credentials: Thousands of CVEs for devices with default admin/admin
  • Debug modes: CVEs from debug features enabled by default in production
  • Weak crypto defaults: CVEs from weak default encryption settings

  • CWE-344: Use of Invariant Value in Dynamically Changing Context (parent)
  • CWE-1419: Incorrect Initialization of Resource (parent)
  • CWE-453: Insecure Default Variable Initialization (child)
  • CWE-1392: Use of Default Credentials (related)

References

  1. MITRE Corporation. "CWE-1188: Initialization of a Resource with an Insecure Default." https://cwe.mitre.org/data/definitions/1188.html
  2. OWASP - Security by Default
  3. NIST - Secure Configuration Guidelines