API Security — Input Validation, CORS, and SQL Injection Prevention
In this tutorial, you'll learn about API Security. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
API security encompasses the practices and tools used to protect REST APIs from attacks including SQL Injection, cross-site scripting, cross-origin abuse, input validation exploits, and unauthorized access through proper request validation and security headers.
What You'll Learn
You will learn to protect APIs against SQL Injection, configure CORS correctly, implement input validation, prevent XSS Attacks, use security headers, and follow OWASP API Security Top 10 recommendations.
Why API Security Matters
APIs are the most attacked surface of modern applications. The OWASP API Security Top 10 lists the most critical risks, from broken authentication to mass assignment. A single API vulnerability can expose millions of user records. In 2025, API attacks accounted for 40 percent of all data breaches. Investing in API security upfront prevents costly incidents.
Real-World Use
DodaTech takes API security seriously across all products. Doda Browser implements strict CORS policies and input validation, DodaZIP uses parameterized queries for all database access, and Durga Antivirus Pro includes API security scanning in its CI/CD pipeline to catch vulnerabilities before deployment.
API Security Learning Path
flowchart LR
A[REST API Design] --> B[Input Validation]
B --> C[SQL Injection Prevention]
C --> D[CORS & Headers]
D --> E[XSS & CSRF Protection]
E --> F[Rate Limiting & Auth]
F --> G[Security Monitoring]
B:::current
classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px
Prerequisites
Understand RESTful Api Design Best Practices, Authentication Patterns JWT OAuth2 API Keys, and HTTP Protocol Basics. Basic security concepts like encryption and hashing are helpful.
Input Validation
Never trust user input. Validate every field on the server side, even if you validate on the client side.
Whitelist Validation
Only accept known-good values:
const Joi = require("joi");
const createUserSchema = Joi.object({
name: Joi.string()
.min(2)
.max(100)
.pattern(/^[a-zA-Z\s'-]+$/)
.required()
.messages({
"string.pattern.base": "Name contains invalid characters"
}),
email: Joi.string()
.email({ tlds: { allow: false } })
.required(),
age: Joi.number()
.integer()
.min(18)
.max(120)
.required(),
role: Joi.string()
.valid("admin", "member", "viewer")
.default("member"),
website: Joi.string()
.uri()
.optional()
});
Python Input Validation with Pydantic
from pydantic import BaseModel, EmailStr, Field, validator
import re
class CreateUserSchema(BaseModel):
name: str = Field(..., min_length=2, max_length=100)
email: EmailStr
age: int = Field(..., ge=18, le=120)
role: str = Field(default="member", pattern="^(admin|member|viewer)$")
@validator("name")
def validate_name(cls, v):
if not re.match(r"^[a-zA-Z\s'-]+$", v):
raise ValueError("Name contains invalid characters")
return v.strip()
SQL Injection Prevention
SQL Injection occurs when user input is concatenated directly into SQL queries.
Vulnerable Code (NEVER do this)
// DANGEROUS: String concatenation
const id = req.params.id;
const result = await db.query(`SELECT * FROM users WHERE id = '${id}'`);
// Attacker: id = "'; DROP TABLE users; --"
Safe Code: Parameterized Queries
// SAFE: Parameterized query with pg library
const result = await db.query(
"SELECT * FROM users WHERE id = $1",
[req.params.id]
);
# SAFE: Parameterized query with psycopg2
cursor.execute(
"SELECT * FROM users WHERE id = %s",
(user_id,)
)
Using an ORM (Safer)
// Sequelize ORM
const user = await User.findByPk(req.params.id);
// Prisma ORM
const user = await prisma.user.findUnique({
where: { id: req.params.id }
});
Common SQL Injection Vectors
| Attack | Malicious Input | Effect |
|---|---|---|
| Tautology | ' OR '1'='1 |
Returns all rows |
| UNION | ' UNION SELECT * FROM passwords-- |
Returns data from other tables |
| Comment injection | admin'-- |
Comments out the REST of query |
| Stacked queries | '; DROP TABLE users; -- |
Executes multiple queries |
CORS (Cross-Origin Resource Sharing)
CORS controls which domains can access your API from a browser.
How CORS Works
sequenceDiagram
Browser->>API: OPTIONS /api/users (Preflight)
API->>Browser: 200 OK (Access-Control-Allow-Origin: *)
Browser->>API: GET /api/users
API->>Browser: 200 OK (Data)
CORS Configuration in Express
const CORS = require("CORS");
// Restrictive: allow only specific origins
app.use(CORS({
origin: [
"HTTPS://dodatech.com",
"HTTPS://app.dodatech.com",
"HTTPS://dashboard.dodatech.com]
],
methods: ["GET", "POST", "PUT", "DELETE"],
allowedHeaders: ["Content-Type", "Authorization"],
exposedHeaders: ["X-RateLimit-Remaining"],
credentials: true, // Allow cookies
maxAge: 86400 // Cache preflight for 24 hours
}));
// NEVER use this in production:
// app.use(CORS({ origin: "*" }));
CORS Configuration in FastAPI
from FastAPI.middleware.CORS import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=[
"HTTPS://dodatech.com",
"HTTPS://app.dodatech.com]
],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Content-Type", "Authorization"],
max_age=86400
)
CORS Headers Explained
| Header | Purpose |
|---|---|
| Access-Control-Allow-Origin | Which origins are allowed |
| Access-Control-Allow-Methods | Which HTTP methods are allowed |
| Access-Control-Allow-Headers | Which headers can be sent |
| Access-Control-Allow-Credentials | Whether cookies are allowed |
| Access-Control-Max-Age | How long to cache preflight |
| Access-Control-Expose-Headers | Which headers the client can read |
Security Headers
const helmet = require("helmet");
app.use(helmet()); // Sets multiple security headers
// Equivalent manual configuration:
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "HTTPS://CDN.dodatech.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
connectSrc: ["'self'", "HTTPS://API.dodatech.com"]
}
},
hsts: {
maxAge: 31536000, // 1 year
includeSubDomains: true,
preload: true
}
}));
| Header | Purpose |
|---|---|
| Content-Security-Policy | Prevents XSS by controlling allowed content sources |
| Strict-Transport-Security | Enforces HTTPS connections |
| X-Content-Type-Options | Prevents MIME type sniffing |
| X-Frame-Options | Prevents clickjacking |
| X-XSS-Protection | Enables browser XSS filter |
Mass Assignment Protection
Mass assignment occurs when an attacker sends extra fields that get written to the database.
Vulnerable Code
// DANGEROUS: Direct assignment from request body
app.put("/API/users/:id", async (req, res) => {
const user = await User.findByPk(req.params.id);
await user.update(req.body); // Attacker can set { role: "admin" }
});
Safe Code: Whitelist Fields
// SAFE: Only update allowed fields
const allowedFields = ["name", "email"];
const updateData = {};
for (const field of allowedFields) {
if (req.body[field] !== undefined) {
updateData[field] = req.body[field];
}
}
await user.update(updateData);
XSS Prevention
Cross-Site Scripting attacks inject malicious scripts into API responses.
// Escape HTML in responses
const escapeHtml = (text) => {
const map = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'"
};
return text.replace(/[&<>"']/g, (m) => map[m]);
};
app.get("/API/users/:id", async (req, res) => {
const user = await User.findByPk(req.params.id);
// Always escape user-generated content in responses
user.bio = escapeHtml(user.bio);
res.JSON(user);
});
Security Checklist
- All input validated server-side with whitelist approach
- Parameterized queries for all database operations
- CORS configured with specific allowed origins (not wildcard)
- Security headers set via helmet or similar middleware
- Rate Limiting on all endpoints
- Authentication required for sensitive endpoints
- Mass assignment prevented with field whitelists
- Output escaped to prevent XSS
- HTTPS enforced (HSTS header)
- File upload validation (type, size, content)
- API keys stored as hashes, not plaintext
- Error messages do not leak internal details
Common Errors
Using wildcard CORS in production — Setting
Access-Control-Allow-Origin: *allows any website to make requests to your API. Always restrict to specific origins in production.Concatenating SQL queries — Building SQL by string concatenation with user input. Always use parameterized queries. Even ORMs can be vulnerable if you use raw queries.
No input length limits — Accepting arbitrarily long input strings. Attackers can send multi-megabyte payloads to exhaust server memory. Set
maxLengthon all string fields.Returning internal error details — Sending Stack traces and database error messages to clients. Use a global error handler that returns sanitized messages.
Trusting request headers for security decisions — Using
X-Forwarded-Forwithout validation for Rate Limiting or access control. These headers can be spoofed. Validate them against trusted Proxy lists.Not validating content type — Accepting any Content-Type including XML that may enable XXE Attacks. Restrict Content-Type to
application/jsonand validate the parser.Missing Rate Limiting on auth endpoints — Allowing unlimited login attempts enables brute force attacks. Always rate limit auth endpoints to 5-10 attempts per minute per IP.
Practice Questions
- What is SQL Injection and how do you prevent it?
- How does CORS protect against cross-origin attacks?
- What is mass assignment and how do you prevent it?
- What security headers should every API include?
- Why is whitelist validation better than blacklist validation?
Challenge
Audit and secure an existing REST API. Review the codebase for: all SQL queries (ensure they use parameterized queries), CORS configuration (restrict to specific origins), input validation (add Joi or Pydantic schemas for all endpoints), security headers (add helmet middleware), Rate Limiting (implement on all endpoints), error handling (sanitize error messages), and authentication (verify JWT validation is correct). Write a security report documenting each vulnerability found and the fix applied.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro