用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/Dev-Toolbelt/dev-team-agents --skill idor命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | idor |
| description | IDOR — detection, authorization enforcement, ID strategy. |
IDOR occurs when an application uses user-controlled input to access objects directly without verifying the requesting user has permission to access that specific object.
# Attacker changes 42 → 43 and gets another user's order
GET /api/orders/43
Authorization: Bearer <attacker-token>
The endpoint fetches Order::find(43) without checking order.user_id === currentUser.id.
IDOR is not just IDs. Any reference to an object that can be guessed or enumerated is vulnerable: filenames in URLs, email addresses as keys, UUIDs if predictable or leaked.
Flag these patterns in code review:
// BAD — no ownership check
$order = Order::find($request->id);
return $order;
// GOOD — scope query to authenticated user
$order = Order::where('id', $request->id)
->where('user_id', auth()->id())
->firstOrFail();
# BAD
order = Order.objects.get(pk=pk)
# GOOD
order = Order.objects.get(pk=pk, user=request.user)
// BAD
const invoice = await Invoice.findByPk(req.params.id)
// GOOD
const invoice = await Invoice.findOne({
where: { id: req.params.id, userId: req.user.id }
})
user_id alone is not enough if soft-delete is used — also filter deleted_at IS NULL to prevent accessing deleted objects/users/{userId}/orders/{orderId} — verify both that the authenticated user is userId AND that the order belongs to that user/orders?ids[]=1&ids[]=2 — apply ownership filter on the entire set; never return a subset silently (either all authorized or error)| ID type | IDOR risk | Recommendation |
|---|---|---|
| Sequential integer (1, 2, 3) | HIGH — trivially enumerable | Use UUIDs for external-facing IDs |
| UUID v4 | MEDIUM — not guessable, but still must enforce ownership | Always enforce ownership; UUIDs are not access control |
| UUID v7 (time-ordered) | MEDIUM — sortable; leaks creation time | Acceptable for most use cases; enforce ownership |
| Slugs | MEDIUM — guessable if predictable pattern | Enforce ownership; avoid slug = user-controlled string |
| Indirect reference (hash map on server) | LOW | Good pattern; map user-visible token → real ID server-side |
UUIDs prevent enumeration but do NOT prevent IDOR. A leaked UUID (from a URL, log, or referrer header) is still exploitable without ownership checks.
These terms overlap — OWASP API Security Top 10 uses BOLA (Broken Object-Level Authorization):
Same root cause, same fix. When auditing APIs, use the BOLA framing from the security-checklist skill.
For every endpoint that accepts an object ID, write these tests:
| Test | Expected result |
|---|---|
| Owner accesses their own object | 200 OK |
| Authenticated user accesses another user's object | 403 Forbidden or 404 Not Found |
| Unauthenticated user accesses any object | 401 Unauthorized |
| Soft-deleted object accessed by owner | 404 Not Found |
| Bulk endpoint with mixed owned/unowned IDs | 403 or only return owned subset with explicit error |
// Example test (framework-agnostic)
it('returns 403 when user accesses another users order', async () => {
const other = await createUser()
const order = await createOrder({ userId: other.id })
const res = await request(app)
.get(`/api/orders/${order.id}`)
.set('Authorization', `Bearer ${currentUser.token}`)
expect(res.status).toBe(403)
})
| Item | Severity |
|---|---|
| Object fetched without user scope | CRITICAL |
| Sequential IDs on external-facing resource endpoints | HIGH |
| Role check present but ownership check absent | HIGH |
| Nested resource route missing parent ownership check | HIGH |
| Bulk endpoint returns unauthorized objects silently | HIGH |
| Soft-deleted records accessible via ID | MEDIUM |
| No IDOR test cases for new endpoints | MEDIUM |