debug-mode-production-anti-pattern

Security anti-pattern for debug mode in production (CWE-215). Use when generating or reviewing code that configures application settings, deployment configurations, or error handling. Detects hardcoded debug flags and development-only features in production.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "debug-mode-production-anti-pattern" with this command: npx skills add igbuend/grimbard/igbuend-grimbard-debug-mode-production-anti-pattern

Debug Mode in Production Anti-Pattern

Severity: High

Summary

Debug mode in production exposes sensitive system information and creates backdoors. Occurs when development settings remain enabled in deployment. Common in AI-generated code that hardcodes debug flags or fails to differentiate environments.

The Anti-Pattern

This anti-pattern manifests in two primary ways:

  1. Hardcoded Debug Flags: Global flag DEBUG = True never changes, so the application runs in debug mode in all environments.
  2. Unprotected Debug Endpoints: Debug routes (/debug/env, /_debug/sql) included in production builds provide attack vectors.

BAD Code Example

# VULNERABLE: Hardcoded debug flag and unprotected debug routes
import os
from flask import Flask, jsonify

app = Flask(__name__)
app.config['DEBUG'] = True # Hardcoded debug mode

@app.route("/")
def index():
    return "Welcome!"

# This debug route exposes all environment variables, including potential secrets.
# It should never be present in a production environment.
@app.route("/debug/env")
def debug_env():
    if app.config['DEBUG']:
        return jsonify(os.environ.copy())
    return "Not in debug mode."

if __name__ == "__main__":
    app.run()

GOOD Code Example

# SECURE: Environment-based configuration and conditional routes
import os
from flask import Flask, jsonify

app = Flask(__name__)

# Load configuration from the environment. Default to 'production'.
APP_ENV = os.environ.get('APP_ENV', 'production')
app.config['DEBUG'] = APP_ENV == 'development'

@app.route("/")
def index():
    return "Welcome!"

# This debug route is now conditionally registered and will only exist
# if the application is explicitly run in a development environment.
if app.config['DEBUG']:
    @app.route("/debug/env")
    def debug_env():
        return jsonify(os.environ.copy())

# It's also a good practice to add a startup check to prevent accidental
# deployment of debug mode to production.
if APP_ENV == 'production' and app.config['DEBUG']:
    raise ValueError("FATAL: Debug mode is enabled in a production environment. Aborting.")

if __name__ == "__main__":
    app.run()

JavaScript/Node.js Examples

BAD:

// VULNERABLE: Hardcoded debug flag in Express
const express = require('express');
const app = express();

// Hardcoded debug mode
const DEBUG = true;

app.get('/', (req, res) => {
    res.send('Welcome!');
});

// Debug route exposes environment variables
app.get('/debug/env', (req, res) => {
    if (DEBUG) {
        res.json(process.env);
    } else {
        res.send('Not in debug mode.');
    }
});

app.listen(3000);

GOOD:

// SECURE: Environment-based configuration
const express = require('express');
const app = express();

// Load from environment, default to production
const APP_ENV = process.env.APP_ENV || 'production';
const DEBUG = APP_ENV === 'development';

app.get('/', (req, res) => {
    res.send('Welcome!');
});

// Conditionally register debug route
if (DEBUG) {
    app.get('/debug/env', (req, res) => {
        res.json(process.env);
    });
}

// Startup check prevents production debug mode
if (APP_ENV === 'production' && DEBUG) {
    throw new Error('FATAL: Debug mode enabled in production. Aborting.');
}

app.listen(3000);

Java/Spring Boot Examples

BAD:

// VULNERABLE: Hardcoded debug in application.properties
// application.properties:
// debug=true
// logging.level.root=DEBUG

@RestController
public class DebugController {
    @Value("${debug}")
    private boolean debug;

    @GetMapping("/debug/env")
    public Map<String, String> debugEnv() {
        if (debug) {
            return System.getenv();
        }
        return Map.of("error", "Not in debug mode");
    }
}

GOOD:

// SECURE: Profile-based configuration
// application-dev.properties:
// debug=true
// application-prod.properties:
// debug=false

@RestController
@Profile("dev")  // Only register in development profile
public class DebugController {
    @GetMapping("/debug/env")
    public Map<String, String> debugEnv() {
        return System.getenv();
    }
}

// Application startup check
@Component
public class EnvironmentValidator implements ApplicationRunner {
    @Value("${spring.profiles.active:prod}")
    private String activeProfile;

    @Value("${debug:false}")
    private boolean debug;

    @Override
    public void run(ApplicationArguments args) {
        if ("prod".equals(activeProfile) && debug) {
            throw new IllegalStateException(
                "FATAL: Debug mode enabled in production. Aborting."
            );
        }
    }
}

Detection

Python/Flask/Django:

  • DEBUG = True in source code
  • debug=True in Flask config
  • DEBUG = True in Django settings.py
  • Debug routes: @app.route("/debug/

JavaScript/Node.js/Express:

  • const DEBUG = true in source code
  • process.env.NODE_ENV !== 'production' checks missing
  • Debug middleware always enabled
  • Routes: app.get('/debug/

Java/Spring Boot:

  • debug=true in application.properties
  • logging.level.root=DEBUG in production
  • Debug endpoints without @Profile("dev")
  • spring.devtools.restart.enabled=true in prod

PHP:

  • error_reporting(E_ALL) in production
  • display_errors = On in php.ini
  • APP_DEBUG=true in .env

Configuration Files:

  • .env files with DEBUG=true
  • YAML configs with debug: true
  • JSON configs with "debug": true

Search Patterns:

  • Grep: DEBUG.*=.*[Tt]rue|debug.*:.*true|\/debug\/|process\.env\.NODE_ENV
  • Development dependencies in production builds
  • Stack traces exposed in error responses
  • Verbose error messages with file paths

Prevention

  • Use environment variables to control debug mode and other environment-specific settings.
  • Never hardcode DEBUG = True.
  • Conditionally register debug routes so they are not included in production builds.
  • Implement a startup check in the application that aborts if it detects debug mode is enabled in a production environment.
  • Use separate configuration files for each environment (development, staging, production) to avoid overlap.
  • Review your CI/CD pipeline to ensure that the correct environment variables are being injected and that development artifacts are excluded from the final build.

Testing for Debug Mode

Manual Testing:

  1. Check environment variables: echo $DEBUG, echo $APP_ENV
  2. Access debug endpoints: /debug, /_debug, /debug/env
  3. Trigger errors and check for stack traces
  4. Review HTTP headers for debug information (X-Debug, Server versions)

Automated Testing:

  • Static Analysis: Semgrep, Bandit (Python), ESLint, SonarQube
  • Configuration Scanning: Detect hardcoded DEBUG = True in code
  • Runtime Testing: Burp Suite, OWASP ZAP to find debug endpoints
  • CI/CD Checks: Fail builds with debug flags enabled

Example Test:

# Test that debug mode is disabled in production
def test_debug_disabled_in_production():
    import os
    os.environ['APP_ENV'] = 'production'

    # This should raise ValueError
    with pytest.raises(ValueError, match="Debug mode is enabled in a production environment"):
        import app  # Import triggers startup check

CI/CD Pipeline Check:

# .github/workflows/deploy.yml
- name: Verify No Debug Mode
  run: |
    if grep -r "DEBUG.*=.*True" app/; then
      echo "ERROR: Hardcoded DEBUG=True found"
      exit 1
    fi

    if [ "$APP_ENV" = "production" ] && [ "$DEBUG" = "true" ]; then
      echo "ERROR: Debug mode enabled for production deployment"
      exit 1
    fi

Remediation Steps

  1. Identify debug configurations - Use detection patterns above
  2. Check current environment - Determine if debug mode is active
  3. Create environment-based config - Use environment variables
  4. Remove hardcoded flags - Replace DEBUG = True with env lookup
  5. Conditional debug routes - Register only in development
  6. Add startup checks - Abort if debug mode in production
  7. Test the fix - Verify debug disabled in production config
  8. Update CI/CD - Add validation to deployment pipeline

Related Security Patterns & Anti-Patterns

References

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

missing-security-headers-anti-pattern

No summary provided by upstream source.

Repository SourceNeeds Review
Security

content-security-policy

No summary provided by upstream source.

Repository SourceNeeds Review
Security

oauth-security-anti-pattern

No summary provided by upstream source.

Repository SourceNeeds Review