/django-access-review
Django access control and IDOR security review. Use when reviewing Django views, DRF viewsets, ORM queries, or any Python/Django code handling user authorization. Trigger keywords: "IDOR", "access control", "authorization", "Django permissions", "object permissions", "tenant
$ npx -y skills add getsentry/sentry-skills --skill django-access-review --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/django-access-review
Context preview
The summary Claude sees to decide when to auto-load this skill.
Django access control and IDOR security review. Use when reviewing Django views, DRF viewsets, ORM queries, or any Python/Django code handling user authorization. Trigger keywords: "IDOR", "access control", "authorization", "Django permissions", "object permissions", "tenant
SKILL.md
django-access-review.SKILL.mdname: django-access-review
description: 'Django access control and IDOR security review. Use when reviewing Django views, DRF viewsets, ORM queries, or any Python/Django code handling user authorization. Trigger keywords: "IDOR", "access control", "authorization", "Django permissions", "object permissions", "tenant isolation", "broken access".'
allowed-tools: Read, Grep, Glob, Bash, Task
license: LICENSE
<!-- Reference material based on OWASP Cheat Sheet Series (CC BY-SA 4.0) https://cheatsheetseries.owasp.org/ -->
Django Access Control & IDOR Review
Find access control vulnerabilities by investigating how the codebase answers one question:
**Can User A access, modify, or delete User B's data?**
Philosophy: Investigation Over Pattern Matching
Do NOT scan for predefined vulnerable patterns. Instead:
1. **Understand** how authorization works in THIS codebase 2. **Ask questions** about specific data flows 3. **Trace code** to find where (or if) access checks happen 4. **Report** only what you've confirmed through investigation
Every codebase implements authorization differently. Your job is to understand this specific implementation, then find gaps.
---
Phase 1: Understand the Authorization Model
Before looking for bugs, answer these questions about the codebase:
How is authorization enforced?
Research the codebase to find:
□ Where are permission checks implemented?
- Decorators? (@login_required, @permission_required, custom?)
- Middleware? (TenantMiddleware, AuthorizationMiddleware?)
- Base classes? (BaseAPIView, TenantScopedViewSet?)
- Permission classes? (DRF permission_classes?)
- Custom mixins? (OwnershipMixin, TenantMixin?)
□ How are queries scoped?
- Custom managers? (TenantManager, UserScopedManager?)
- get_queryset() overrides?
- Middleware that sets query context?
□ What's the ownership model?
- Single user ownership? (document.owner_id)
- Organization/tenant ownership? (document.organization_id)
- Hierarchical? (org -> team -> user -> resource)
- Role-based within context? (org admin vs member)
Investigation commands
# Find how auth is typically done
grep -rn "permission_classes\|@login_required\|@permission_required" --include="*.py" | head -20
# Find base classes that views inherit from
grep -rn "class Base.*View\|class.*Mixin.*:" --include="*.py" | head -20
# Find custom managers
grep -rn "class.*Manager\|def get_queryset" --include="*.py" | head -20
# Find ownership fields on models
grep -rn "owner\|user_id\|organization\|tenant" --include="models.py" | head -30
**Do not proceed until you understand the authorization model.**
---
Phase 2: Map the Attack Surface
Identify endpoints that handle user-specific data:
What resources exist?
□ What models contain user data?
□ Which have ownership fields (owner_id, user_id, organization_id)?
□ Which are accessed via ID in URLs or request bodies?
What operations are exposed?
For each resource, map:
- List endpoints - what data is returned?
- Detail/retrieve endpoints - how is the object fetched?
- Create endpoints - who sets the owner?
- Update endpoints - can users modify others' data?
- Delete endpoints - can users delete others' data?
- Custom actions - what do they access?
---
Phase 3: Ask Questions and Investigate
For each endpoint that handles user data, ask:
The Core Question
**"If I'm User A and I know the ID of User B's resource, can I access it?"**
Trace the code to answer this:
1. Where does the resource ID enter the system?
- URL path: /api/documents/{id}/
- Query param: ?document_id=123
- Request body: {"document_id": 123}
2. Where is that ID used to fetch data?
- Find the ORM query or database call
3. Between (1) and (2), what checks exist?
- Is the query scoped to current user?
- Is there an explicit ownership check?
- Is there a permission check on the object?
- Does a base class or mixin enforce access?
4. If you can't find a check, is there one you missed?
- Check parent classes
- Check middleware
- Check managers
- Check decorators at URL levelFollow-Up Questions
□ For list endpoints: Does the query filter to user's data, or return everything?
□ For create endpoints: Who sets the owner - the server or the request?
□ For bulk operations: Are they scoped to user's data?
□ For related resources: If I can access a document, can I access its comments?
What if the document belongs to someone else?
□ For tenant/org resources: Can User in Org A access Org B's data by changing
the org_id in the URL?
---
Phase 4: Trace Specific Flows
Pick a concrete endpoint and trace it completely.
Example Investigation
Endpoint: GET /api/documents/{pk}/
1. Find the view handling this URL
→ DocumentViewSet.retrieve() in api/views.py
2. Check what DocumentViewSet inherits from
→ class DocumentViewSet(viewsets.ModelViewSet)
→ No custom base class with authorization
3. Check permission_classes
→ permission_classes = [IsAuthenticated]
→ Only checks login, not ownership
4. Check get_queryset()
→ def get_queryset(self):
→ return Document.objects.all()
→ Returns ALL documents!
5. Check for has_object_permission()
→ Not implemented
6. Check retrieve() method
→ Uses default, which calls get_object()
→ get_object() uses get_queryset(), which returns all
7. Conclusion: IDOR - Any authenticated user can access any documentWhat to look for when tracing
Potential gap indicators (investigate further, don't auto-flag):
- get_queryset() returns .all() or filters without user
- Direct Model.objects.get(pk=pk) without ownership in query
- ID comes from request body for sensitive operations
- Permission class checks auth but not ownership
- No has_object_permission() and queryset isn't scoped
Likely safe patterns (but verify the implementation):
- get_queryset() filters by request.user or us
Read more
name: django-access-review description: 'Django access control and IDOR security review. Use when reviewing Django views, DRF viewsets, ORM queries, or any Python/Django code handling user authorization. Trigger keywords: "IDOR", "access control", "authorization", "Django permissions", "object permissions", "tenant isolation", "broken access".' allowed-tools: Read, Grep, Glob, Bash, Task license: LICENSE
<!-- Reference material based on OWASP Cheat Sheet Series (CC BY-SA 4.0) https://cheatsheetseries.owasp.org/ -->
Django Access Control & IDOR Review
Find access control vulnerabilities by investigating how the codebase answers one question:
**Can User A access, modify, or delete User B's data?**
Philosophy: Investigation Over Pattern Matching
Do NOT scan for predefined vulnerable patterns. Instead:
1. **Understand** how authorization works in THIS codebase 2. **Ask questions** about specific data flows 3. **Trace code** to find where (or if) access checks happen 4. **Report** only what you've confirmed through investigation
Every codebase implements authorization differently. Your job is to understand this specific implementation, then find gaps.
---
Phase 1: Understand the Authorization Model
Before looking for bugs, answer these questions about the codebase:
How is authorization enforced?
Research the codebase to find:
□ Where are permission checks implemented? - Decorators? (@login_required, @permission_required, custom?) - Middleware? (TenantMiddleware, AuthorizationMiddleware?) - Base classes? (BaseAPIView, TenantScopedViewSet?) - Permission classes? (DRF permission_classes?) - Custom mixins? (OwnershipMixin, TenantMixin?) □ How are queries scoped? - Custom managers? (TenantManager, UserScopedManager?) - get_queryset() overrides? - Middleware that sets query context? □ What's the ownership model? - Single user ownership? (document.owner_id) - Organization/tenant ownership? (document.organization_id) - Hierarchical? (org -> team -> user -> resource) - Role-based within context? (org admin vs member)
Investigation commands
# Find how auth is typically done grep -rn "permission_classes\|@login_required\|@permission_required" --include="*.py" | head -20 # Find base classes that views inherit from grep -rn "class Base.*View\|class.*Mixin.*:" --include="*.py" | head -20 # Find custom managers grep -rn "class.*Manager\|def get_queryset" --include="*.py" | head -20 # Find ownership fields on models grep -rn "owner\|user_id\|organization\|tenant" --include="models.py" | head -30
**Do not proceed until you understand the authorization model.**
---
Phase 2: Map the Attack Surface
Identify endpoints that handle user-specific data:
What resources exist?
□ What models contain user data? □ Which have ownership fields (owner_id, user_id, organization_id)? □ Which are accessed via ID in URLs or request bodies?
What operations are exposed?
For each resource, map:
- List endpoints - what data is returned?
- Detail/retrieve endpoints - how is the object fetched?
- Create endpoints - who sets the owner?
- Update endpoints - can users modify others' data?
- Delete endpoints - can users delete others' data?
- Custom actions - what do they access?
---
Phase 3: Ask Questions and Investigate
For each endpoint that handles user data, ask:
The Core Question
**"If I'm User A and I know the ID of User B's resource, can I access it?"**
Trace the code to answer this:
1. Where does the resource ID enter the system?
- URL path: /api/documents/{id}/
- Query param: ?document_id=123
- Request body: {"document_id": 123}
2. Where is that ID used to fetch data?
- Find the ORM query or database call
3. Between (1) and (2), what checks exist?
- Is the query scoped to current user?
- Is there an explicit ownership check?
- Is there a permission check on the object?
- Does a base class or mixin enforce access?
4. If you can't find a check, is there one you missed?
- Check parent classes
- Check middleware
- Check managers
- Check decorators at URL levelFollow-Up Questions
□ For list endpoints: Does the query filter to user's data, or return everything? □ For create endpoints: Who sets the owner - the server or the request? □ For bulk operations: Are they scoped to user's data? □ For related resources: If I can access a document, can I access its comments? What if the document belongs to someone else? □ For tenant/org resources: Can User in Org A access Org B's data by changing the org_id in the URL?
---
Phase 4: Trace Specific Flows
Pick a concrete endpoint and trace it completely.
Example Investigation
Endpoint: GET /api/documents/{pk}/
1. Find the view handling this URL
→ DocumentViewSet.retrieve() in api/views.py
2. Check what DocumentViewSet inherits from
→ class DocumentViewSet(viewsets.ModelViewSet)
→ No custom base class with authorization
3. Check permission_classes
→ permission_classes = [IsAuthenticated]
→ Only checks login, not ownership
4. Check get_queryset()
→ def get_queryset(self):
→ return Document.objects.all()
→ Returns ALL documents!
5. Check for has_object_permission()
→ Not implemented
6. Check retrieve() method
→ Uses default, which calls get_object()
→ get_object() uses get_queryset(), which returns all
7. Conclusion: IDOR - Any authenticated user can access any documentWhat to look for when tracing
Potential gap indicators (investigate further, don't auto-flag): - get_queryset() returns .all() or filters without user - Direct Model.objects.get(pk=pk) without ownership in query - ID comes from request body for sensitive operations - Permission class checks auth but not ownership - No has_object_permission() and queryset isn't scoped Likely safe patterns (but verify the implementation): - get_queryset() filters by request.user or us
For skills to help set up Sentry in your project or debug production issues, see Agent skills for Sentry employees, following the Agent Skills open format.
Repo: getsentry/sentry-skills
Other skills on sentry-skills.
- /agents-md
Creates and maintains concise AGENTS.md and CLAUDE.md project instruction files. Use when asked to create AGENTS.md, update AGENTS.md, maintain agent docs, set up CLAUDE.md, document repository agent conventions, or keep coding-agent instructions minimal and reference-backed.
Open skill - /blog-writing-guide
Write, review, and improve blog posts for the Sentry engineering blog following Sentry's specific writing standards, voice, and quality bar. Use this skill whenever someone asks to write a blog post, draft a technical article, review blog content, improve a draft, write a
Open skill - /brand-guidelines
Write copy following Sentry brand guidelines. Use when writing UI text, error messages, empty states, onboarding flows, 404 pages, documentation, marketing copy, or any user-facing content. Covers both Plain Speech (default) and Sentry Voice tones.
Open skill - /claude-settings-audit
Analyze a repository to generate recommended Claude Code settings.json permissions. Use when setting up a new project, auditing existing settings, or determining which read-only bash commands to allow. Detects tech stack, build tools, and monorepo structure.
Open skill - /code-review
Perform code reviews following Sentry engineering practices. Use when reviewing pull requests, examining code changes, or providing feedback on code quality. Covers security, performance, testing, and design review.
Open skill - /code-simplifier
Simplifies and refines code for clarity, consistency, and maintainability while preserving all functionality. Use when asked to "simplify code", "clean up code", "refactor for clarity", "improve readability", or review recently modified code for elegance. Focuses on
Open skill

