# Secure Defaults ## Rule Fail closed. Deny by default. Make the secure path the easy path. **Source:** [OWASP Secure Design Principles](https://wiki.owasp.org/index.php/Security_by_Design_Principles) ## Fail Closed ### Correct Pattern ```python def check_access(user_id: str, resource_id: str) -> bool: """Default deny — return False on any error.""" try: permissions = get_permissions(user_id, resource_id) return "read" in permissions except Exception: # Log the error for debugging logging.exception("Permission check failed") # But deny access — fail closed return False def process_request(request): """Handle errors by denying, not allowing.""" try: validate_request(request) return handle_request(request) except ValidationError as e: return {"error": str(e)}, 400 except Exception: # Unknown error — don't leak info, don't allow access logging.exception("Unexpected error") return {"error": "Internal error"}, 500 ``` ### Incorrect Pattern ```python # Wrong: fail open def check_access(user_id, resource_id): try: return has_permission(user_id, resource_id) except Exception: return True # "Let them in if something breaks" # Wrong: exception = success try: verify_signature(token) except: pass # Signature verification bypassed! ``` ## Deny by Default ```python # Correct: explicit allowlist ALLOWED_ORIGINS = {"https://app.example.com", "https://admin.example.com"} def check_cors(origin: str) -> bool: return origin in ALLOWED_ORIGINS # Wrong: blocklist approach BLOCKED_ORIGINS = {"http://evil.com"} def check_cors(origin: str) -> bool: return origin not in BLOCKED_ORIGINS # New attacks bypass this ``` ## Secure Configuration ```python # Correct: secure defaults, explicit opt-out class SecurityConfig: https_only: bool = True csrf_protection: bool = True content_security_policy: str = "default-src 'self'" cookie_secure: bool = True cookie_httponly: bool = True cookie_samesite: str = "Strict" # Wrong: insecure defaults class Config: debug: bool = True # Should be False verify_ssl: bool = False # Should be True allow_all_origins: bool = True # Should be False ``` ## Least Privilege ```python # Correct: minimal permissions def create_db_connection(): return connect( user="app_readonly", # Not root database="app_db", # Only needed permissions ) # Service accounts should have minimal scope SERVICE_ACCOUNT_PERMISSIONS = [ "storage.objects.get", "storage.objects.list", # NOT: "storage.admin" ] ``` ## Defense in Depth ```python class SecureEndpoint: """Multiple layers of security.""" def handle(self, request): # Layer 1: Rate limiting if not self.rate_limiter.allow(request.ip): raise TooManyRequests() # Layer 2: Authentication user = self.authenticate(request) if not user: raise Unauthorized() # Layer 3: Authorization if not self.authorize(user, request.resource): raise Forbidden() # Layer 4: Input validation data = self.validate(request.data) # Layer 5: Business logic with validated data return self.process(user, data) ``` ## Edge Cases - Feature flags that disable security controls - Debug endpoints left enabled in production - Default passwords in documentation - Verbose error messages in production - Commented-out security checks