Insecure direct object reference (IDOR)

    What is an insecure direct object reference (IDOR)?

    SHORT ANSWER

    An insecure direct object reference (IDOR) happens when your app uses an ID, like a number in a web address, to find a record, and never checks that the person asking is allowed to see it. Change /orders/101 to /orders/102 and you're reading someone else's order.

    Also called: IDOR

    ON THIS PAGE

    What it means

    Many apps number things in order: orders, users, invoices, files. If the server returns whatever record matches the number, anyone can walk through them one at a time. A bot can read thousands in a few minutes.

    IDOR is one specific kind of broken access control. Random IDs make guessing harder, but only a proper owner check on the server really fixes it.

    Why it matters for vibe-coded apps

    AI-generated routes often look up a record by ID and return it, because that's the shortest code that works. The missing owner check is invisible until someone tries a different number.

    IF THIS IS WRONG IN YOUR APP
    • Private records, such as orders, messages and documents, can be downloaded in bulk.
    • The app works perfectly for normal users, so nothing looks wrong.
    • Personal data exposed this way can create legal obligations for you.

    Example

    A route that returns an order by its number.

    ✕ RISKYReturns any order whose number you ask for
    app.get("/orders/:id", requireLogin, async (req, res) => {
      res.json(await db.orders.findById(req.params.id));
    });
    ✓ SAFEROnly returns the logged-in user's own order
    app.get("/orders/:id", requireLogin, async (req, res) => {
      const order = await db.orders.findOne({ id: req.params.id, userId: req.user.id });
      if (!order) return res.status(404).end();
      res.json(order);
    });

    Use random IDs (UUIDs) as well, so numbers can't be guessed, but never treat that as the only protection.

    How to check if your app has this problem

    1. 1Log in, open one of your own records, and change the number or ID in the web address.
    2. 2Try the same address while logged out, and while logged in as a different user.

    The quicker way: LetMeCheck tests for this automatically, from the outside, the way an attacker would.

    Run a free scan →

    How to fix it

    1. 1Add an owner check to every lookup by ID.
    2. 2Return 404 (not 403) for records that aren't theirs, so IDs can't be confirmed.
    3. 3Switch to random UUIDs for new records.
    4. 4Turn on row level security as a second layer.
    FIX PROMPT · PASTE INTO YOUR AI TOOL

    Find every route in my app that loads a record using an ID from the URL or request body. Update each so it also filters by the logged-in user's ID (or checks their role), and returns 404 when the record isn't theirs.

    Check if your app has this problem

    Paste your website and we'll check for insecure direct object reference (IDOR) issues and other common issues in AI-built apps. Free, about a minute, and nothing on your site is changed.

    Last updated