Detect Insecure Direct Object Reference (IDOR) vulnerabilities in a codebase using a three-phase approach: recon (find candidates), batched verify (check authorization in parallel subagents, 3…
Install the "sast-idor" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-idor into .claude/skills/sast-idor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-idor", then confirm the skill loads.
Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Type this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-idor -a codex
Project install goes to .agents/skills/; add -g for ~/.codex/skills/.
Install the "sast-idor" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-idor into .agents/skills/sast-idor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-idor", then confirm the skill loads.
Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-idor -a cursor
Project install goes to .agents/skills/; add -g for ~/.cursor/skills/.
Install the "sast-idor" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-idor into .cursor/skills/sast-idor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-idor", then confirm the skill loads.
Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-idor -a gemini-cli
Project install goes to .agents/skills/; add -g for ~/.gemini/skills/.
Install the "sast-idor" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-idor into .gemini/skills/sast-idor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-idor", then confirm the skill loads.
Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
GitHub CLI
$ gh skill install utkusen/sast-skills sast-idor
Installs for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-idor -a github-copilot
Project install goes to .agents/skills/; add -g for ~/.copilot/skills/.
Install the "sast-idor" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-idor into .github/skills/sast-idor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-idor", then confirm the skill loads.
GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add utkusen/sast-skills --skill sast-idor -a opencode
OpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
Install the "sast-idor" agent skill from https://github.com/utkusen/sast-skills/tree/main/sast-files/.agents/skills/sast-idor into .opencode/skills/sast-idor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sast-idor", then confirm the skill loads.
OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Facts
Skill name
sast-idor
GitHub stars
1.3k
Token cost
~4.9k tokens
SKILL.md length
1,804 words
Files
1
Skills in repo
16
Repo updated
First seen
Licence
MIT
At a glance
Detect Insecure Direct Object Reference (IDOR) vulnerabilities in a codebase using a three-phase approach: recon (find candidates), batched verify (check authorization in parallel subagents, 3…
SKILL.md covers What is IDOR, Vulnerable vs. Secure Examples, Execution and Important Reminders
Needs USER_B_TOKEN
What it does
Sast Idor is an agent skill from utkusen/sast-skills. Detect Insecure Direct Object Reference (IDOR) vulnerabilities in a codebase using a three-phase approach: recon (find candidates), batched verify (check authorization in parallel subagents, 3 candidates each), and merge (consolidate batch results). Checks endpoints for missing ownership or authorization checks on user-supplied identifiers. Requires sast/architecture.md (run sast-analysis first). Outputs findings to sast/idor-results.md. Use when asked to find IDOR or authorization bypass bugs.
Its SKILL.md is about 4.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Security, covering Web application vulnerabilities, Static analysis and SAST and Authorization and RBAC. The repository describes itself as: Collection of agent skills to find vulnerabilities inside your web/mobile apps. The licence is MIT.
When your agent uses it
Asked to find IDOR
Authorization bypass bugs
Example prompts
“/sast-idor”
Requirements
Python 3
Node.js
Workflow steps
3 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit db52227. It shows what the files ask for, not the result of running them.
Tool permissions
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Runs code
No scripts in the folder and no shell commands in SKILL.md (its code samples are python, javascript, ruby, java, go, php, csharp and markdown).
From the folder's file list and the shell code blocks in SKILL.md.
Network
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Credentials
Names these keys or tokens, usually read from environment variables:
USER_B_TOKEN
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Context cost
Sast Idor loads about 4.9k tokens when it runs. Until then it costs about 127 tokens; SKILL.md has 1,804 words of instructions outside code blocks.
Always· name and description, kept in context so the agent knows when to use it
~127
When it runs· the whole SKILL.md, loaded when a task matches
~4.9k
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
Safety
Auto-check passed
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
Download SKILL.mdSave it as .claude/skills/sast-idor/SKILL.md (or your agent's skills folder).
name
sast-idor
description
Detect Insecure Direct Object Reference (IDOR) vulnerabilities in a codebase using a three-phase approach: recon (find candidates), batched verify (check authorization in parallel subagents, 3 candidates each), and merge (consolidate batch results). Checks endpoints for missing ownership or authorization checks on user-supplied identifiers. Requires sast/architecture.md (run sast-analysis first). Outputs findings to sast/idor-results.md. Use when asked to find IDOR or authorization bypass bugs.
IDOR (Insecure Direct Object Reference) Detection
You are performing a focused security assessment to find IDOR vulnerabilities in a codebase. This skill uses a three-phase approach with subagents: recon (find candidate endpoints), batched verify (check authorization in parallel batches of 3), and merge (consolidate results).
Prerequisites: sast/architecture.md must exist. Run the analysis skill first if it doesn't.
What is IDOR
IDOR occurs when an application uses a user-supplied identifier (ID, slug, filename, etc.) to directly access an object without verifying the requesting user is authorized to access that specific object. The application authenticates the user but fails to check ownership or permissions on the requested resource.
The core pattern: authenticated user A can access or modify resources belonging to user B by changing an identifier in the request.
What IDOR IS
Changing /api/orders/1001 to /api/orders/1002 and seeing another user's order
Sending DELETE /api/documents/555 to delete a document you don't own
Modifying {"account_id": 789} in a request body to transfer money from someone else's account
Changing a file download parameter ?file_id=42 to access another user's private file
Updating another user's profile via PUT /api/users/other-user-id
What IDOR is NOT
Do not flag these as IDOR:
Missing authentication: Endpoint requires no login at all → that's "Unauthenticated Access", a different class
Broken function-level access control: Regular user accessing /admin/dashboard → that's vertical privilege escalation, not IDOR
Public resources: Accessing /api/posts/123 where posts are intentionally public is not IDOR
Parameter tampering on non-object fields: Changing role=admin or price=0 in a request → that's mass assignment or business logic, not IDOR
SQL injection via ID fields: ?id=1 OR 1=1 → that's SQLi, not IDOR
Authorization Patterns That Prevent IDOR
When you see these patterns, the endpoint is likely not vulnerable:
1. Query scoped to current user (most common fix)
# The query itself ensures only the user's own records are returned
Order.objects.filter(id=order_id, user=request.user) # Django
current_user.orders.find(params[:id]) # Rails
Order.findOne({ _id: orderId, userId: req.user.id }) # Mongoose
SELECT * FROM orders WHERE id = ? AND user_id = ? # Raw SQL
2. Explicit ownership check after fetch
order = Order.find(order_id)
if order.user_id != current_user.id:
raise Forbidden
# Multi-tenant apps that scope all queries to the tenant
tenant = get_current_tenant(request)
Order.objects.filter(id=order_id, tenant=tenant)
Vulnerable vs. Secure Examples
Python — Django
python
# VULNERABLE: fetches any order by ID, no ownership check
def get_order(request, order_id):
order = Order.objects.get(id=order_id)
return JsonResponse(model_to_dict(order))
# SECURE: query scoped to requesting user
def get_order(request, order_id):
order = get_object_or_404(Order, id=order_id, user=request.user)
return JsonResponse(model_to_dict(order))
# VULNERABLE
def show
@order = Order.find(params[:id])
end
# SECURE
def show
@order = current_user.orders.find(params[:id])
end
Java — Spring Boot
java
// VULNERABLE
@GetMapping("/api/accounts/{id}")
public Account getAccount(@PathVariable Long id) {
return accountRepo.findById(id).orElseThrow();
}
// SECURE
@GetMapping("/api/accounts/{id}")
public Account getAccount(@PathVariable Long id, Authentication auth) {
Account acct = accountRepo.findById(id).orElseThrow();
if (!acct.getOwnerId().equals(auth.getName()))
throw new AccessDeniedException("Forbidden");
return acct;
}
Go
go
// VULNERABLE
func GetOrder(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
order, _ := db.GetOrder(id)
json.NewEncoder(w).Encode(order)
}
// SECURE
func GetOrder(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
userID := r.Context().Value("userID").(string)
order, _ := db.GetOrderByUser(id, userID)
json.NewEncoder(w).Encode(order)
}
PHP — Laravel
php
// VULNERABLE
public function show($id) {
return Invoice::findOrFail($id);
}
// SECURE (scoped query)
public function show($id) {
return auth()->user()->invoices()->findOrFail($id);
}
// SECURE (policy)
public function show($id) {
$invoice = Invoice::findOrFail($id);
$this->authorize('view', $invoice);
return $invoice;
}
C# — ASP.NET Core
csharp
// VULNERABLE
[HttpGet("api/profiles/{id}")]
public async Task<IActionResult> GetProfile(int id) {
var profile = await _db.Profiles.FindAsync(id);
return Ok(profile);
}
// SECURE
[HttpGet("api/profiles/{id}")]
public async Task<IActionResult> GetProfile(int id) {
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var profile = await _db.Profiles.FirstOrDefaultAsync(p => p.Id == id && p.UserId == userId);
if (profile == null) return NotFound();
return Ok(profile);
}
Execution
This skill runs in three phases using subagents. Pass the contents of sast/architecture.md to all subagents as context.
Phase 1: Recon — Find Candidate Endpoints
Launch a subagent with the following instructions:
Goal: Find every endpoint, controller action, or handler that retrieves, modifies, or deletes a specific object using a user-supplied identifier. Write results to sast/idor-recon.md.
Context: You will be given the project's architecture summary. Use it to understand the tech stack, frameworks, route definitions, and data access patterns.
What to search for:
Route definitions that contain ID parameters:
Path parameters: :id, {id}, <int:id>, [id]
Search patterns: route/path/endpoint definitions with parameter placeholders
Controller/handler methods that accept ID arguments and use them to fetch or mutate objects:
After Phase 1 completes, read sast/idor-recon.md and split the candidates into batches of up to 3 candidates each. Launch one subagent per batch in parallel. Each subagent verifies only its assigned candidates and writes results to its own batch file.
Batching procedure (you, the orchestrator, do this — not a subagent):
Read sast/idor-recon.md and count the numbered candidate sections (### 1., ### 2., etc.).
Divide them into batches of up to 3. For example, 8 candidates → 3 batches (1-3, 4-6, 7-8).
For each batch, extract the full text of those candidate sections from the recon file.
Launch all batch subagents in parallel, passing each one only its assigned candidates.
Each subagent writes to sast/idor-batch-N.md where N is the 1-based batch number.
Identify the project's primary language/framework from sast/architecture.md and select only the matching examples from the "Vulnerable vs. Secure Examples" section above. For example, if the project uses Node.js/Express with Prisma, include only the "Node.js — Express / Prisma" and "Node.js — Express / Mongoose" examples. Include these selected examples in each subagent's instructions where indicated by [TECH-STACK EXAMPLES] below.
Give each batch subagent the following instructions (substitute the batch-specific values):
Goal: Verify the following IDOR (Insecure Direct Object Reference) candidates and determine whether adequate authorization checks exist. Our goal is to find IDOR vulnerabilities. Write results to sast/idor-batch-[N].md.
Your assigned candidates (from the recon phase):
[Paste the full text of the assigned candidate sections here, preserving the original numbering]
Context: You will be given the project's architecture summary. Use it to understand the auth mechanism, middleware stack, and ORM patterns.
IDOR Reference — What to look for:
IDOR occurs when an authenticated user can access or modify resources belonging to another user by changing an identifier in the request. Focus on horizontal privilege escalation (user-to-user).
What IDOR is NOT — do not flag these as IDOR:
Missing authentication: Endpoint requires no login at all → that's "Unauthenticated Access", not IDOR
Broken function-level access control: Regular user accessing /admin/dashboard → that's vertical privilege escalation, not IDOR
Public resources: Accessing /api/posts/123 where posts are intentionally public is not IDOR
Parameter tampering on non-object fields: Changing role=admin or price=0 → that's mass assignment or business logic, not IDOR
SQL injection via ID fields: ?id=1 OR 1=1 → that's SQLi, not IDOR
Authorization patterns that PREVENT IDOR — if you see these, the endpoint is likely safe:
Query scoped to current user: The query filters by the authenticated user's ID (e.g., WHERE id = ? AND user_id = ?, current_user.orders.find(id), Order.findOne({ _id: id, userId: req.user.id }), Order.objects.filter(id=order_id, user=request.user))
Explicit ownership check after fetch: Code fetches the object then compares resource.user_id == current_user.id before returning
Tenant/organization scoping: All queries scoped to the current tenant/org
Vulnerable vs. Secure examples for this project's tech stack:
[TECH-STACK EXAMPLES]
For each candidate endpoint, check:
Is the database query scoped to the authenticated user?
Does the query include a user_id / owner_id / tenant_id filter matching the current user?
Is the query done through an association (e.g., current_user.orders.find(id))?
Is there an explicit ownership/permission check after fetching?
Does the code compare resource.user_id == current_user.id (or equivalent)?
Is there a policy/ability/authorization check?
Is there authorization middleware applied to this route?
Is there middleware that verifies object ownership before the handler runs?
Trace the middleware chain — don't assume a middleware name implies it checks ownership
For mutations (update/delete), are the same checks present?
Sometimes read endpoints are protected but write endpoints are not
Edge cases to check:
Does the auth check exist but only run conditionally (e.g., skipped for certain content types)?
Is the check present in one branch of an if/else but missing in another?
Can the check be bypassed by sending the ID in an alternative field?
Are bulk/batch endpoints checked per-item or just at the batch level?
Classification:
Vulnerable: No authorization check found for the specific object. User A can access User B's resources.
Likely Vulnerable: Auth check exists but appears incomplete, bypassable, or conditional.
Not Vulnerable: Proper authorization check is in place.
Needs Manual Review: Cannot determine with confidence (e.g., complex middleware chain, authorization happens in a service layer that's hard to trace).
Output format — write to sast/idor-batch-[N].md:
markdown
# IDOR Batch [N] Results
## Findings
### [VULNERABLE] Endpoint name
- **File**: `path/to/file.ext` (lines X-Y)
- **Endpoint**: `METHOD /path/:param`
- **Issue**: [Clear description of what's missing]
- **Impact**: [What an attacker can do — read other users' X, delete other users' Y, etc.]
- **Proof**: [Show the code path — from route to DB query — highlighting the missing check]
- **Remediation**: [Specific fix for this endpoint]
- **Dynamic Test**:
[curl command or step-by-step instructions to confirm this finding on the live app.
Include the exact endpoint, HTTP method, headers, and what to look for in the response.
Use placeholder tokens like <USER_B_TOKEN> and <USER_A_RESOURCE_ID>.]
### [LIKELY VULNERABLE] Endpoint name
- **File**: `path/to/file.ext` (lines X-Y)
- **Endpoint**: `METHOD /path/:param`
- **Issue**: [What's incomplete about the check]
- **Concern**: [Why this might still be exploitable]
- **Proof**: [Show the code path with the weak/partial check]
- **Remediation**: [Specific fix]
- **Dynamic Test**:
[curl command or step-by-step instructions to confirm this finding on the live app.
Include the exact endpoint, HTTP method, headers, and what to look for in the response.
Use placeholder tokens like <USER_B_TOKEN> and <USER_A_RESOURCE_ID>.]
After all Phase 2 batch subagents complete, read every sast/idor-batch-*.md file and merge them into a single sast/idor-results.md. You (the orchestrator) do this directly — no subagent needed.
Merge procedure:
Read all sast/idor-batch-1.md, sast/idor-batch-2.md, ... files.
Collect all findings from each batch file and combine them into one list, preserving the original classification and all detail fields.
Count totals across all batches for the executive summary.
Write the merged report to sast/idor-results.md using this format:
markdown
# IDOR Analysis Results: [Project Name]
## Executive Summary
- Candidates analyzed: [total across all batches]
- Vulnerable: [N]
- Likely Vulnerable: [N]
- Not Vulnerable: [N]
- Needs Manual Review: [N]
## Findings
[All findings from all batches, grouped by classification:
VULNERABLE first, then LIKELY VULNERABLE, then NEEDS MANUAL REVIEW, then NOT VULNERABLE.
Preserve every field from the batch results exactly as written.]
After writing sast/idor-results.md, delete all intermediate batch files (sast/idor-batch-*.md).
Important Reminders
Read sast/architecture.md and pass its content to all subagents as context.
Phase 2 must run AFTER Phase 1 completes — it depends on the recon output.
Phase 3 must run AFTER all Phase 2 batches complete — it depends on all batch outputs.
Batch size is 3 candidates per subagent. If there are 1-3 candidates total, use a single subagent. If there are 10, use 4 subagents (3+3+3+1).
Launch all batch subagents in parallel — do not run them sequentially.
Each batch subagent receives only its assigned candidates' text from the recon file, not the entire recon file. This keeps each subagent's context small and focused.
Focus on horizontal privilege escalation (user-to-user). Vertical escalation (user-to-admin) is a different skill.
When in doubt, classify as "Needs Manual Review" rather than "Not Vulnerable". False negatives are worse than false positives in security assessment.
Trace the full code path: route → middleware → controller → service → data access. Authorization can happen at any layer.
Pay attention to framework conventions. In Rails, current_user.orders.find(id) is safe. In Express, just having auth middleware doesn't mean ownership is checked.
Clean up intermediate files: delete sast/idor-recon.md and all sast/idor-batch-*.md files after the final sast/idor-results.md is written.
Sast Idor next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
Scans code with a bundled Node script for injection, secrets, XSS and other risky patterns, ranks findings by severity and checks that security decisions are documented.
Detect GraphQL injection vulnerabilities in a codebase using a three-phase approach: recon (confirm GraphQL usage and find unsafe operation document assembly sites), batched verify (trace user input…
Detect business logic vulnerabilities in a codebase using a three-phase approach: threat modeling (domain analysis and attack scenarios), batched verify (check exploitable gaps in parallel…
Detect insecure file upload vulnerabilities in a codebase using a three-phase approach: discovery (find all upload sites), batched verify (check extension bypass and related issues in parallel…
Detect Insecure Direct Object Reference (IDOR) vulnerabilities in a codebase using a three-phase approach: recon (find candidates), batched verify (check authorization in parallel subagents, 3…. Sast Idor is an agent skill from utkusen/sast-skills. Detect Insecure Direct Object Reference (IDOR) vulnerabilities in a codebase using a three-phase approach: recon (find candidates), batched verify (check authorization in parallel subagents, 3 candidates each), and merge (consolidate batch results).
Run `npx skills add utkusen/sast-skills --skill sast-idor -a claude-code`. Or copy the skill folder (sast-files/.agents/skills/sast-idor in utkusen/sast-skills) into .claude/skills/sast-idor in your project. Claude Code loads it when a task matches its description.
How do I install Sast Idor in Codex?
Run `npx skills add utkusen/sast-skills --skill sast-idor -a codex`. Or copy the skill folder (sast-files/.agents/skills/sast-idor in utkusen/sast-skills) into .agents/skills/sast-idor in your project. Codex loads it when a task matches its description.
Can I use Sast Idor in Cursor, Gemini CLI or GitHub Copilot?
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add utkusen/sast-skills --skill sast-idor -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/sast-idor, .gemini/skills/sast-idor, .github/skills/sast-idor and .opencode/skills/sast-idor in your project.
What does Sast Idor need to run?
Going by SKILL.md and its folder, Sast Idor needs credentials named USER_B_TOKEN. Our summary lists: Python 3; Node.js.
Does Sast Idor access the network?
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Is Sast Idor safe to install?
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
What licence does Sast Idor use?
Sast Idor is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
How many tokens does Sast Idor use?
About 4.9k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
What are the alternatives to Sast Idor?
Skills that share tags, products or a category with Sast Idor: Moai Ref Secops (modu-ai/moai-adk, 1.2k stars), Strix Code Vulnerability Scan (usestrix/strix, 68k stars), Security Verification Gate (fengshao1227/ccg-workflow, 5.9k stars) and Secknowledge Skill (Pa55w0rd/secknowledge-skill, 425 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Who maintains Sast Idor?
utkusen (a GitHub user) maintains it in utkusen/sast-skills, which has 1,331 GitHub stars. The repository holds 16 skills in this directory. The repository was last updated on April 8, 2026.
Source: utkusen/sast-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.