← All posts
IDORsecurityvulnerabilityfixweb app securityaccess control

IDOR Vulnerability Fix: What It Is and How to Fix It

O

OverMCP Team

TL;DR: Insecure Direct Object Reference (IDOR) is a vulnerability where an attacker can access or modify resources (like user data, orders, or documents) by simply changing an ID parameter in the URL or request. To fix it, implement proper access control checks on every server-side endpoint that accesses a resource by ID—never trust user-supplied identifiers without verifying ownership.

What Is an IDOR Vulnerability?

IDOR stands for Insecure Direct Object Reference. It occurs when an application exposes a reference to an internal object (like a database ID, filename, or key) and fails to verify that the user is authorized to access that specific object. For example, if your app uses /api/order/123 to fetch order details, an attacker can change 123 to 124 and view another user's order if no access control is in place.

IDOR is one of the most common vulnerabilities in vibe-coded apps because AI tools often generate CRUD endpoints that trust the user-supplied identifier without checking permissions. It falls under the OWASP Top 10 category "Broken Access Control."

How IDOR Exploits Work (Real Examples)

Example 1: Numeric ID in URL

Imagine a note-taking app with this endpoint:

GET /note/42

If the server returns note 42 without checking if the current user owns it, an attacker can iterate through IDs to read every note:

GET /note/1
GET /note/2
...
GET /note/1000

Example 2: UUID or Hash in URL

Even if you use UUIDs, IDOR can exist if the endpoint doesn't verify ownership. For instance:

GET /api/document/abc-123-def

If the attacker can guess or obtain another user's document UUID (e.g., via a shared link or leaked in client-side code), they can access it.

Example 3: ID in Request Body or Query Parameter

IDOR isn't limited to URLs. Consider a POST endpoint to update a user profile:

POST /api/user/update
{
  "user_id": 456,
  "email": "hacker@evil.com"
}

If the server uses user_id from the request body instead of the authenticated user's ID, an attacker can change any user's email.

How to Fix IDOR Vulnerabilities (Step-by-Step)

Step 1: Authenticate Every Request

Ensure every endpoint that accesses a resource requires authentication. Use session tokens, JWTs, or API keys to identify the user.

Step 2: Implement Authorization Checks

For every endpoint that uses an ID to fetch or modify a resource, verify that the authenticated user owns or has permission to access that resource.

#### Fix for Example 1 (Numeric ID)

Vulnerable code (Node.js/Express):

app.get('/note/:id', async (req, res) => {
  const note = await db.findNoteById(req.params.id);
  res.json(note);
});

Fixed code:

app.get('/note/:id', async (req, res) => {
  const note = await db.findNoteById(req.params.id);
  if (!note) return res.status(404).json({ error: 'Note not found' });
  if (note.userId !== req.user.id) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  res.json(note);
});

#### Fix for Example 2 (UUID)

Same principle—check ownership:

app.get('/document/:uuid', async (req, res) => {
  const doc = await db.findDocumentByUuid(req.params.uuid);
  if (!doc) return res.status(404).json({ error: 'Document not found' });
  if (doc.ownerId !== req.user.id) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  res.json(doc);
});

#### Fix for Example 3 (ID in Body)

Never trust the client-provided user ID. Use the authenticated user's ID from the session/token:

app.post('/user/update', async (req, res) => {
  const userId = req.user.id; // from auth middleware
  const { email } = req.body;
  // Update user where id = userId
  await db.updateUser(userId, { email });
  res.json({ success: true });
});

Step 3: Use Indirect References (Optional)

Instead of exposing internal database IDs, use indirect references that are unique per user and hard to guess. For example, assign each user a random token for each resource:

GET /order/token-xyz789

But this is a band-aid—you still need authorization checks.

Step 4: Test for IDOR

Manual testing:

  • Log in as user A, get a resource ID.
  • Log in as user B, try to access that resource using the same ID.
  • If you succeed, you have an IDOR vulnerability.
  • Automated scanning: Use tools like Burp Suite, OWASP ZAP, or OverMCP's security scanner to detect IDOR in your app.

    IDOR in Vibe-Coded Apps: Why It's Common

    AI coding tools like Cursor, Bolt.new, and Lovable generate code quickly, but they often omit access control logic. They assume the developer will add it later—or worse, they generate endpoints that trust user input implicitly. If you're building an MVP with AI, you must manually audit every endpoint that takes an ID parameter.

    Preventing IDOR at the Architecture Level

  • Use a consistent authorization layer: Implement a middleware or decorator that checks ownership for every resource access.
  • Prefer user-scoped queries: Instead of fetching a note by ID and then checking ownership, query directly with both ID and user ID:
  • const note = await db.findNote({ id: req.params.id, userId: req.user.id });
    if (!note) return res.status(404).json({ error: 'Note not found' });

    This eliminates the risk of forgetting the ownership check.

  • Use parameterized queries: Avoid SQL injection alongside IDOR (defense in depth).
  • Tools to Help You Find IDOR

  • OverMCP: Scans your vibe-coded app for IDOR and other vulnerabilities automatically. It integrates with your CI/CD pipeline and alerts you before deployment.
  • Burp Suite: Intercept and replay requests to test IDOR manually.
  • OWASP ZAP: Free automated scanner that can detect some IDOR patterns.
  • FAQ

    What is the difference between IDOR and broken access control?

    IDOR is a specific type of broken access control. Broken access control is a broader category that includes any failure to enforce proper permissions (e.g., privilege escalation, missing function-level access control). IDOR specifically involves direct access to objects via user-supplied identifiers.

    Can IDOR exist if I use UUIDs instead of sequential IDs?

    Yes. UUIDs make guessing harder but do not prevent IDOR. If an attacker obtains a valid UUID (e.g., via a shared link, data breach, or client-side leak), they can still access the resource if no ownership check is performed.

    How do I test my app for IDOR vulnerabilities?

    Log in as two different users. Take a resource ID from user A's session (e.g., from the URL or API response) and try to access that resource while logged in as user B. If the request succeeds, you have an IDOR vulnerability. Use automated scanners like OverMCP to find them across your entire app.

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free