OWASP
OWASP
Proactive Controls
Secure Development
Input Validation
+2 more

OWASP Proactive Controls 2026: 10 Security Practices Every Developer Must Know

SCR Security Research Team
February 8, 2026
19 min read
Share

What Are the OWASP Proactive Controls?

While the OWASP Top 10 lists what can go wrong, the OWASP Proactive Controls (OPC) tell developers what to do right. They are the 10 most critical security techniques that every developer should build into their applications from the start.

Philosophy: "It is far more cost-effective to design security into applications from the beginning than to fix vulnerabilities after deployment." — OWASP Proactive Controls documentation.

Cost of fixing vulnerabilities by phase:

PhaseCost MultiplierExample
Design1x (baseline)Threat modeling catches missing auth
Development6.5xCode review finds SQL injection
Testing15xPen test discovers IDOR
Production100xData breach response

Source: NIST, IBM Security Cost of a Data Breach Report 2025


C1: Define Security Requirements

Before writing a single line of code, define what "secure" means for your application.

Security Requirements by Application Type

RequirementWeb AppAPIMobileAI/ML
Authentication methodSSO/MFAOAuth 2.0Biometric + PINAPI key + token
Session managementServer-side, 15min timeoutStateless JWT, 5min expSecure enclave storagePer-request auth
Input validationAll user inputs, CSRF tokensSchema validation (OpenAPI)All inputs + certificate pinningPrompt validation + injection detection
Data encryptionTLS 1.3 + AES-256 at restmTLS + field-level encryptionApp-level encryptionTraining data encryption
Logging levelActions + errorsFull request/responseCrash/security eventsInference requests + outputs

Practical Exercise: User Story Security Requirements

User Story: "As a user, I can reset my password via email"

Security Requirements:
1. Reset tokens must be cryptographically random (min 128 bits)
2. Tokens expire after 15 minutes
3. Tokens are single-use (invalidated after use)
4. Rate limit: max 3 reset requests per hour per email
5. Don't reveal whether email exists ("If this email is registered...")
6. Log all reset attempts for audit
7. Notify user via email of successful password change
8. New password must meet complexity requirements

C2: Leverage Security Frameworks and Libraries

Don't build security primitives from scratch. Use battle-tested, actively maintained libraries.

FunctionNode.js/TypeScriptPythonJava
AuthenticationNextAuth.js, PassportDjango Auth, AuthlibSpring Security
Password hashingbcrypt, argon2passlib (argon2)BCryptPasswordEncoder
Input validationzod, joi, express-validatorpydantic, marshmallowBean Validation (JSR 380)
CSRF protectioncsrf (npm), Next.js built-inDjango CSRF middlewareSpring CSRF
SQL injection preventionPrisma, Drizzle (parameterized)SQLAlchemy (parameterized)JPA/Hibernate
XSS preventionDOMPurify, React (auto-escapes)bleach, MarkupSafeOWASP Java Encoder
CryptographyNode.js crypto (built-in)cryptography (pyca)Tink (by Google)

C3: Secure Database Access

Every database query must be parameterized. This is non-negotiable.

// VULNERABLE — String concatenation = SQL injection
const user = await db.query(
  `SELECT * FROM users WHERE email = '${email}' AND password = '${password}'`
);

// SECURE — Parameterized query (Prisma ORM)
const user = await prisma.user.findUnique({
  where: { email: email },
  select: { id: true, email: true, hashedPassword: true },
});
// Then verify password separately with bcrypt.compare()

Database Security Principles

  1. Use an ORM with parameterized queries (Prisma, Drizzle, SQLAlchemy, Hibernate)
  2. Principle of least privilege — Application DB user should only have SELECT/INSERT/UPDATE on required tables
  3. No database admin credentials in application code — Ever
  4. Enable query logging in development — Catch raw query construction early
  5. Encrypt sensitive columns — PII, financial data, health records

C4: Encode and Escape Data

All data that crosses a trust boundary must be encoded for the output context.

ContextEncodingExample
HTML bodyHTML entity encoding<script>&lt;script&gt;
HTML attributeAttribute encoding" onmouseover="&quot; onmouseover=&quot;
JavaScriptJavaScript encodingUnicode escape sequences
URLURL encodingSpaces → %20
CSSCSS encodingHex encoding
SQLParameterized queriesNot string encoding — use parameters

React & Next.js: React automatically escapes JSX expressions, making XSS via {variable} rare. The danger is dangerouslySetInnerHTML — avoid it, or use DOMPurify.


C5: Validate All Inputs

Validate on the server. Client-side validation is a UX feature, not a security control.

import { z } from "zod";

// Define strict input schema
const ContactSchema = z.object({
  name: z.string()
    .min(2, "Name must be at least 2 characters")
    .max(100, "Name too long")
    .regex(/^[a-zA-Z\s'-]+$/, "Invalid characters in name"),

  email: z.string()
    .email("Invalid email address")
    .max(254, "Email too long"),

  message: z.string()
    .min(10, "Message too short")
    .max(5000, "Message too long")
    .transform(msg => msg.trim()),

  phone: z.string()
    .regex(/^\+?[1-9]\d{6,14}$/, "Invalid phone number")
    .optional(),
});

// Use in API route
export async function POST(req: Request) {
  const body = await req.json();
  const result = ContactSchema.safeParse(body);

  if (!result.success) {
    return Response.json({ error: result.error.flatten() }, { status: 400 });
  }

  // result.data is now validated and typed
  await saveContact(result.data);
}

C6: Implement Digital Identity

Modern Authentication Checklist

  • Use established identity providers (NextAuth.js, Auth0, Firebase Auth, Keycloak)
  • Implement MFA for all user accounts (TOTP, WebAuthn, passkeys)
  • Hash passwords with Argon2id or bcrypt (cost factor ≥ 12)
  • Use secure session management (HttpOnly, Secure, SameSite cookies)
  • Implement account lockout after failed attempts (5 failures → 15min lockout)
  • Provide password strength feedback in real-time

C7: Enforce Access Controls

Deny by default. Every endpoint must verify both authentication and authorization.


C8: Protect Data Everywhere

  • In transit: TLS 1.3 (minimum TLS 1.2). No mixed content.
  • At rest: AES-256 for databases, encrypted volumes for storage
  • In use: Consider confidential computing for sensitive workloads
  • Key management: Use cloud KMS (AWS KMS, Azure Key Vault, GCP Cloud KMS) — never store keys in code

C9: Implement Security Logging and Monitoring

Log these events (at minimum):

  • Authentication successes and failures
  • Authorization failures
  • Input validation failures
  • Application errors
  • Admin and privileged actions
  • Data access patterns

C10: Handle All Errors and Exceptions

  • Never expose stack traces in production
  • Log detailed errors internally, return generic messages externally
  • Use global error handlers to catch unhandled exceptions
  • Return consistent error response formats

Further Reading

Advertisement