← Back to Blog

9 API Security Mistakes That Get You Hacked (with Fixes)

APIs are the backbone of modern applications, and they are also the most targeted attack surface. The OWASP API Security Top 10 documents the most critical API vulnerabilities, yet developers continue to make the same mistakes. This guide walks through each common mistake with real code examples showing both the vulnerable and secure patterns.

Mistake 1: Broken Object Level Authorization (BOLA)

BOLA is the number one API vulnerability according to OWASP. It occurs when an API does not verify that the authenticated user has permission to access the specific resource they are requesting. An attacker simply changes the ID in the request to access another user's data.

Vulnerable Code

// Express.js - VULNERABLE: No ownership check
app.get('/api/users/:userId/orders', authenticate, (req, res) => {
  const orders = db.orders.findByUserId(req.params.userId);
  res.json(orders);
});

Secure Code

// Express.js - SECURE: Verify resource ownership
app.get('/api/users/:userId/orders', authenticate, (req, res) => {
  if (req.user.id !== req.params.userId && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  const orders = db.orders.findByUserId(req.params.userId);
  res.json(orders);
});

BOLA is responsible for some of the largest API breaches in recent years. In 2023, a major rideshare company exposed 57 million user records through a BOLA vulnerability that allowed any authenticated user to access any other user's profile by changing the user ID parameter.

Mistake 2: Broken Authentication

Weak authentication mechanisms allow attackers to impersonate legitimate users. Common failures include:

  • No rate limiting on login endpoints enabling brute force attacks
  • JWT tokens that never expire or have excessively long lifetimes
  • Storing passwords in plain text or using weak hashing (MD5, SHA1)
  • Not validating JWT signatures or accepting "alg: none"
  • API keys in URLs that get logged in server access logs
// SECURE: JWT with proper expiration and refresh
const accessToken = jwt.sign(
  { userId: user.id, role: user.role },
  process.env.JWT_SECRET,
  { expiresIn: '15m', algorithm: 'HS256' }
);

const refreshToken = jwt.sign(
  { userId: user.id, tokenVersion: user.tokenVersion },
  process.env.REFRESH_SECRET,
  { expiresIn: '7d', algorithm: 'HS256' }
);

Use our JWT Generator to test token creation and the JWT Decoder to inspect existing tokens.

Mistake 3: Excessive Data Exposure

APIs often return entire database objects when the client only needs a few fields. This leaks sensitive data including internal IDs, timestamps, admin flags, and even password hashes.

// VULNERABLE: Returns everything from the database
app.get('/api/users/:id', authenticate, (req, res) => {
  const user = db.users.findById(req.params.id);
  res.json(user); // Includes passwordHash, ssn, internalNotes
});

// SECURE: Return only what the client needs
app.get('/api/users/:id', authenticate, (req, res) => {
  const user = db.users.findById(req.params.id);
  res.json({
    id: user.id,
    name: user.name,
    email: user.email,
    createdAt: user.createdAt
  });
});

Mistake 4: Missing Rate Limiting

Without rate limiting, attackers can brute force credentials, scrape data, or overwhelm your API with requests. Every API endpoint should have rate limiting appropriate to its function.

// Express.js with express-rate-limit
const rateLimit = require('express-rate-limit');

// Strict limit for authentication endpoints
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts per window
  message: { error: 'Too many login attempts, try again later' }
});
app.post('/api/auth/login', authLimiter, loginHandler);

// General API limit
const apiLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 100 // 100 requests per minute
});
app.use('/api/', apiLimiter);

Mistake 5: CORS Misconfiguration

Overly permissive CORS policies allow malicious websites to make authenticated requests to your API on behalf of your users. The most dangerous pattern is reflecting the Origin header back without validation.

// VULNERABLE: Reflects any origin
app.use(cors({ origin: true, credentials: true }));

// SECURE: Whitelist specific origins
const allowedOrigins = ['https://app.example.com', 'https://admin.example.com'];
app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true
}));

Read our detailed guide on CORS misconfiguration security risks and use the CSP Builder to generate proper Content Security Policy headers.

Check Your API's Security Surface

Exposed endpoints, missing headers, and server information leaks are the first things attackers look for. Scan your domain with SecureBin Exposure Checker.

Scan Your Domain Free

Mistake 6: No Input Validation

Every API input must be validated for type, length, format, and range. Without validation, your API is vulnerable to SQL injection, NoSQL injection, command injection, and data corruption.

// SECURE: Validate all inputs with a schema
const Joi = require('joi');

const createUserSchema = Joi.object({
  name: Joi.string().min(1).max(100).required(),
  email: Joi.string().email().required(),
  age: Joi.number().integer().min(13).max(150),
  role: Joi.string().valid('user', 'admin').default('user')
});

app.post('/api/users', authenticate, (req, res) => {
  const { error, value } = createUserSchema.validate(req.body);
  if (error) return res.status(400).json({ error: error.details[0].message });
  // Proceed with validated data
});

Mistake 7: Verbose Error Messages

Detailed error messages in production reveal internal architecture, database schema, file paths, and technology stack to attackers. Always return generic error messages to clients and log detailed errors internally.

// VULNERABLE: Leaks internal details
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message, stack: err.stack });
});

// SECURE: Generic client response, detailed internal log
app.use((err, req, res, next) => {
  logger.error({ err, requestId: req.id, path: req.path });
  res.status(500).json({ error: 'Internal server error', requestId: req.id });
});

Mistake 8: No API Versioning

Without versioning, you cannot deprecate insecure endpoints without breaking existing clients. Use URL path versioning (/api/v1/, /api/v2/) and maintain a deprecation schedule that gives clients time to migrate before insecure versions are removed.

Frequently Asked Questions

What is the most dangerous API vulnerability?

BOLA (Broken Object Level Authorization) is the most exploited API vulnerability according to OWASP. It is easy to discover, easy to exploit, and can expose all user data in a system. Unlike XSS or CSRF which require user interaction, BOLA attacks are fully automated and can extract data at scale. Every API endpoint that accepts a resource ID must verify that the authenticated user has permission to access that specific resource.

Should I use API keys or OAuth for authentication?

It depends on the use case. API keys are appropriate for server-to-server communication where the key is stored securely on the backend. For user-facing applications, use OAuth 2.0 with PKCE for authorization and short-lived JWT access tokens for authentication. Never use API keys in client-side code (mobile apps, SPAs) because they can be extracted. See our API Security Best Practices guide for detailed implementation.

How do I test my API for security vulnerabilities?

Start with automated tools: use OWASP ZAP for dynamic testing, Postman for manual endpoint testing, and the SecureBin Exposure Checker for surface-level checks. Then perform manual testing: try accessing other users' resources (BOLA), send malformed inputs, test with expired tokens, and verify rate limiting works. For production APIs, consider annual penetration testing by a qualified firm. See our guide on scanning for vulnerabilities with free tools.

Find Exposed API Endpoints

Misconfigured APIs often leak information through headers, error pages, and debug endpoints. Run a free scan to check your domain.

Check Your Domain Free

The Bottom Line

API security is not about adding a single layer of protection. It requires defense in depth: proper authentication, authorization on every endpoint, input validation, rate limiting, correct CORS configuration, and minimal data exposure. The OWASP API Security Top 10 provides a roadmap, but the real work is in consistent implementation and testing. Start by auditing your most critical endpoints against the mistakes listed above, fix what you find, and build security testing into your CI/CD pipeline.

Related reading: API Security Best Practices 2026, CORS Misconfiguration Risks, How Hackers Find Exposed API Keys, Check if API Key is Exposed.